diff --git a/AutoRAII.test/CMakeLists.txt b/AutoRAII.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/AutoRAII.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 ) diff --git a/AutoRAII.test/Makefile b/AutoRAII.test/Makefile deleted file mode 100644 index b76123d..0000000 --- a/AutoRAII.test/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -CXXFLAGS+= -std=c++17 -I ../ - -all: 0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e78b67..d6c8d28 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,32 @@ cmake_minimum_required( VERSION 3.25 ) project( Alepha ) -add_compile_options( -I . ; -std=c++20 ) +include( cmake/rules.cmake ) -set( VERBOSE 1 ) -set( CMAKE_VERBOSE_MAKEFILE true ) -file( CREATE_LINK ${CMAKE_SOURCE_DIR} Alepha SYMBOLIC ) -add_library( alepha SHARED Console.cpp ProgramOptions.cpp string_algorithms.cpp word_wrap.cpp ) +# The core alepha library: + +add_library( alepha SHARED + Console.cpp + ProgramOptions.cpp + string_algorithms.cpp + word_wrap.cpp +) +# Everything else depends upon it link_libraries( alepha ) +# The subdirs to build +add_subdirectory( Meta ) +add_subdirectory( Proof ) +add_subdirectory( Reflection ) +add_subdirectory( Testing ) + +# The local subdir tests to build +add_subdirectory( AutoRAII.test ) +add_subdirectory( comparisons.test ) +add_subdirectory( Exception.test ) +add_subdirectory( word_wrap.test ) + +# Sample applications add_executable( example example.cc ) diff --git a/Exception.test/CMakeLists.txt b/Exception.test/CMakeLists.txt new file mode 100644 index 0000000..c725ed7 --- /dev/null +++ b/Exception.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( exception ) diff --git a/Exception.test/Makefile b/Exception.test/Makefile deleted file mode 100644 index d73a1b3..0000000 --- a/Exception.test/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -CXXFLAGS+= -std=c++2a -I ../ -CXXFLAGS+= -g -O0 -CXX=g++ - -CXXFLAGS+= -Wno-inline-namespace-reopened-noninline -CXXFLAGS+= -Wno-unused-comparison -CXXFLAGS+= -DAlepha=MyProject_Alepha - -all: exception diff --git a/Makefile b/Makefile deleted file mode 100644 index 1d210f2..0000000 --- a/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -CXXFLAGS+= -std=c++20 -I . - -all: example - -example: ProgramOptions.o string_algorithms.o Console.o word_wrap.o diff --git a/Meta/CMakeLists.txt b/Meta/CMakeLists.txt new file mode 100644 index 0000000..e69eebb --- /dev/null +++ b/Meta/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory( Meta.test ) diff --git a/Meta/Makefile b/Meta/Makefile deleted file mode 100644 index 3ec6ce7..0000000 --- a/Meta/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -CXXFLAGS+= -std=c++17 -I ../ - -all: test diff --git a/Meta/Meta.test/CMakeLists.txt b/Meta/Meta.test/CMakeLists.txt new file mode 100644 index 0000000..15040cf --- /dev/null +++ b/Meta/Meta.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( traits ) diff --git a/Meta/test.cc b/Meta/Meta.test/traits.cc similarity index 100% rename from Meta/test.cc rename to Meta/Meta.test/traits.cc diff --git a/Proof/Attestation.test/CMakeLists.txt b/Proof/Attestation.test/CMakeLists.txt new file mode 100644 index 0000000..6c1ba18 --- /dev/null +++ b/Proof/Attestation.test/CMakeLists.txt @@ -0,0 +1,2 @@ +unit_test( simple ) +unit_test( test ) diff --git a/Proof/Attestation.test/simple.cc b/Proof/Attestation.test/simple.cc new file mode 100644 index 0000000..7b100da --- /dev/null +++ b/Proof/Attestation.test/simple.cc @@ -0,0 +1,369 @@ +#include "../Attestation.h" + +#include +#include +#include +#include +#include +#include +#include + +// Ignore the headers, for the moment, just assume that I have included what I need. + + +namespace +{ + // An initial way you might do things... + class Thing0 + { + private: + std::mutex mtx; + + void helper_needs_lock() {} + + + public: + void + function() + { + std::lock_guard< std::mutex > lock( mtx ); + helper_needs_lock(); + } + }; + + + // A better way you might do it. + class Thing1 + { + private: + std::mutex mtx; + + void helper( const std::lock_guard< std::mutex > & ) {} + + + public: + void + function() + { + std::lock_guard< std::mutex > lock( mtx ); + helper( lock ); + } + }; + + + + // A more adaptable way you might do it. + class WithLock + { + public: + WithLock( const std::lock_guard< std::mutex > & ) {} + WithLock( const std::unique_lock< std::mutex > &lock ) { assert( lock.owns_lock() ); } + }; + + class Thing2 + { + private: + std::mutex mtx; + + void helper( WithLock ) {} + + + public: + void + function() + { + std::lock_guard< std::mutex > lock( mtx ); + helper( lock ); + } + }; + + + + + + + + + // How might we generalize this? + + + class NotSorted : public std::exception + { + public: + virtual const char *what() const noexcept final { return "Something wasn't sorted."; } + }; + + + + struct Sorter; + struct sorted_tag { using averant= Sorter; }; + + using Sorted= Alepha::Proof::Attestation< sorted_tag >; + + struct Sorter + { + static Sorted::Witness< const std::vector< int > & > + sort( std::vector< int > &v ) + { + std::sort( begin( v ), end( v ) ); + return attest( Sorted::permission ).aver< const std::vector< int > & >( v ); + } + + static Sorted::Witness< const std::vector< int > & > + check( std::vector< int > &v ) + { + if( !std::is_sorted( begin( v ), end( v ) ) ) throw NotSorted{}; + return attest( Sorted::permission ).aver< const std::vector< int > & >( v ); + } + }; +} + +namespace // Other guy +{ + bool + binarySearch( Sorted::Witness< const std::vector< int > & > v, const int data ) + { + return std::binary_search( begin( testify( v ) ), end( testify( v ) ), data ); + } + + inline namespace test_detail + { + std::vector< int > getData(); + } +} + + +int +main() +{ + //auto data= std::vector< int >( std::istream_iterator< int >( std::cin ), + //std::istream_iterator< int >() ); + + std::vector< int > data= getData(); + + + try + { + auto witness= Sorter::check( data ); + throw std::logic_error( "This should have thrown in `check`!" ); + } + catch( const NotSorted & ) {} + + std::sort( begin( data ), end( data ) ); + + auto witness= Sorter::check( data ); // This time it oughtn't throw. + + std::cout << std::boolalpha << binarySearch( witness, 42 ) << std::endl; +} + + +namespace +{ + std::vector< int > + test_detail::getData() + { + return + { + 49344, + 248, + 34529, + 12412, + 28387, + 52204, + 17330, + 64061, + 26865, + 53098, + 6254, + 24235, + 12433, + 5162, + 6967, + 22064, + 3150, + 37829, + 47719, + 15118, + 24956, + 7880, + 34712, + 57950, + 28045, + 58978, + 32835, + 41625, + 34921, + 4994, + 42600, + 21544, + 57838, + 48717, + 293, + 35508, + 13139, + 59576, + 2232, + 9298, + 65262, + 62943, + 32059, + 58746, + 8749, + 21421, + 20637, + 8188, + 15577, + 44297, + 55962, + 40634, + 58919, + 32798, + 34149, + 44650, + 53797, + 5154, + 65141, + 17675, + 7335, + 6778, + 44150, + 12318, + 59968, + 46993, + 35697, + 49319, + 56361, + 26640, + 40924, + 43750, + 43787, + 31692, + 65222, + 59041, + 20470, + 40424, + 52828, + 4730, + 3432, + 60223, + 44893, + 62286, + 34341, + 46247, + 56626, + 6411, + 38579, + 44396, + 64745, + 24651, + 21627, + 11543, + 44708, + 41595, + 40306, + 23704, + 41460, + 34339, + 51595, + 45262, + 36429, + 56661, + 25925, + 19652, + 54824, + 46212, + 12859, + 64783, + 47842, + 35101, + 52132, + 56040, + 25982, + 40335, + 48109, + 39422, + 21357, + 6038, + 27967, + 16297, + 30156, + 56378, + 44745, + 9223, + 11229, + 49482, + 17689, + 40163, + 22734, + 18030, + 50310, + 9113, + 25363, + 8367, + 16282, + 11922, + 4331, + 5890, + 19401, + 28942, + 37930, + 50699, + 57258, + 46439, + 10721, + 9926, + 54356, + 5157, + 19125, + 62868, + 7203, + 3141, + 8435, + 11667, + 27030, + 32321, + 49138, + 39657, + 33371, + 22733, + 59225, + 4257, + 35253, + 43775, + 44733, + 36009, + 58911, + 65521, + 2472, + 4557, + 23185, + 36930, + 15248, + 30805, + 23263, + 29451, + 32896, + 64592, + 26391, + 49382, + 59807, + 4328, + 60062, + 17463, + 17645, + 3516, + 25561, + 28430, + 32386, + 11974, + 13668, + 25827, + 45584, + 64900, + 20025, + 40000, + 50531, + 49065, + }; + } +} diff --git a/Proof/test.cc b/Proof/Attestation.test/test.cc similarity index 99% rename from Proof/test.cc rename to Proof/Attestation.test/test.cc index caf6cfc..b495616 100644 --- a/Proof/test.cc +++ b/Proof/Attestation.test/test.cc @@ -1,4 +1,4 @@ -#include "Attestation.h" +#include "../Attestation.h" #include #include diff --git a/Proof/CMakeLists.txt b/Proof/CMakeLists.txt new file mode 100644 index 0000000..3974e90 --- /dev/null +++ b/Proof/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory( Attestation.test ) diff --git a/Proof/Makefile b/Proof/Makefile deleted file mode 100644 index 7d99331..0000000 --- a/Proof/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -#CXX=clang++ -CXX=g++ -CXXFLAGS+= -std=c++1z -#CXXFLAGS+= -stdlib=libstdc++ -CXXFLAGS+= -O3 -all: simple test - -test.cc: Attestation.h -simple.cc: Attestation.h - -clean: - $(RM) *.o test diff --git a/Proof/simple.cc b/Proof/simple.cc deleted file mode 100644 index 91202c0..0000000 --- a/Proof/simple.cc +++ /dev/null @@ -1,134 +0,0 @@ -#include "Attestation.h" -#include -#include -#include -#include -#include -#include -#include - -// Ignore the headers, for the moment, just assume that I have included what I need. - - -namespace -{ - // An initial way you might do things... - class Thing0 - { - private: - std::mutex mtx; - - void helper_needs_lock() {} - - - public: - void - function() - { - std::lock_guard< std::mutex > lock( mtx ); - helper_needs_lock(); - } - }; - - - // A better way you might do it. - class Thing1 - { - private: - std::mutex mtx; - - void helper( const std::lock_guard< std::mutex > & ) {} - - - public: - void - function() - { - std::lock_guard< std::mutex > lock( mtx ); - helper( lock ); - } - }; - - - - // A more adaptable way you might do it. - class WithLock - { - public: - WithLock( const std::lock_guard< std::mutex > & ) {} - WithLock( const std::unique_lock< std::mutex > &lock ) { assert( lock.owns_lock() ); } - }; - - class Thing2 - { - private: - std::mutex mtx; - - void helper( WithLock ) {} - - - public: - void - function() - { - std::lock_guard< std::mutex > lock( mtx ); - helper( lock ); - } - }; - - - - - - - - - // How might we generalize this? - - - - - - struct Sorter; - struct sorted_tag { using averant= Sorter; }; - - using Sorted= Alepha::Proof::Attestation< sorted_tag >; - - struct Sorter - { - static Sorted::Witness< const std::vector< int > & > - sort( std::vector< int > &v ) - { - std::sort( begin( v ), end( v ) ); - return attest( Sorted::permission ).aver< const std::vector< int > & >( v ); - } - - static Sorted::Witness< const std::vector< int > & > - check( std::vector< int > &v ) - { - if( !std::is_sorted( begin( v ), end( v ) ) ) throw std::runtime_error( "" ); - return attest( Sorted::permission ).aver< const std::vector< int > & >( v ); - } - }; -} - -namespace // Other guy -{ - bool - binarySearch( Sorted::Witness< const std::vector< int > & > v, const int data ) - { - return std::binary_search( begin( testify( v ) ), end( testify( v ) ), data ); - } -} - - -int -main() -{ - auto data= std::vector< int >( std::istream_iterator< int >( std::cin ), - std::istream_iterator< int >() ); - auto witness= Sorter::check( data ); - - std::cout << std::boolalpha << binarySearch( witness, 42 ) << std::endl; -} - diff --git a/Reflection/CMakeLists.txt b/Reflection/CMakeLists.txt new file mode 100644 index 0000000..d124a33 --- /dev/null +++ b/Reflection/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory( tuplizeAggregate.test ) diff --git a/Reflection/tuplizeAggregate.test/CMakeLists.txt b/Reflection/tuplizeAggregate.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/Reflection/tuplizeAggregate.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 ) diff --git a/Reflection/tuplizeAggregate.test/Makefile b/Reflection/tuplizeAggregate.test/Makefile deleted file mode 100644 index 1f88709..0000000 --- a/Reflection/tuplizeAggregate.test/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -CXXFLAGS+= -std=c++17 -I . -CXXFLAGS+= -g -O0 - -all: 0 diff --git a/Testing/CMakeLists.txt b/Testing/CMakeLists.txt new file mode 100644 index 0000000..4a30b10 --- /dev/null +++ b/Testing/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory( TableTest.test ) + +add_library( unit-test SHARED testlib.cc ) diff --git a/Testing/Makefile b/Testing/Makefile deleted file mode 100644 index 3ec6ce7..0000000 --- a/Testing/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -CXXFLAGS+= -std=c++17 -I ../ - -all: test diff --git a/Testing/TableTest.h b/Testing/TableTest.h index 2b556cd..84212a9 100644 --- a/Testing/TableTest.h +++ b/Testing/TableTest.h @@ -34,7 +34,7 @@ namespace Alepha::Hydrogen::Testing { const bool debug= false; const bool debugCaseTypes= false or C::debug; - using namespace Alepha::exports::console::C; + using namespace Alepha::console::C; } using namespace Utility::exports::evaluation; diff --git a/Testing/TableTest.test/CMakeLists.txt b/Testing/TableTest.test/CMakeLists.txt new file mode 100644 index 0000000..f75bd65 --- /dev/null +++ b/Testing/TableTest.test/CMakeLists.txt @@ -0,0 +1,2 @@ +unit_test( test ) +unit_test( test2 ) diff --git a/Testing/test.cc b/Testing/TableTest.test/test.cc similarity index 100% rename from Testing/test.cc rename to Testing/TableTest.test/test.cc diff --git a/Testing/test2.cc b/Testing/TableTest.test/test2.cc similarity index 100% rename from Testing/test2.cc rename to Testing/TableTest.test/test2.cc diff --git a/Testing/test.h b/Testing/test.h index ccbc83b..fe72aad 100644 --- a/Testing/test.h +++ b/Testing/test.h @@ -32,7 +32,7 @@ namespace Alepha::Hydrogen::Testing const bool debugTestRegistration= false or C::debug; const bool debugTestRun= false or C::debug; - using namespace Alepha::exports::C; + using namespace Alepha::Hydrogen::exports::C; } using namespace std::literals::string_literals; @@ -227,4 +227,9 @@ namespace Alepha::Hydrogen::Testing { using namespace detail::testing::exports; } + + namespace exports::inline literals::inline program_option_literals + { + using namespace detail::testing::exports::literals; + } } diff --git a/Testing/testlib.cc b/Testing/testlib.cc new file mode 100644 index 0000000..b3d989c --- /dev/null +++ b/Testing/testlib.cc @@ -0,0 +1,25 @@ +static_assert( __cplusplus > 2020'00 ); + +#include +#include + +namespace +{ + namespace impl + { + int + main( const int argcnt, const char *const *const argvec ) + { + // TODO: Have test selection options here and more. + const auto args= Alepha::handleOptions( argcnt, argvec ); + const auto result= Alepha::Testing::runAllTests( args ); + return result; + } + } +} + +int +main( const int argcnt, const char *const *const argvec ) +{ + return impl::main( argcnt, argvec ); +} diff --git a/cmake/rules.cmake b/cmake/rules.cmake new file mode 100644 index 0000000..70e49fc --- /dev/null +++ b/cmake/rules.cmake @@ -0,0 +1,27 @@ +#cmake_policy( SET CMP0002 OLD ) + +add_compile_options( -I ${CMAKE_BINARY_DIR} ; -std=c++20 ; -I . ) + + +list( APPEND CMAKE_CTEST_ARGUMENTS "-VV" ) + + +set( VERBOSE 1 ) +set( CMAKE_VERBOSE_MAKEFILE true ) + +file( CREATE_LINK ${CMAKE_SOURCE_DIR} Alepha SYMBOLIC ) + + +include(CTest) + + +function( unit_test TEST_NAME ) + +get_filename_component( TEST_DOMAIN ${CMAKE_CURRENT_SOURCE_DIR} NAME ) +set( FULL_TEST_NAME ${TEST_DOMAIN}.${TEST_NAME} ) + +add_executable( ${FULL_TEST_NAME} ${TEST_NAME}.cc ) +add_test( ${FULL_TEST_NAME} ${FULL_TEST_NAME} ) + +endfunction( unit_test ) + diff --git a/comparisons.test/CMakeLists.txt b/comparisons.test/CMakeLists.txt new file mode 100644 index 0000000..b099603 --- /dev/null +++ b/comparisons.test/CMakeLists.txt @@ -0,0 +1 @@ +unit_test( 0 ) diff --git a/comparisons.test/Makefile b/comparisons.test/Makefile deleted file mode 100644 index cd954b9..0000000 --- a/comparisons.test/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -CXXFLAGS+= -std=c++17 -I ../ -CXXFLAGS+= -g -O0 - -all: 0 diff --git a/helpful-things/Makefile b/helpful-things/Makefile new file mode 100644 index 0000000..0cef424 --- /dev/null +++ b/helpful-things/Makefile @@ -0,0 +1,13 @@ +# You can use this makefile in your +# build directory to drive ninja builds. + +__primary: test + +all: + ninja -v -j19 all + +clean: + ninja clean + +test: all + ninja test diff --git a/word_wrap.test/0.cc b/word_wrap.test/0.cc new file mode 100644 index 0000000..00d4518 --- /dev/null +++ b/word_wrap.test/0.cc @@ -0,0 +1,21 @@ +static_assert( __cplusplus > 2020'00 ); + +#include "../word_wrap.h" + +#include +#include +#include + +namespace +{ + using namespace Alepha::Testing::literals::program_option_literals; + using Alepha::Testing::TableTest; +} + +static auto init= Alepha::Utility::enroll <=[] +{ + "Does word wrap with no-indent do sensible things?"_test <=TableTest< Alepha::wordWrap >::Cases + { + { "Three word with break after first?", { "Goodbye cruel world!", 12, 0 }, "Goodbye \ncruel world!" }, + }; +}; diff --git a/word_wrap.test/CMakeLists.txt b/word_wrap.test/CMakeLists.txt new file mode 100644 index 0000000..d31c4a6 --- /dev/null +++ b/word_wrap.test/CMakeLists.txt @@ -0,0 +1,2 @@ +link_libraries( unit-test ) +unit_test( 0 )