Skip to content

Commit a3a8f25

Browse files
xinhaoyuancopybara-github
authored andcommitted
Report skipped test in the runner mode instead of the controller mode.
With this change, FuzzTest no longer needs to instantiate the fixture in the controller mode, and setup failures in the fixture instantiation can be captured (otherwise they would crash the controller process). Because of this, a few fixture test expectations become trickier. Note that there can be setup failures that cannot be captured, such as environment setup and the static SetUpTestSuite function. But this is still a step forward. PiperOrigin-RevId: 755118538
1 parent e8a1d93 commit a3a8f25

File tree

2 files changed

+52
-34
lines changed

2 files changed

+52
-34
lines changed

e2e_tests/functional_test.cc

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1321,10 +1321,19 @@ TEST_P(FuzzingModeFixtureTest,
13211321
TEST_P(FuzzingModeFixtureTest, FixtureGoesThroughCompleteLifecycle) {
13221322
auto [status, std_out, std_err] = Run("FixtureTest.NeverFails",
13231323
/*iterations=*/10);
1324-
EXPECT_GT(CountTargetRuns(std_err), 0);
1325-
EXPECT_EQ(CountTargetRuns(std_err),
1324+
#ifdef FUZZTEST_USE_CENTIPEDE
1325+
// In the single binary execution model there is a target process running in
1326+
// controller mode, where no FuzzTest fixture object is created.
1327+
const int target_controller_runs =
1328+
GetParam() == ExecutionModelParam::kTestBinary ||
1329+
GetParam() == ExecutionModelParam::kTestBinaryInvokingCentipedeBinary;
1330+
#else
1331+
const int target_controller_runs = 0;
1332+
#endif
1333+
EXPECT_GT(CountTargetRuns(std_err) - target_controller_runs, 0);
1334+
EXPECT_EQ(CountTargetRuns(std_err) - target_controller_runs,
13261335
CountSubstrs(std_err, "<<FixtureTest::FixtureTest()>>"));
1327-
EXPECT_EQ(CountTargetRuns(std_err),
1336+
EXPECT_EQ(CountTargetRuns(std_err) - target_controller_runs,
13281337
CountSubstrs(std_err, "<<FixtureTest::~FixtureTest()>>"));
13291338
}
13301339

@@ -1823,14 +1832,6 @@ TEST_P(FuzzingModeCrashFindingTest, GTestCrashMetadataIsDumpedIfEnvVarIsSet) {
18231832

18241833
TEST_P(FuzzingModeCrashFindingTest,
18251834
SetupFailureCrashMetadataIsDumpedIfEnvVarIsSet) {
1826-
#ifdef FUZZTEST_USE_CENTIPEDE
1827-
if (GetParam() == ExecutionModelParam::kTestBinary ||
1828-
GetParam() == ExecutionModelParam::kTestBinaryInvokingCentipedeBinary) {
1829-
// TODO(b/393582695): Reconsider how we want to handle setup failures in the
1830-
// single-binary mode.
1831-
GTEST_SKIP() << "Currently not supported in test-binary mode.";
1832-
}
1833-
#endif
18341835
TempDir out_dir;
18351836
const std::string crash_metadata_path = out_dir.path() / "crash_metadata";
18361837
auto [status, std_out, std_err] =

fuzztest/internal/centipede_adaptor.cc

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,19 @@ class CentipedeAdaptorRunnerCallbacks
422422
prng_(GetRandomSeed()) {}
423423

424424
bool Execute(fuzztest::internal::ByteSpan input) override {
425+
[[maybe_unused]] static bool check_if_not_skipped_on_setup = [&] {
426+
if (runtime_.skipping_requested()) {
427+
absl::FPrintF(GetStderr(),
428+
"[.] Skipping %s per request from the test setup.\n",
429+
fuzzer_impl_.test_.full_name());
430+
CentipedeSetFailureDescription("SKIPPED TEST: Requested from setup");
431+
// It has to use _Exit(1) to avoid trigger the reporting of regular
432+
// setup failure while let Centipede be aware of this. Note that this
433+
// skips the fixture teardown.
434+
std::_Exit(1);
435+
}
436+
return true;
437+
}();
425438
// We should avoid doing anything other than executing the input here so
426439
// that we don't affect the execution time.
427440
auto parsed_input =
@@ -728,17 +741,9 @@ bool CentipedeFuzzerAdaptor::Run(int* argc, char*** argv, RunMode mode,
728741
configuration.replay_in_single_process) {
729742
return ReplayCrashInSingleProcess(configuration);
730743
}
731-
int result = EXIT_FAILURE;
732-
bool to_run_controller = false;
733-
fuzzer_impl_.fixture_driver_->RunFuzzTest([&, this]() {
734-
if (runtime_.skipping_requested()) {
735-
absl::FPrintF(GetStderr(),
736-
"[.] Skipping %s per request from the test setup.\n",
737-
test_.full_name());
738-
result = 0;
739-
return;
740-
}
741-
if (runner_mode) {
744+
if (runner_mode) {
745+
std::optional<int> result;
746+
fuzzer_impl_.fixture_driver_->RunFuzzTest([&, this]() {
742747
CentipedeAdaptorRunnerCallbacks runner_callbacks(&runtime_, &fuzzer_impl_,
743748
&configuration);
744749
static char fake_argv0[] = "fake_argv";
@@ -747,21 +752,33 @@ bool CentipedeFuzzerAdaptor::Run(int* argc, char*** argv, RunMode mode,
747752
argc != nullptr ? *argc : 1, argv != nullptr ? *argv : fake_argv,
748753
runner_callbacks);
749754
return;
750-
}
751-
// Centipede engine does not support replay and reproducer minimization
752-
// (within the single process). So use the existing fuzztest implementation.
755+
});
756+
FUZZTEST_INTERNAL_CHECK(result.has_value(),
757+
"No result is set for running fuzz test");
758+
return *result == EXIT_SUCCESS;
759+
} else if (is_running_property_function_in_this_process) {
760+
// If `is_running_property_function_in_this_process` holds at this point. We
761+
// assume it is for `ReplayInputsIfAvailable` to handle `FUZZTEST_REPLAY`
762+
// and `FUZZTEST_MINIMIZE_REPRODUCER`, which Centipede does not support.
753763
// This is fine because it does not require coverage instrumentation.
754-
if (!configuration.crashing_input_to_reproduce.has_value() &&
755-
fuzzer_impl_.ReplayInputsIfAvailable(configuration)) {
756-
result = 0;
764+
FUZZTEST_INTERNAL_CHECK(
765+
std::getenv("FUZZTEST_REPLAY") ||
766+
std::getenv("FUZZTEST_MINIMIZE_REPRODUCER"),
767+
"Both env vars `FUZZTEST_REPLAY` and `FUZZTEST_MINIMIZE_REPRODUCER` "
768+
"are not set when calling the legacy input replaying - this is a "
769+
"FuzzTest bug!");
770+
fuzzer_impl_.fixture_driver_->RunFuzzTest([&, this]() {
771+
FUZZTEST_INTERNAL_CHECK_PRECONDITION(
772+
fuzzer_impl_.ReplayInputsIfAvailable(configuration),
773+
"ReplayInputsIfAvailable failed to handle env vars `FUZZTEST_REPLAY` "
774+
"or `FUZZTEST_MINIMIZE_REPRODUCER`. Please check if they are set "
775+
"properly.");
757776
return;
758-
}
759-
// `ReplayInputsIfAvailable` overwrites the run mode - revert it back.
760-
runtime_.SetRunMode(mode);
761-
to_run_controller = true;
762-
});
763-
if (!to_run_controller) return result == 0;
777+
});
778+
return true;
779+
}
764780
// Run as the fuzzing engine.
781+
int result = EXIT_FAILURE;
765782
[&] {
766783
runtime_.SetShouldTerminateOnNonFatalFailure(false);
767784
std::unique_ptr<TempDir> workdir;

0 commit comments

Comments
 (0)