KiCad PCB EDA Suite
unit_test_utils.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
24#ifndef UNIT_TEST_UTILS__H
25#define UNIT_TEST_UTILS__H
26
27#define BOOST_NO_AUTO_PTR
28
29#include <boost/test/unit_test.hpp>
30#include <turtle/mock.hpp>
31
33
34#include <functional>
35#include <set>
36
37#include <wx/gdicmn.h>
47#if BOOST_VERSION >= 105900
48#define HAVE_EXPECTED_FAILURES
49#endif
50
60#undef BOOST_TEST
61
62
63#if BOOST_VERSION < 105900
64
65/*
66 * BOOST_TEST_INFO is not available before 1.59. It's not critical for
67 * test pass/fail, it's just info, so just pass along to a logging
68 * function.
69 *
70 * This can be removed when our minimum boost version is 1.59 or higher.
71 */
72#define BOOST_TEST_INFO( A ) BOOST_TEST_MESSAGE( A )
73
74/*
75 *
76 * BOOST_TEST_CONTEXT provides scoped info, but again, only after 1.59.
77 * Replacing with a call to BOOST_TEST_MESSAGE will work, and the
78 * scoping will still work for newer boosts.
79 *
80 * This can be removed when our minimum boost version is 1.59 or higher.
81 */
82#define BOOST_TEST_CONTEXT( A ) BOOST_TEST_MESSAGE( A );
83
84#endif
85
86/*
87 * Boost hides the configuration point for print_log_value in different
88 * namespaces between < 1.59 and >= 1.59.
89 *
90 * The macros can be used to open and close the right level of namespacing
91 * based on the version.
92 *
93 * We could just use a conditionally defined namespace alias, but that
94 * doesn't work in GCC <7 (GCC bug #56480)
95 *
96 * From Boost 1.64, this should be done with boost_test_print_type,
97 * and these defines can be removed once all logging functions use that.
98 */
99#if BOOST_VERSION >= 105900
100#define BOOST_TEST_PRINT_NAMESPACE_OPEN \
101 boost \
102 { \
103 namespace test_tools \
104 { \
105 namespace tt_detail
106#define BOOST_TEST_PRINT_NAMESPACE_CLOSE }}
107#else
108#define BOOST_TEST_PRINT_NAMESPACE_OPEN \
109 boost \
110 { \
111 namespace test_tools
112#define BOOST_TEST_PRINT_NAMESPACE_CLOSE }
113#endif
114
121#if BOOST_VERSION < 106400
122
124{
125template <>
126struct print_log_value<std::nullptr_t>
127{
128 inline void operator()( std::ostream& os, std::nullptr_t const& p )
129 {
130 os << "nullptr";
131 }
132};
133}
135
136#endif
137
138
140{
141
145template <typename T>
146struct print_log_value<std::vector<T>>
147{
148 inline void operator()( std::ostream& os, std::vector<T> const& aVec )
149 {
150 os << "std::vector size " << aVec.size() << "[";
151
152 for( const auto& i : aVec )
153 {
154 os << "\n ";
155 print_log_value<T>()( os, i );
156 }
157
158 os << "]";
159 }
160};
161
166template <>
167struct print_log_value<wxPoint>
168{
169 void operator()( std::ostream& os, wxPoint const& aVec );
170};
171}
173
174
175namespace KI_TEST
176{
177
178template <typename EXP_CONT> using EXP_OBJ = typename EXP_CONT::value_type;
179template <typename FOUND_CONT> using FOUND_OBJ = typename FOUND_CONT::value_type;
180
197template <typename EXP_OBJ, typename FOUND_OBJ>
198using MATCH_PRED = std::function<bool( const EXP_OBJ&, const FOUND_OBJ& )>;
199
234template <typename EXP_CONT, typename FOUND_CONT, typename MATCH_PRED>
235void CheckUnorderedMatches( const EXP_CONT& aExpected, const FOUND_CONT& aFound,
236 MATCH_PRED aMatchPredicate )
237{
238 using EXP_OBJ = typename EXP_CONT::value_type;
239
240 // set of object we've already found
241 std::set<const EXP_OBJ*> matched;
242
243 // fill the set of object that match
244 for( const auto& found : aFound )
245 {
246 for( const auto& expected : aExpected )
247 {
248 if( aMatchPredicate( expected, found ) )
249 {
250 matched.insert( &expected );
251 break;
252 }
253 }
254 }
255
256 // first check every expected object was "found"
257 for( const EXP_OBJ& exp : aExpected )
258 {
259 BOOST_CHECK_MESSAGE( matched.count( &exp ) > 0, "Expected item was not found. Expected: \n"
260 << exp );
261 }
262
263 // check every "found" object was expected
264 for( const EXP_OBJ* found : matched )
265 {
266 const bool was_expected = std::find_if( aExpected.begin(), aExpected.end(),
267 [found]( const EXP_OBJ& aObj )
268 {
269 return &aObj == found;
270 } ) != aExpected.end();
271
272 BOOST_CHECK_MESSAGE( was_expected, "Found item was not expected. Found: \n" << *found );
273 }
274}
275
276
280template <typename T>
281bool CollectionHasNoDuplicates( const T& aCollection )
282{
283 T sorted = aCollection;
284 std::sort( sorted.begin(), sorted.end() );
285
286 return std::adjacent_find( sorted.begin(), sorted.end() ) == sorted.end();
287}
288
289
296#ifdef DEBUG
297#define CHECK_WX_ASSERT( STATEMENT ) BOOST_CHECK_THROW( STATEMENT, KI_TEST::WX_ASSERT_ERROR );
298#else
299#define CHECK_WX_ASSERT( STATEMENT )
300#endif
301
302} // namespace KI_TEST
303
304#endif // UNIT_TEST_UTILS__H
Before Boost 1.64, nullptr_t wasn't handled.
void CheckUnorderedMatches(const EXP_CONT &aExpected, const FOUND_CONT &aFound, MATCH_PRED aMatchPredicate)
Check that a container of "found" objects matches a container of "expected" objects.
bool CollectionHasNoDuplicates(const T &aCollection)
Predicate to check a collection has no duplicate elements.
std::function< bool(const EXP_OBJ &, const FOUND_OBJ &)> MATCH_PRED
A match predicate: check that a "found" object is equivalent to or represents an "expected" object,...
typename FOUND_CONT::value_type FOUND_OBJ
typename EXP_CONT::value_type EXP_OBJ
Definition: bitmap.cpp:65
void operator()(std::ostream &os, std::nullptr_t const &p)
void operator()(std::ostream &os, std::vector< T > const &aVec)
VECTOR3I expected(15, 30, 45)
#define BOOST_TEST_PRINT_NAMESPACE_CLOSE