// tcatch.cpp // Example run: ./tcatch --success --durations yes // For doco on Catch2 TEST_CASE and SECTION see: // https://github.com/catchorg/Catch2/blob/devel/docs/test-cases-and-sections.md #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ---------------------------------------------------------------------------- typedef int_fast64_t llil_int_type; // All words in big1.txt, big2.txt, big3.txt are <= 6 chars in length. // big.txt max word length is 6 // long.txt max word length is 208 // // Based on rough benchmarking, the short fixed string hack below is only // worth trying for MAX_STR_LEN_L up to about 22. // See also https://backlinko.com/google-keyword-study // // To use (limited length) fixed length strings uncomment the next line. // #define MAX_STR_LEN_L 10 #ifdef MAX_STR_LEN_L struct str_type : std::array { bool operator==( const str_type& o ) const { return ::memcmp(this->data(), o.data(), MAX_STR_LEN_L) == 0; } bool operator<( const str_type& o ) const { return ::memcmp(this->data(), o.data(), MAX_STR_LEN_L) < 0; } }; #else struct str_type : std::basic_string { bool operator==( const str_type& o ) const { return ::strcmp(this->data(), o.data()) == 0; } bool operator<( const str_type& o ) const { return ::strcmp(this->data(), o.data()) < 0; } }; #endif using str_int_type = std::pair; using vec_str_int_type = std::vector; // inject specialization of std::hash for str_type into namespace std namespace std { template<> struct hash { std::size_t operator()( str_type const& v ) const noexcept { #if 0 return boost::hash_range( v.cbegin(), v.cend() ); #else std::basic_string_view bv { reinterpret_cast(v.data()), v.size() * sizeof(char) }; return std::hash>()(bv); #endif } }; } // Test with std::map, std::unordered_map or phmap::parallel_flat_hash_map #define MT_STD_MAP_L 0 #define MT_STD_UNORDERED_MAP_L 1 #define MT_PARALLEL_FLAT_HASH_MAP_L 2 // Uncomment one of the three map types below #define MAP_TYPE_L MT_STD_MAP_L // #define MAP_TYPE_L MT_STD_UNORDERED_MAP_L // #define MAP_TYPE_L MT_PARALLEL_FLAT_HASH_MAP_L #if MAP_TYPE_L == MT_STD_MAP_L #include using map_str_int_type = std::map; #elif MAP_TYPE_L == MT_STD_UNORDERED_MAP_L #include using map_str_int_type = std::unordered_map; #elif MAP_TYPE_L == MT_PARALLEL_FLAT_HASH_MAP_L #include // create the parallel_flat_hash_map without internal mutexes using map_str_int_type = phmap::parallel_flat_hash_map< str_type, llil_int_type, phmap::priv::hash_default_hash, phmap::priv::hash_default_eq, phmap::priv::Allocator>, 8, phmap::NullMutex >; #else #error "Unsupported map_str_int_type" #endif // Simple RAII timer ----------------------------------------------------------- // Create a MyTimer object in a scope: // { // MyTimer tt; // ... // } // to automatically print the time taken in the block to stderr #include inline double elaspe_time( std::chrono::high_resolution_clock::time_point cend, std::chrono::high_resolution_clock::time_point cstart) { return double( std::chrono::duration_cast(cend - cstart).count() ) * 1e-3; } class MyTimer { public: MyTimer() { stnow_m = std::chrono::high_resolution_clock::now(); } ~MyTimer() { auto endnow = std::chrono::high_resolution_clock::now(); std::cerr << " (" << elaspe_time(endnow, stnow_m) << " seconds)\n"; } private: std::chrono::time_point stnow_m; }; // --------------------------------------------------------------------- #include "get_properties.inl" #include #include // Catch2 tests start here ----------------------------------- TEST_CASE( "Error tests" ) { map_str_int_type mymap; REQUIRE( get_properties( "non-existent-file", mymap ) == -1 ); } TEST_CASE( "Normal tests" ) { map_str_int_type mymap; REQUIRE( get_properties( "llil-1.txt", mymap ) == 3 ); REQUIRE( get_properties( "llil-2.txt", mymap ) == 5 ); vec_str_int_type myvec( mymap.begin(), mymap.end() ); REQUIRE_THAT( myvec, Catch::Matchers::UnorderedEquals( vec_str_int_type{ { str_type { "camel" }, 69 }, { str_type { "dromedary" }, 76 }, { str_type { "kibitzer" }, 1000 }, { str_type { "pearl" }, 42 } } )); }