diff --git a/Documentation/development/testing.md b/Documentation/development/testing.md index 0b47d13a1e..81fd227013 100644 --- a/Documentation/development/testing.md +++ b/Documentation/development/testing.md @@ -70,6 +70,50 @@ messages inside tested functions (i.e. where you don't have access to the Boost unit test headers). These will always be printed, so take care to remove them before committing, or they'll show up when KiCad runs normally! +### Expected failures {#expected-failures} + +Sometimes, it is helpful to check in tests that do not pass. However, it is bad +practise to intentionally check in commits that break builds (which is what +happens if you cause `make test` to fail). + +Boost provides a method of declaring that some specific tests are allowed to fail. +This syntax is not consistently available in all supported Boost versions, so you +should use the following construct: + +``` +#include + +// On platforms with older boosts, the test will be excluded entirely +#ifdef HAVE_EXPECTED_FAILURES + +// Declare a test case with 1 "allowed" failure (out of 2, in this case) +BOOST_AUTO_TEST_CASE( SomeTest, *boost::unit_test::expected_failures( 1 ) ) +{ + BOOST_CHECK_EQUAL( 1, 1 ); + + // This check fails, but does not cause a test suite failure + BOOST_CHECK_EQUAL( 1, 2 ); + + // Further failures *would* be a test suit failure +} + +#endif +``` + +When run, this produces output somewhat like this: + +``` +qa/common/test_mytest.cpp(123): error: in "MyTests/SomeTest": check 1 == 2 has failed [1 != 2 +*** No errors detected +``` + +And the unit test executable returns `0` (success). + +Checking in a failing test is a strictly temporary situation, used to illustrate +the triggering of a bug prior to fixing it. This is advantageous, not only from +a "project history" perspective, but also to ensure that the test you write to +catch the bug in question does, in fact, catch the bug in the first place. + ## Python modules {#python-tests} The Pcbnew Python modules have some test programs in the `qa` directory. diff --git a/qa/CMakeLists.txt b/qa/CMakeLists.txt index ae30e1a38b..086bf144d8 100644 --- a/qa/CMakeLists.txt +++ b/qa/CMakeLists.txt @@ -14,6 +14,7 @@ endif() # common QA helpers add_subdirectory( qa_utils ) +add_subdirectory( unit_test_utils ) add_subdirectory( common ) add_subdirectory( shape_poly_set_refactor ) diff --git a/qa/common/CMakeLists.txt b/qa/common/CMakeLists.txt index ad17eeaab6..f6a7298cc0 100644 --- a/qa/common/CMakeLists.txt +++ b/qa/common/CMakeLists.txt @@ -19,12 +19,8 @@ # or you may write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA -find_package(Boost COMPONENTS unit_test_framework REQUIRED) find_package( wxWidgets 3.0.0 COMPONENTS gl aui adv html core net base xml stc REQUIRED ) - -add_definitions(-DBOOST_TEST_DYN_LINK) - add_executable( qa_common # This is needed for the global mock objects common_mocks.cpp @@ -39,6 +35,7 @@ add_executable( qa_common ../../common/colors.cpp ../../common/observable.cpp + test_color4d.cpp test_hotkey_store.cpp test_title_block.cpp test_utf8.cpp @@ -50,7 +47,6 @@ include_directories( ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/polygon - ${Boost_INCLUDE_DIR} ${INC_AFTER} ) @@ -60,7 +56,8 @@ target_link_libraries( qa_common polygon bitmaps gal - ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} + qa_utils + unit_test_utils ${wxWidgets_LIBRARIES} ) diff --git a/qa/common/geometry/geom_test_utils.h b/qa/common/geometry/geom_test_utils.h index d598a24df1..5f79edc688 100644 --- a/qa/common/geometry/geom_test_utils.h +++ b/qa/common/geometry/geom_test_utils.h @@ -26,55 +26,18 @@ #include +#include +#include +#include + +#include + /** * @brief Utility functions for testing geometry functions. */ namespace GEOM_TEST { -/** - * @brief Check if a value is within a tolerance of a nominal value - * -* @return value is in [aNominal - aError, aNominal + aError] - */ -template -bool IsWithin( T aValue, T aNominal, T aError ) -{ - return ( aValue >= aNominal - aError ) - && ( aValue <= aNominal + aError ); -} - -/** - * @brief Check if a value is within a tolerance of a nominal value, - * with different allowances for errors above and below. - * - * @return value is in [aNominal - aErrorBelow, aNominal + aErrorAbove] - */ -template -bool IsWithin( T aValue, T aNominal, T aErrorAbove, T aErrorBelow ) -{ - return ( aValue >= aNominal - aErrorBelow ) - && ( aValue <= aNominal + aErrorAbove ); -} - -/** - * @brief value is in range [aNominal - aErrorBelow, aNominal] - */ -template -bool IsWithinAndBelow( T aValue, T aNominal, T aErrorBelow ) -{ - return IsWithin( aValue, aNominal, 0, aErrorBelow ); -} - -/** - * @brief value is in range [aNominal, aNominal + aErrorAbove] - */ -template -bool IsWithinAndAbove( T aValue, T aNominal, T aErrorAbove ) -{ - return IsWithin( aValue, aNominal, aErrorAbove, 0 ); -} - /** * @brief Geometric quadrants, from top-right, anti-clockwise * @@ -163,7 +126,7 @@ bool ArePerpendicular( const VECTOR2& a, const VECTOR2& b, double aToleran angle -= M_PI; } - return IsWithin( angle, M_PI / 2.0, aTolerance ); + return KI_TEST::IsWithin( angle, M_PI / 2.0, aTolerance ); } /** diff --git a/qa/common/geometry/test_fillet.cpp b/qa/common/geometry/test_fillet.cpp index 119db6b198..a3521d09ef 100644 --- a/qa/common/geometry/test_fillet.cpp +++ b/qa/common/geometry/test_fillet.cpp @@ -24,6 +24,8 @@ #include #include +#include + #include #include @@ -51,26 +53,24 @@ BOOST_FIXTURE_TEST_SUITE( Fillet, FilletFixture ) void TestFilletSegmentConstraints( const SEG& aSeg, VECTOR2I aRadCentre, int aRadius, int aError ) { - using namespace GEOM_TEST; - const auto diffA = aRadCentre - aSeg.A; const auto diffB = aRadCentre - aSeg.B; const auto diffC = aRadCentre - aSeg.Center(); // Check 1: radii (error of 1 for rounding) - BOOST_CHECK_PREDICATE( IsWithinAndBelow, - ( diffA.EuclideanNorm() )( aRadius )( 1 ) ); - BOOST_CHECK_PREDICATE( IsWithinAndBelow, - ( diffB.EuclideanNorm() )( aRadius )( 1 ) ); + BOOST_CHECK_PREDICATE( + KI_TEST::IsWithinAndBelow, ( diffA.EuclideanNorm() )( aRadius )( 1 ) ); + BOOST_CHECK_PREDICATE( + KI_TEST::IsWithinAndBelow, ( diffB.EuclideanNorm() )( aRadius )( 1 ) ); // Check 2: Mid-point error - BOOST_CHECK_PREDICATE( IsWithinAndBelow, - ( diffC.EuclideanNorm() )( aRadius )( aError + 1 ) ); + BOOST_CHECK_PREDICATE( + KI_TEST::IsWithinAndBelow, ( diffC.EuclideanNorm() )( aRadius )( aError + 1 ) ); // Check 3: Mid-point -> radius centre perpendicular const auto perpendularityMaxError = ( M_PI / 2 ) / 10; - BOOST_CHECK_PREDICATE( ArePerpendicular, - ( diffC )( aSeg.A - aSeg.B )( perpendularityMaxError ) ); + BOOST_CHECK_PREDICATE( GEOM_TEST::ArePerpendicular, + ( diffC )( aSeg.A - aSeg.B )( perpendularityMaxError ) ); } diff --git a/qa/common/test_color4d.cpp b/qa/common/test_color4d.cpp new file mode 100644 index 0000000000..940fb0ad1d --- /dev/null +++ b/qa/common/test_color4d.cpp @@ -0,0 +1,289 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2018 KiCad Developers, see CHANGELOG.TXT for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include +#include + +#include + +#ifdef WX_COMPATIBILITY +#include +#endif + +// All these tests are of a class in KIGFX +using namespace KIGFX; + + +/** + * Checks if a COLOR4D is close enough to another + */ +bool pred_colour_is_near( const COLOR4D& aCol, const COLOR4D aOther, double aTol ) +{ + return KI_TEST::IsWithin( aCol.r, aOther.r, aTol ) + && KI_TEST::IsWithin( aCol.g, aOther.g, aTol ) + && KI_TEST::IsWithin( aCol.b, aOther.b, aTol ) + && KI_TEST::IsWithin( aCol.a, aOther.a, aTol ); +} + +/** + * Checks if a COLOR4D is close enough to a given RGB char value + */ +bool pred_colour_is_near_hex( + const COLOR4D& aCol, unsigned char r, unsigned char g, unsigned char b, unsigned char a ) +{ + const double tol = 0.5 / 255.0; // One bit of quantised error + + return KI_TEST::IsWithin( aCol.r, r / 255.0, tol ) + && KI_TEST::IsWithin( aCol.g, g / 255.0, tol ) + && KI_TEST::IsWithin( aCol.b, b / 255.0, tol ) + && KI_TEST::IsWithin( aCol.a, a / 255.0, tol ); +} + + +/** + * Declares a struct as the Boost test fixture. + */ +BOOST_AUTO_TEST_SUITE( Color4D ) + + +/** + * Check basic setting and getting of values + */ +BOOST_AUTO_TEST_CASE( BasicOps ) +{ + const auto c = COLOR4D{ 0.4, 0.5, 0.6, 0.7 }; + + BOOST_CHECK_EQUAL( c.r, 0.4 ); + BOOST_CHECK_EQUAL( c.g, 0.5 ); + BOOST_CHECK_EQUAL( c.b, 0.6 ); + BOOST_CHECK_EQUAL( c.a, 0.7 ); + + const auto copied = c; + + // Test equality + BOOST_CHECK_EQUAL( c, copied ); + + const auto c2 = COLOR4D{ 0.1, 0.2, 0.3, 0.4 }; + + // Test inequality + BOOST_CHECK_NE( c, c2 ); +} + + +/** + * Test case data for a test that takes a colour and a scalar factor + * and returns a result. + */ +struct COLOR_SCALAR_CASE +{ + COLOR4D start; + double factor; + COLOR4D expected; +}; + + +/** + * Check inversion + */ +BOOST_AUTO_TEST_CASE( Invert ) +{ + // Inverts RGB, A is the same + static const std::vector cases = { + { { 0.0, 0.25, 1.0, 1.0 }, 0.0, { 1.0, 0.75, 0.0, 1.0 } }, + }; + + for( const auto& c : cases ) + { + auto col = c.start; + + const auto inverted = col.Inverted(); + BOOST_CHECK_EQUAL( inverted, c.expected ); + + // Test in-place function + col.Invert(); + BOOST_CHECK_EQUAL( col, c.expected ); + } +} + + +/** + * Check inversion + */ +BOOST_AUTO_TEST_CASE( Brighten ) +{ + static const std::vector cases = { + { { 0.0, 0.0, 0.0, 1.0 }, 0.5, { 0.5, 0.5, 0.5, 1.0 } }, + { { 0.0, 0.5, 1.0, 1.0 }, 0.5, { 0.5, 0.75, 1.0, 1.0 } }, + }; + + for( const auto& c : cases ) + { + auto col = c.start; + + const auto brightened = col.Brightened( c.factor ); + BOOST_CHECK_EQUAL( brightened, c.expected ); + + // Test in-place function + col.Brighten( c.factor ); + BOOST_CHECK_EQUAL( col, c.expected ); + } +} + + +/** + * Check darken + */ +BOOST_AUTO_TEST_CASE( Darken ) +{ + static const std::vector cases = { + { { 0.0, 0.0, 0.0, 1.0 }, 0.5, { 0.0, 0.0, 0.0, 1.0 } }, + { { 1.0, 1.0, 1.0, 1.0 }, 0.5, { 0.5, 0.5, 0.5, 1.0 } }, + }; + + for( const auto& c : cases ) + { + auto col = c.start; + + const auto brightened = col.Darkened( c.factor ); + BOOST_CHECK_EQUAL( brightened, c.expected ); + + // Test in-place function + col.Darken( c.factor ); + BOOST_CHECK_EQUAL( col, c.expected ); + } +} + + +/** + * Check alpha setting + */ +BOOST_AUTO_TEST_CASE( WithAlpha ) +{ + static const std::vector cases = { + { { 0.0, 0.0, 0.0, 1.0 }, 0.5, { 0.0, 0.0, 0.0, 0.5 } }, + { { 0.0, 0.5, 1.0, 1.0 }, 0.5, { 0.0, 0.5, 1.0, 0.5 } }, + }; + + for( const auto& c : cases ) + { + auto col = c.start; + + const auto with_alpha = col.WithAlpha( c.factor ); + BOOST_CHECK_EQUAL( with_alpha, c.expected ); + } + + // Note: If COLOR4D::WithAlpha raised an exception, we could check + // the bounds-checking with BOOST_REQUIRE_THROW, + // but it assert()s, so we can't. +} + +struct FROM_HSV_TO_HEX_CASE +{ + double h; + double s; + double v; + unsigned char r; + unsigned char g; + unsigned char b; +}; + + +/** + * Check FromHSV + */ +BOOST_AUTO_TEST_CASE( FromHsv ) +{ + static const std::vector cases = { + { 90.0, 0.5, 0.5, 96, 128, 64 }, + }; + + for( const auto& c : cases ) + { + auto col = COLOR4D{}; + col.FromHSV( c.h, c.s, c.v ); + const unsigned char alpha = 0xFF; + + BOOST_CHECK_PREDICATE( pred_colour_is_near_hex, ( col )( c.r )( c.g )( c.b )( alpha ) ); + } +} + + +#ifdef WX_COMPATIBILITY + +struct WX_CONV_CASE +{ + wxColour wx; + COLOR4D c4d; +}; + + +static std::vector wx_conv_cases = { + { { 0x00, 0x00, 0x00, 0x00 }, { 0.0, 0.0, 0.0, 0.0 } }, + { { 0x66, 0x80, 0x99, 0xB3 }, { 0.4, 0.5, 0.6, 0.7 } }, + { { 0xFF, 0xFF, 0xFF, 0xFF }, { 1.0, 1.0, 1.0, 1.0 } }, + { { 0xFF, 0x00, 0x00, 0xFF }, { 0.999, 0.001, 0.0, 1.0 } }, +}; + +#ifdef HAVE_EXPECTED_FAILURES + +/** + * Check conversion to WxColour + */ +BOOST_AUTO_TEST_CASE( ToWx, *boost::unit_test::expected_failures( 3 ) ) +{ + for( const auto& c : wx_conv_cases ) + { + wxColour wx_col = c.c4d.ToColour(); + + // A hack, but avoids having to define a custom operator<< + BOOST_CHECK_EQUAL( wx_col.Red(), c.wx.Red() ); + BOOST_CHECK_EQUAL( wx_col.Green(), c.wx.Green() ); + BOOST_CHECK_EQUAL( wx_col.Blue(), c.wx.Blue() ); + BOOST_CHECK_EQUAL( wx_col.Alpha(), c.wx.Alpha() ); + } +} + +#endif // HAVE_EXPECTED_FAILURES + + +/** + * Check conversion from WxColour + */ +BOOST_AUTO_TEST_CASE( FromWx ) +{ + const double tol = 0.5 / 255.0; // One bit of quantised error + + for( const auto& c : wx_conv_cases ) + { + const auto col = COLOR4D{ c.wx }; + + BOOST_CHECK_PREDICATE( pred_colour_is_near, ( col )( c.c4d )( tol ) ); + } +} + +#endif // WX_COMPATIBILITY + +BOOST_AUTO_TEST_SUITE_END() diff --git a/qa/unit_test_utils/CMakeLists.txt b/qa/unit_test_utils/CMakeLists.txt new file mode 100644 index 0000000000..3fbfa05b86 --- /dev/null +++ b/qa/unit_test_utils/CMakeLists.txt @@ -0,0 +1,47 @@ +# This program source code file is part of KiCad, a free EDA CAD application. +# +# Copyright (C) 2018 KiCad Developers, see CHANGELOG.TXT for contributors. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, you may find one here: +# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html +# or you may search the http://www.gnu.org website for the version 2 license, +# or you may write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# The unit_test_utils library is a simple helper library to collate +# utilities that are generically useful for unit test executables. +# +# Code that is useful for QA purposes outside of the unit-testing context +# belongs in qa_utils. + +find_package(Boost COMPONENTS unit_test_framework REQUIRED) + +set(SRCS + unit_test_utils.cpp +) + +add_library( unit_test_utils STATIC ${SRCS} ) + +target_link_libraries( unit_test_utils PUBLIC + ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} +) + +target_include_directories( unit_test_utils PUBLIC + include + ${Boost_INCLUDE_DIR} +) + +target_compile_definitions( unit_test_utils PUBLIC + BOOST_TEST_DYN_LINK +) \ No newline at end of file diff --git a/qa/unit_test_utils/include/unit_test_utils/numeric.h b/qa/unit_test_utils/include/unit_test_utils/numeric.h new file mode 100644 index 0000000000..cfda976f1d --- /dev/null +++ b/qa/unit_test_utils/include/unit_test_utils/numeric.h @@ -0,0 +1,74 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/** + * @file numeric.h + * Numerical test predicates. + */ + +#ifndef NUMERIC__H +#define NUMERIC__H + +namespace KI_TEST +{ + +/** + * Check if a value is within a tolerance of a nominal value + * + * @return value is in [aNominal - aError, aNominal + aError] + */ +template bool IsWithin( T aValue, T aNominal, T aError ) +{ + return ( aValue >= aNominal - aError ) && ( aValue <= aNominal + aError ); +} + +/** + * Check if a value is within a tolerance of a nominal value, + * with different allowances for errors above and below. + * + * @return value is in [aNominal - aErrorBelow, aNominal + aErrorAbove] + */ +template bool IsWithinBounds( T aValue, T aNominal, T aErrorAbove, T aErrorBelow ) +{ + return ( aValue >= aNominal - aErrorBelow ) && ( aValue <= aNominal + aErrorAbove ); +} + +/** + * value is in range [aNominal - aErrorBelow, aNominal] + */ +template bool IsWithinAndBelow( T aValue, T aNominal, T aErrorBelow ) +{ + return IsWithinBounds( aValue, aNominal, 0, aErrorBelow ); +} + +/** + * value is in range [aNominal, aNominal + aErrorAbove] + */ +template bool IsWithinAndAbove( T aValue, T aNominal, T aErrorAbove ) +{ + return IsWithinBounds( aValue, aNominal, aErrorAbove, 0 ); +} + +} // namespace KI_TEST + +#endif // NUMERIC__H \ No newline at end of file diff --git a/qa/unit_test_utils/include/unit_test_utils/unit_test_utils.h b/qa/unit_test_utils/include/unit_test_utils/unit_test_utils.h new file mode 100644 index 0000000000..8efcd46f27 --- /dev/null +++ b/qa/unit_test_utils/include/unit_test_utils/unit_test_utils.h @@ -0,0 +1,53 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2018 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef UNIT_TEST_UTILS__H +#define UNIT_TEST_UTILS__H + +#include + +/** + * If HAVE_EXPECTED_FAILURES is defined, this means that + * boost::unit_test::expected_failures is available. + * + * Wrap expected-to-fail tests with this to prevent them being compiled + * on platforms with older (<1.59) Boost versions. + * + * This can be removed when our minimum boost version is 1.59 or higher. + */ +#if BOOST_VERSION >= 105900 +#define HAVE_EXPECTED_FAILURES +#endif + +/** + * BOOST_TEST, while extremely handy, is not available in Boost < 1.59. + * Undef it here to prevent use. Using it can cause older packaging like + * Ubuntu LTS (which is on Boost 1.58) to fail. + * + * Use BOOST_CHECK_{EQUAL,NE,etc} instead. + * + * This can be removed when our minimum boost version is 1.59 or higher. + */ +#undef BOOST_TEST + +#endif // UNIT_TEST_UTILS__H \ No newline at end of file diff --git a/qa/unit_test_utils/unit_test_utils.cpp b/qa/unit_test_utils/unit_test_utils.cpp new file mode 100644 index 0000000000..e96ba6c09f --- /dev/null +++ b/qa/unit_test_utils/unit_test_utils.cpp @@ -0,0 +1,26 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, you may find one here: + * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html + * or you may search the http://www.gnu.org website for the version 2 license, + * or you may write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + * Nothing here yet, but CMake requires *something*. + */ \ No newline at end of file