diff options
| author | Leitwolf | 2026-10-31 17:18:21 +0300 |
|---|---|---|
| committer | GitHub | 2026-10-31 17:18:21 +0300 |
| commit | 326ea0c0213aeecb6b984bba3dabb0ebad97679e (patch) | |
| tree | 5cec698f0bc0b8a60f45e866fb40f2fd8a358bd1 /tests | |
| parent | 6a42cdf6461b2577106ef094d6f98025554b6077 (diff) | |
| parent | afe91797e9d50cd4712d3694a2e5fedfc0b966b1 (diff) | |
| download | catch3-326ea0c0213aeecb6b984bba3dabb0ebad97679e.tar.gz | |
Merge pull request #22 from Progmasoft/build/cpp17
Build Catch3 as C++17
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | tests/ExtraTests/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | tests/Progmasoft/BUILD.bazel | 8 | ||||
| -rw-r--r-- | tests/Progmasoft/Generators.tests.cpp | 76 | ||||
| -rw-r--r-- | tests/Progmasoft/Property.tests.cpp | 66 | ||||
| -rw-r--r-- | tests/Progmasoft/Results.tests.cpp | 2 | ||||
| -rw-r--r-- | tests/Progmasoft/Snapshot.tests.cpp | 77 | ||||
| -rw-r--r-- | tests/Progmasoft/Strategy.tests.cpp | 34 | ||||
| -rw-r--r-- | tests/meson.build | 4 |
9 files changed, 187 insertions, 86 deletions
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5af76cab..a5524a38 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -172,12 +172,12 @@ add_executable(ProgmasoftSelfTest Progmasoft/Strategy.tests.cpp ) target_link_libraries(ProgmasoftSelfTest PRIVATE Catch3WithMain) -target_compile_features(ProgmasoftSelfTest PRIVATE cxx_std_20) +target_compile_features(ProgmasoftSelfTest PRIVATE cxx_std_17) # Tests that misbehave on purpose, for the runner's integration tests. add_executable(RunnerFixture Progmasoft/RunnerFixture.cpp) target_link_libraries(RunnerFixture PRIVATE Catch3WithMain) -target_compile_features(RunnerFixture PRIVATE cxx_std_20) +target_compile_features(RunnerFixture PRIVATE cxx_std_17) add_dependencies(ProgmasoftSelfTest RunnerFixture) add_test(NAME Progmasoft::PropertyTests COMMAND $<TARGET_FILE:ProgmasoftSelfTest> --no-history) diff --git a/tests/ExtraTests/CMakeLists.txt b/tests/ExtraTests/CMakeLists.txt index 9518c733..e6488650 100644 --- a/tests/ExtraTests/CMakeLists.txt +++ b/tests/ExtraTests/CMakeLists.txt @@ -431,7 +431,7 @@ add_executable(AmalgamatedTestCompilation ) target_include_directories(AmalgamatedTestCompilation PRIVATE ${CATCH_DIR}/extras) # The amalgamated files hold the runner, which needs C++20. -target_compile_features(AmalgamatedTestCompilation PRIVATE cxx_std_20) +target_compile_features(AmalgamatedTestCompilation PRIVATE cxx_std_17) add_test(NAME AmalgamatedFileTest COMMAND AmalgamatedTestCompilation --no-history) set_tests_properties(AmalgamatedFileTest diff --git a/tests/Progmasoft/BUILD.bazel b/tests/Progmasoft/BUILD.bazel index 9627f65d..de7f124d 100644 --- a/tests/Progmasoft/BUILD.bazel +++ b/tests/Progmasoft/BUILD.bazel @@ -24,8 +24,8 @@ cc_test( "Strategy.tests.cpp", ], copts = select({ - "@platforms//os:windows": ["/std:c++20"], - "//conditions:default": ["-std=c++20"], + "@platforms//os:windows": ["/std:c++17"], + "//conditions:default": ["-std=c++17"], }), args = ["--no-history"], data = [":runner_fixture"], @@ -41,8 +41,8 @@ cc_binary( name = "runner_fixture", srcs = ["RunnerFixture.cpp"], copts = select({ - "@platforms//os:windows": ["/std:c++20"], - "//conditions:default": ["-std=c++20"], + "@platforms//os:windows": ["/std:c++17"], + "//conditions:default": ["-std=c++17"], }), deps = [ "//:catch3", diff --git a/tests/Progmasoft/Generators.tests.cpp b/tests/Progmasoft/Generators.tests.cpp index 553a8962..b59bab4a 100644 --- a/tests/Progmasoft/Generators.tests.cpp +++ b/tests/Progmasoft/Generators.tests.cpp @@ -96,11 +96,16 @@ TEST_CASE( "Vector shrinking offers a bounded number of candidates", TEST_CASE( "Vector properties shrink to a small counterexample", "[progmasoft][property][vector]" ) { const auto result = CheckProperty( - Vector( Integer<int>( 0, 100 ), 0, 20 ), - []( const std::vector<int>& values ) { + Vector(Integer<int>(0, 100), 0, 20), + [](const std::vector<int> &values) { return std::accumulate( values.begin(), values.end(), 0 ) < 10; }, - PropertyOptions{ .Trials = 200, .Seed = 0xF00D } ); + [&] { + PropertyOptions made; + made.Trials = 200; + made.Seed = 0xF00D; + return made; + }()); REQUIRE( result.Status == PropertyStatus::kFailed ); REQUIRE( result.Failure.has_value() ); @@ -113,10 +118,15 @@ TEST_CASE( "Vector<bool> values generate, shrink and print", const auto generator = Vector( Progmasoft::Catch3::Boolean(), 0, 8 ); const auto result = CheckProperty( generator, - []( const std::vector<bool>& flags ) { + [](const std::vector<bool> &flags) { return std::count( flags.begin(), flags.end(), true ) < 2; }, - PropertyOptions{ .Trials = 300, .Seed = 0xB001 } ); + [&] { + PropertyOptions made; + made.Trials = 300; + made.Seed = 0xB001; + return made; + }()); REQUIRE( result.Status == PropertyStatus::kFailed ); REQUIRE( result.Failure.has_value() ); CHECK( result.Failure->Counterexample == "{ true, true }" ); @@ -167,11 +177,16 @@ TEST_CASE( "Tuple shrinking changes one component at a time, first to last", TEST_CASE( "Tuple properties minimize every component", "[progmasoft][property][tuple]" ) { const auto result = CheckProperty( - Tuple( Integer<int>( 0, 1000 ), Integer<int>( 0, 1000 ) ), - []( const std::tuple<int, int>& value ) { + Tuple(Integer<int>(0, 1000), Integer<int>(0, 1000)), + [](const std::tuple<int, int> &value) { return std::get<0>( value ) < 50 || std::get<1>( value ) < 50; }, - PropertyOptions{ .Trials = 500, .Seed = 0x7007 } ); + [&] { + PropertyOptions made; + made.Trials = 500; + made.Seed = 0x7007; + return made; + }()); REQUIRE( result.Status == PropertyStatus::kFailed ); REQUIRE( result.Failure.has_value() ); @@ -234,11 +249,16 @@ TEST_CASE( "Text generators stay inside their alphabet and length range", TEST_CASE( "Text properties shrink to the shortest simplest string", "[progmasoft][property][text]" ) { const auto result = CheckProperty( - Text( "abcxyz", 0, 24 ), - []( const std::string& value ) { + Text("abcxyz", 0, 24), + [](const std::string &value) { return value.find( 'x' ) == std::string::npos; }, - PropertyOptions{ .Trials = 300, .Seed = 0x7E47 } ); + [&] { + PropertyOptions made; + made.Trials = 300; + made.Seed = 0x7E47; + return made; + }()); REQUIRE( result.Status == PropertyStatus::kFailed ); REQUIRE( result.Failure.has_value() ); @@ -260,8 +280,12 @@ TEST_CASE( "A reported replay seed reproduces exactly that trial", std::get<1>( value ).size() < 2; }; - const auto original = CheckProperty( - generator, predicate, PropertyOptions{ .Trials = 500, .Seed = 0x5EED } ); + const auto original = CheckProperty(generator, predicate, [&] { + PropertyOptions made; + made.Trials = 500; + made.Seed = 0x5EED; + return made; + }()); REQUIRE( original.Status == PropertyStatus::kFailed ); REQUIRE( original.Failure.has_value() ); // The failure was not on the first trial, so replay skips real work. @@ -273,12 +297,13 @@ TEST_CASE( "A reported replay seed reproduces exactly that trial", // A different root seed and trial count prove that only the replay seed // decides what runs. - const auto replayed = CheckProperty( - generator, - predicate, - PropertyOptions{ .Trials = 3, - .Seed = 1, - .ReplayTrialSeed = original.Failure->TrialSeed } ); + const auto replayed = CheckProperty(generator, predicate, [&] { + PropertyOptions made; + made.Trials = 3; + made.Seed = 1; + made.ReplayTrialSeed = original.Failure->TrialSeed; + return made; + }()); REQUIRE( replayed.Status == PropertyStatus::kFailed ); REQUIRE( replayed.Failure.has_value() ); CHECK( replayed.TrialsRun == 1 ); @@ -290,9 +315,16 @@ TEST_CASE( "A reported replay seed reproduces exactly that trial", // Replaying a seed whose trial passes reports one passing trial. const auto passing = CheckProperty( - Integer<int>( 0, 10 ), - []( int value ) { return value <= 10; }, - PropertyOptions{ .Trials = 50, .ReplayTrialSeed = 12345 } ); + Integer<int>(0, 10), + [](int value) { + return value <= 10; + }, + [&] { + PropertyOptions made; + made.Trials = 50; + made.ReplayTrialSeed = 12345; + return made; + }()); CHECK( passing.Succeeded() ); CHECK( passing.TrialsRun == 1 ); } diff --git a/tests/Progmasoft/Property.tests.cpp b/tests/Progmasoft/Property.tests.cpp index 5cec3979..9c4c95fb 100644 --- a/tests/Progmasoft/Property.tests.cpp +++ b/tests/Progmasoft/Property.tests.cpp @@ -63,11 +63,13 @@ TEST_CASE( "Integer generators preserve bounds and useful shrink order", Integer<int>( -100, 100 ).Shrink( 6 ); REQUIRE( !positiveShrinks.empty() ); CHECK( positiveShrinks.front() == 0 ); - CHECK( std::ranges::find( positiveShrinks, 5 ) != positiveShrinks.end() ); + CHECK(std::find(positiveShrinks.begin(), positiveShrinks.end(), 5) + != positiveShrinks.end()); const std::vector<int> negativeShrinks = generator.Shrink( -6 ); CHECK( negativeShrinks.front() == 0 ); - CHECK( std::ranges::find( negativeShrinks, -5 ) != negativeShrinks.end() ); + CHECK(std::find(negativeShrinks.begin(), negativeShrinks.end(), -5) + != negativeShrinks.end()); CHECK_THROWS_AS( Integer<int>( 5, -5 ), std::invalid_argument ); } @@ -93,8 +95,13 @@ TEST_CASE( "Properties count trials and reproduce their seed", using Progmasoft::Catch3::PropertyOptions; int checks = 0; - const PropertyOptions options{ - .Trials = 64, .Seed = 0xC0FFEE, .MaxShrinkSteps = 100 }; + const PropertyOptions options = [&] { + PropertyOptions made; + made.Trials = 64; + made.Seed = 0xC0FFEE; + made.MaxShrinkSteps = 100; + return made; + }(); const auto property = [&]( int value ) { ++checks; return value >= -100 && value <= 100; @@ -137,8 +144,16 @@ TEST_CASE( "Property failures shrink to and report a replayable counterexample", const auto result = CheckProperty( generator, - []( int value ) { return value >= 0; }, - PropertyOptions{ .Trials = 4, .Seed = 0xFACE, .MaxShrinkSteps = 20 } ); + [](int value) { + return value >= 0; + }, + [&] { + PropertyOptions made; + made.Trials = 4; + made.Seed = 0xFACE; + made.MaxShrinkSteps = 20; + return made; + }()); CHECK_FALSE( result.Succeeded() ); CHECK( result.Status == Progmasoft::Catch3::PropertyStatus::kFailed ); @@ -166,8 +181,16 @@ TEST_CASE( "Property shrink work is bounded", "[progmasoft][property]" ) { } ); const auto result = CheckProperty( generator, - []( int ) { return false; }, - PropertyOptions{ .Trials = 1, .Seed = 4, .MaxShrinkSteps = 3 } ); + [](int) { + return false; + }, + [&] { + PropertyOptions made; + made.Trials = 1; + made.Seed = 4; + made.MaxShrinkSteps = 3; + return made; + }()); REQUIRE( result.Failure.has_value() ); CHECK( result.Failure->ShrinkSteps == 3 ); @@ -198,8 +221,16 @@ TEST_CASE( []( const int& ) { return std::vector<int>{}; } ); const auto invalidOptions = CheckProperty( constantGenerator, - []( int ) { return true; }, - PropertyOptions{ .Trials = 0, .Seed = 1, .MaxShrinkSteps = 1 } ); + [](int) { + return true; + }, + [&] { + PropertyOptions made; + made.Trials = 0; + made.Seed = 1; + made.MaxShrinkSteps = 1; + return made; + }()); CHECK( invalidOptions.Status == PropertyStatus::kInvalidConfiguration ); } @@ -226,8 +257,15 @@ TEST_CASE( "Predicate exceptions are ordinary reproducible property failures", TEST_CASE( "Catch3 property assertions report successful runs", "[progmasoft][property]" ) { CATCH3_CHECK_PROPERTY( - Progmasoft::Catch3::Integer<int>( 1, 100 ), - []( int value ) { return value > 0; }, - Progmasoft::Catch3::PropertyOptions{ - .Trials = 25, .Seed = 42, .MaxShrinkSteps = 10 } ); + Progmasoft::Catch3::Integer<int>(1, 100), + [](int value) { + return value > 0; + }, + [&] { + Progmasoft::Catch3::PropertyOptions made; + made.Trials = 25; + made.Seed = 42; + made.MaxShrinkSteps = 10; + return made; + }()); } diff --git a/tests/Progmasoft/Results.tests.cpp b/tests/Progmasoft/Results.tests.cpp index ad52d311..a05a601d 100644 --- a/tests/Progmasoft/Results.tests.cpp +++ b/tests/Progmasoft/Results.tests.cpp @@ -207,7 +207,7 @@ TEST_CASE("JUnit XML keeps every attempt and marks flaky tests", CHECK(xml.find("<property name=\"random-seed\" value=\"42\" />") != std::string::npos); CHECK(xml.find("time=\"0.263500\"") != std::string::npos); - CHECK(xml.ends_with("</testsuites>\n")); + CHECK(xml.rfind("</testsuites>\n") == xml.size() - 14U); } TEST_CASE("JUnit XML replaces malformed UTF-8 and forbidden XML controls", diff --git a/tests/Progmasoft/Snapshot.tests.cpp b/tests/Progmasoft/Snapshot.tests.cpp index 65ee732e..c29cb143 100644 --- a/tests/Progmasoft/Snapshot.tests.cpp +++ b/tests/Progmasoft/Snapshot.tests.cpp @@ -42,10 +42,11 @@ TEST_CASE( "Snapshot comparison does not write during ordinary runs", using Progmasoft::Catch3::SnapshotStatus; const TemporarySnapshotDirectory directory; - const auto result = - CompareSnapshot( "greeting", - "hello\nworld\n", - SnapshotOptions{ .Directory = directory.Path } ); + const auto result = CompareSnapshot("greeting", "hello\nworld\n", [&] { + SnapshotOptions made; + made.Directory = directory.Path; + return made; + }()); CHECK( result.Status == SnapshotStatus::kMismatched ); CHECK_FALSE( result.Succeeded() ); @@ -62,10 +63,12 @@ TEST_CASE( "Snapshots normalize line endings and report precise differences", using Progmasoft::Catch3::SnapshotUpdateMode; const TemporarySnapshotDirectory directory; - const SnapshotOptions createOptions{ - .Directory = directory.Path, - .UpdateMode = SnapshotUpdateMode::kCreateMissing, - }; + const SnapshotOptions createOptions = [&] { + SnapshotOptions made; + made.Directory = directory.Path; + made.UpdateMode = SnapshotUpdateMode::kCreateMissing; + return made; + }(); const auto created = CompareSnapshot( "multiline", "one\ntwo\n", createOptions ); REQUIRE( created.Status == SnapshotStatus::kCreated ); @@ -76,10 +79,11 @@ TEST_CASE( "Snapshots normalize line endings and report precise differences", CHECK( normalized.Status == SnapshotStatus::kMatched ); CHECK( normalized.Expected == "one\ntwo\n" ); - const auto mismatch = - CompareSnapshot( "multiline", - "one\ntoo\n", - SnapshotOptions{ .Directory = directory.Path } ); + const auto mismatch = CompareSnapshot("multiline", "one\ntoo\n", [&] { + SnapshotOptions made; + made.Directory = directory.Path; + return made; + }()); CHECK( mismatch.Status == SnapshotStatus::kMismatched ); CHECK( mismatch.DifferenceLine == 2 ); CHECK( mismatch.DifferenceColumn == 2 ); @@ -94,10 +98,12 @@ TEST_CASE( "Snapshot creation and replacement require explicit update modes", using Progmasoft::Catch3::SnapshotUpdateMode; const TemporarySnapshotDirectory directory; - const SnapshotOptions createMissing{ - .Directory = directory.Path, - .UpdateMode = SnapshotUpdateMode::kCreateMissing, - }; + const SnapshotOptions createMissing = [&] { + SnapshotOptions made; + made.Directory = directory.Path; + made.UpdateMode = SnapshotUpdateMode::kCreateMissing; + return made; + }(); REQUIRE( CompareSnapshot( "answer", "first", createMissing ).Succeeded() ); const auto protectedMismatch = @@ -105,10 +111,12 @@ TEST_CASE( "Snapshot creation and replacement require explicit update modes", CHECK( protectedMismatch.Status == SnapshotStatus::kMismatched ); CHECK( protectedMismatch.Expected == "first" ); - const SnapshotOptions updateEverything{ - .Directory = directory.Path, - .UpdateMode = SnapshotUpdateMode::kAlways, - }; + const SnapshotOptions updateEverything = [&] { + SnapshotOptions made; + made.Directory = directory.Path; + made.UpdateMode = SnapshotUpdateMode::kAlways; + return made; + }(); const auto updated = CompareSnapshot( "answer", "second", updateEverything ); REQUIRE( updated.Status == SnapshotStatus::kUpdated ); @@ -125,7 +133,11 @@ TEST_CASE( "Snapshot names and I/O failures are returned as structured errors", using Progmasoft::Catch3::SnapshotUpdateMode; const TemporarySnapshotDirectory directory; - const SnapshotOptions options{ .Directory = directory.Path }; + const SnapshotOptions options = [&] { + SnapshotOptions made; + made.Directory = directory.Path; + return made; + }(); CHECK( CompareSnapshot( "../outside", "text", options ).Status == SnapshotStatus::kInvalidName ); CHECK( CompareSnapshot( "nested/name", "text", options ).Status == @@ -141,11 +153,12 @@ TEST_CASE( "Snapshot names and I/O failures are returned as structured errors", REQUIRE( output.good() ); output << "file"; } - const auto ioFailure = CompareSnapshot( - "snapshot", - "text", - SnapshotOptions{ .Directory = blockingFile, - .UpdateMode = SnapshotUpdateMode::kCreateMissing } ); + const auto ioFailure = CompareSnapshot("snapshot", "text", [&] { + SnapshotOptions made; + made.Directory = blockingFile; + made.UpdateMode = SnapshotUpdateMode::kCreateMissing; + return made; + }()); CHECK( ioFailure.Status == SnapshotStatus::kIoError ); CHECK_FALSE( ioFailure.Message.empty() ); } @@ -156,9 +169,11 @@ TEST_CASE( "Snapshot assertion macro reports successful explicit updates", CATCH3_CHECK_SNAPSHOT( "macro", "stable value", - ( Progmasoft::Catch3::SnapshotOptions{ - .Directory = directory.Path, - .UpdateMode = - Progmasoft::Catch3::SnapshotUpdateMode::kCreateMissing, - } ) ); + ([&] { + Progmasoft::Catch3::SnapshotOptions made; + made.Directory = directory.Path; + made.UpdateMode + = Progmasoft::Catch3::SnapshotUpdateMode::kCreateMissing; + return made; + }())); } diff --git a/tests/Progmasoft/Strategy.tests.cpp b/tests/Progmasoft/Strategy.tests.cpp index 5a1d5a2a..2bd49105 100644 --- a/tests/Progmasoft/Strategy.tests.cpp +++ b/tests/Progmasoft/Strategy.tests.cpp @@ -116,15 +116,23 @@ TEST_CASE( "Integer strategies respect every kind of range", TEST_CASE( "Float strategies stay finite and in range unless allowed", "[progmasoft][strategy]" ) { using Progmasoft::Catch3::FloatOptions; - const auto bounded = Gen::Floats<double>( - FloatOptions{ .Minimum = -2.5, .Maximum = 1000.0 } ); + const auto bounded = Gen::Floats<double>([&] { + FloatOptions made; + made.Minimum = -2.5; + made.Maximum = 1000.0; + return made; + }()); for ( double value : Sample( bounded, 3000, 6 ) ) { CHECK( std::isfinite( value ) ); CHECK( value >= -2.5 ); CHECK( value <= 1000.0 ); } - const auto everything = Gen::Floats<double>( - FloatOptions{ .AllowNaN = true, .AllowInfinity = true } ); + const auto everything = Gen::Floats<double>([&] { + FloatOptions made; + made.AllowNaN = true; + made.AllowInfinity = true; + return made; + }()); const auto values = Sample( everything, 3000, 7 ); CHECK( std::any_of( values.begin(), values.end(), []( double value ) { return std::isnan( value ); @@ -132,14 +140,22 @@ TEST_CASE( "Float strategies stay finite and in range unless allowed", CHECK( std::any_of( values.begin(), values.end(), []( double value ) { return std::isinf( value ); } ) ); - const auto positive = Gen::Floats<float>( - FloatOptions{ .Minimum = 1.0, .Maximum = 2.0 } ); + const auto positive = Gen::Floats<float>([&] { + FloatOptions made; + made.Minimum = 1.0; + made.Maximum = 2.0; + return made; + }()); const std::vector<std::uint64_t> zeros; ChoiceSource simplest( zeros, 0 ); CHECK( positive.Draw( simplest ) == 1.0F ); - CHECK_THROWS_AS( Gen::Floats<double>( FloatOptions{ .Minimum = 2.0, - .Maximum = 1.0 } ), - std::invalid_argument ); + CHECK_THROWS_AS(Gen::Floats<double>([&] { + FloatOptions made; + made.Minimum = 2.0; + made.Maximum = 1.0; + return made; + }()), + std::invalid_argument); } TEST_CASE( "Collection strategies respect their size ranges", diff --git a/tests/meson.build b/tests/meson.build index 340b61cf..95556f06 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -89,7 +89,7 @@ progmasoft_property_tests = executable( ], include_directories: '../src', dependencies: [catch3_with_main_dep], - override_options: ['cpp_std=c++20'], + override_options: ['cpp_std=c++17'], ) # Tests that misbehave on purpose, for the runner's integration tests. @@ -98,7 +98,7 @@ runner_fixture = executable( 'Progmasoft/RunnerFixture.cpp', include_directories: '../src', dependencies: [catch3_with_main_dep], - override_options: ['cpp_std=c++20'], + override_options: ['cpp_std=c++17'], ) test( |