Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion e2e_tests/functional_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1525,7 +1525,9 @@ TEST_P(FuzzingModeFixtureTest, TestIsSkippedWhenRequestedInFixturePerTest) {
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,
Expand Down
84 changes: 61 additions & 23 deletions fuzztest/internal/centipede_adaptor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -510,14 +510,19 @@ class CentipedeAdaptorRunnerCallbacks
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
Expand Down Expand Up @@ -963,16 +968,27 @@ bool CentipedeFuzzerAdaptor::Run(int* argc, char*** argv, RunMode mode,
}
// Run as the fuzzing engine.
int result = EXIT_FAILURE;
TempDir temp_dir;
const std::string skipped_test_indicator_file =
temp_dir.path() / "skipped_test";
std::error_code ec;
runtime_.SetShouldTerminateOnNonFatalFailure(false);

[&] {
runtime_.SetShouldTerminateOnNonFatalFailure(false);
std::unique_ptr<TempDir> workdir;
if (configuration.corpus_database.empty() ||
(mode == RunMode::kUnitTest && 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() ||
(mode == RunMode::kUnitTest && 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;
Expand All @@ -994,17 +1010,25 @@ bool CentipedeFuzzerAdaptor::Run(int* argc, char*** argv, RunMode mode,
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.
Expand All @@ -1017,16 +1041,23 @@ bool CentipedeFuzzerAdaptor::Run(int* argc, char*** argv, RunMode mode,
// 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);
result = 0;
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(
Expand All @@ -1045,6 +1076,13 @@ bool CentipedeFuzzerAdaptor::Run(int* argc, char*** argv, RunMode mode,
}
}
}();
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;
}

Expand Down
9 changes: 7 additions & 2 deletions fuzztest/internal/googletest_adaptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,22 @@ class GTest_TestAdaptor : public ::testing::Test {
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.";
}
if (Runtime::instance().skipping_requested()) {
GTEST_SKIP() << "Test was skipped";
}
}

static void SetUpTestSuite() {
Expand Down
Loading