Handle test skipping and early termination without the special failure types. These failure types will not be supported when migrate to the engine ABI. PiperOrigin-RevId: 952854556
diff --git a/e2e_tests/functional_test.cc b/e2e_tests/functional_test.cc index af8f9e2..64ecd26 100644 --- a/e2e_tests/functional_test.cc +++ b/e2e_tests/functional_test.cc
@@ -1541,7 +1541,9 @@ EXPECT_THAT_LOG(std_err, HasSubstr("Skipping SkippedTestFixturePerTest.SkippedTest")); EXPECT_THAT_LOG(std_err, Not(HasSubstr("SkippedTest should not be run"))); - EXPECT_THAT(status, Eq(ExitCode(0))); +#ifdef FUZZTEST_USE_CENTIPEDE + EXPECT_THAT_LOG(std_err, HasSubstr("SETUP FAILURE: Test is skipped")); +#endif } TEST_P(FuzzingModeFixtureTest,
diff --git a/fuzztest/internal/centipede_adaptor.cc b/fuzztest/internal/centipede_adaptor.cc index f13801b..7670d76 100644 --- a/fuzztest/internal/centipede_adaptor.cc +++ b/fuzztest/internal/centipede_adaptor.cc
@@ -41,7 +41,8 @@ #include <optional> #include <random> #include <string> -#include <thread> // NOLINT: For thread::get_id() only. +#include <system_error> // NOLINT +#include <thread> // NOLINT: For thread::get_id() only. #include <utility> #include <vector> @@ -510,14 +511,19 @@ absl::FPrintF(GetStderr(), "[.] Skipping %s per request from the test setup.\n", fuzzer_impl_.test_.full_name()); - CentipedeSetFailureDescription("SKIPPED TEST: Requested from setup"); - return true; + if (const char* indicator = + std::getenv("FUZZTEST_SKIPPED_TEST_INDICATOR_FILE"); + indicator != nullptr) { + absl::FPrintF(GetStderr(), "[.] Touching the indicator file %s\n", + indicator); + WriteFile(indicator, ""); + } + CentipedeSetFailureDescription("SETUP FAILURE: Test is skipped"); + return false; } if (runtime_.termination_requested()) { absl::FPrintF(GetStderr(), - "[.] Termination requested - exiting without executing " - "further inputs.\n"); - CentipedeSetFailureDescription("IGNORED FAILURE: Termination requested"); + "[.] Termination requested - not executing input.\n"); return false; } // We should avoid doing anything other than executing the input here so @@ -963,17 +969,28 @@ } // Run as the fuzzing engine. int result = EXIT_FAILURE; + TempDir temp_dir; + const std::string skipped_test_indicator_file = + temp_dir.path() / "skipped_test_indicator"; + std::error_code ec; + runtime_.SetShouldTerminateOnNonFatalFailure(false); + [&] { - runtime_.SetShouldTerminateOnNonFatalFailure(false); - std::unique_ptr<TempDir> workdir; - if (configuration.corpus_database.empty() || - (!configuration.update_corpus_database && - configuration.workdir_root.empty())) { - workdir = std::make_unique<TempDir>("fuzztest_workdir"); - } - const std::string workdir_path = workdir ? workdir->path() : ""; - const auto env = CreateCentipedeEnvironmentFromConfiguration( - configuration, workdir_path, test_.full_name(), mode); + const auto env = [&] { + std::string workdir_path; + if (configuration.corpus_database.empty() || + (!configuration.update_corpus_database && + configuration.workdir_root.empty())) { + workdir_path = temp_dir.path() / "workdir"; + } + auto env = CreateCentipedeEnvironmentFromConfiguration( + configuration, workdir_path, test_.full_name(), mode); + env.env_diff_for_binaries.push_back( + absl::StrCat("FUZZTEST_SKIPPED_TEST_INDICATOR_FILE=", + skipped_test_indicator_file)); + return env; + }(); + if (const char* minimize_dir_chars = std::getenv("FUZZTEST_MINIMIZE_TESTSUITE_DIR")) { const std::string minimize_dir = minimize_dir_chars; @@ -995,17 +1012,25 @@ replay_env.corpus_dir = {"", minimize_dir}; replay_env.load_shards_only = true; replay_env.report_crash_summary = false; - FUZZTEST_CHECK( - RunCentipede(replay_env, configuration.centipede_command) == 0) - << "Failed to replaying the testsuite for minimization"; + result = RunCentipede(replay_env, configuration.centipede_command); + if (std::filesystem::exists(skipped_test_indicator_file, ec)) { + return; + } + if (result != 0) { + absl::FPrintF(GetStderr(), + "[!] Failed to replaying the corpus for minimization"); + return; + } absl::FPrintF(GetStderr(), "[.] Imported the corpus from %s.\n", minimize_dir); // 2. Run Centipede distillation on the shard. auto distill_env = env; distill_env.distill = true; - FUZZTEST_CHECK( - RunCentipede(distill_env, configuration.centipede_command) == 0) - << "Failed to minimize the testsuite"; + result = RunCentipede(distill_env, configuration.centipede_command); + if (result != 0) { + absl::FPrintF(GetStderr(), "[!] Failed to minimize the testsuite"); + return; + } absl::FPrintF(GetStderr(), "[.] Minimized the corpus using Centipede distillation.\n"); // 3. Replace the shard corpus data with the distillation result. @@ -1018,9 +1043,13 @@ // 4. Export the corpus of the shard. auto export_env = env; export_env.corpus_to_files = corpus_out_dir; - FUZZTEST_CHECK( - RunCentipede(export_env, configuration.centipede_command) == 0) - << "Failed to export the corpus to FUZZTEST_MINIMIZE_TESTSUITE_DIR"; + result = RunCentipede(export_env, configuration.centipede_command); + if (result != 0) { + absl::FPrintF( + GetStderr(), + "Failed to export the corpus to FUZZTEST_MINIMIZE_TESTSUITE_DIR"); + return; + } absl::FPrintF(GetStderr(), "[.] Exported the minimized the corpus to %s.\n", corpus_out_dir); @@ -1028,6 +1057,9 @@ return; } result = RunCentipede(env, configuration.centipede_command); + if (std::filesystem::exists(skipped_test_indicator_file, ec)) { + return; + } if (!env.workdir.empty()) { if (runtime_.termination_requested()) { absl::FPrintF( @@ -1046,6 +1078,13 @@ } } }(); + if (std::filesystem::exists(skipped_test_indicator_file, ec)) { + absl::FPrintF( + GetStderr(), + "[.] Indicator file for skipped test found - ignoring any failures.\n"); + runtime_.SetSkippingRequested(true); + return true; + } return result == 0; }
diff --git a/fuzztest/internal/googletest_adaptor.h b/fuzztest/internal/googletest_adaptor.h index 4571781..39ffcab 100644 --- a/fuzztest/internal/googletest_adaptor.h +++ b/fuzztest/internal/googletest_adaptor.h
@@ -85,14 +85,16 @@ EXPECT_TRUE(false) << "Death test is not supported."; #endif } else { - EXPECT_TRUE(test->RunInUnitTestMode(configuration_)) + EXPECT_TRUE(test->RunInUnitTestMode(configuration_) || + Runtime::instance().skipping_requested()) << "Failure(s) found in the unit-test mode - please see the test " "log for more details."; } } else { // TODO(b/245753736): Consider using `tolerate_failure` when FuzzTest can // tolerate crashes in fuzzing mode. - EXPECT_TRUE(test->RunInFuzzingMode(argc_, argv_, configuration_)) + EXPECT_TRUE(test->RunInFuzzingMode(argc_, argv_, configuration_) || + Runtime::instance().skipping_requested()) << "Failure(s) found in the fuzzing mode - please see the test log " "for more details."; }