No public description
PiperOrigin-RevId: 568641066
diff --git a/fuzztest/BUILD b/fuzztest/BUILD
index 2e04944..e150612 100644
--- a/fuzztest/BUILD
+++ b/fuzztest/BUILD
@@ -39,6 +39,7 @@
cc_library(
name = "fuzztest",
+ testonly = True,
srcs = ["fuzztest.cc"],
hdrs = ["fuzztest.h"],
deps = [
@@ -67,6 +68,8 @@
hdrs = ["init_fuzztest.h"],
deps = [
":googletest_adaptor",
+ ":io",
+ ":logging",
":registry",
":runtime",
"@com_google_absl//absl/flags:flag",
@@ -126,6 +129,7 @@
srcs = ["internal/any_test.cc"],
deps = [
":any",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
],
@@ -133,6 +137,7 @@
cc_library(
name = "centipede_adaptor",
+ testonly = True,
srcs = ["internal/centipede_adaptor.cc"],
hdrs = ["internal/centipede_adaptor.h"],
defines = ["FUZZTEST_USE_CENTIPEDE"],
@@ -142,12 +147,14 @@
":logging",
":runtime",
"@com_google_absl//absl/algorithm:container",
+ "@com_google_absl//absl/strings:string_view",
"@com_google_fuzztest//centipede:centipede_runner_no_main",
],
)
cc_library(
name = "compatibility_mode",
+ testonly = True,
srcs = ["internal/compatibility_mode.cc"],
hdrs = ["internal/compatibility_mode.h"],
deps = [
@@ -291,6 +298,7 @@
":fixture_driver",
":logging",
":registration",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_absl//absl/types:span",
"@com_google_googletest//:gtest_main",
],
@@ -304,6 +312,8 @@
deps = [
":registry",
":runtime",
+ "@com_google_absl//absl/functional:function_ref",
+ "@com_google_absl//absl/strings",
"@com_google_googletest//:gtest",
],
)
@@ -335,6 +345,7 @@
deps = [
":fuzztest",
":io",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
],
@@ -378,12 +389,14 @@
":type_support",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/strings:str_format",
+ "@com_google_absl//absl/strings:string_view",
"@com_google_absl//absl/types:span",
],
)
cc_library(
name = "registry",
+ testonly = True,
srcs = ["internal/registry.cc"],
hdrs = ["internal/registry.h"],
deps = [
@@ -435,6 +448,7 @@
":domain",
":runtime",
":test_protobuf_cc_proto",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest_main",
],
@@ -457,6 +471,7 @@
srcs = ["internal/seed_seq_test.cc"],
deps = [
":seed_seq",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/types:span",
"@com_google_googletest//:gtest_main",
@@ -482,6 +497,7 @@
deps = [
":serialization",
":test_protobuf_cc_proto",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_googletest//:gtest_main",
"@com_google_protobuf//:protobuf",
],
@@ -515,6 +531,7 @@
srcs = ["internal/subprocess_test.cc"],
deps = [
":subprocess",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_googletest//:gtest_main",
@@ -536,8 +553,8 @@
name = "table_of_recent_compares_test",
srcs = ["internal/table_of_recent_compares_test.cc"],
deps = [
- ":domain",
":table_of_recent_compares",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_absl//absl/random",
"@com_google_googletest//:gtest_main",
],
@@ -575,6 +592,7 @@
":domain",
":test_protobuf_cc_proto",
":type_support",
+ "@com_google_absl//absl/functional:function_ref",
"@com_google_absl//absl/numeric:int128",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
diff --git a/fuzztest/init_fuzztest.cc b/fuzztest/init_fuzztest.cc
index 9d05df0..9592ee3 100644
--- a/fuzztest/init_fuzztest.cc
+++ b/fuzztest/init_fuzztest.cc
@@ -10,10 +10,14 @@
#include "gtest/gtest.h"
#include "absl/flags/flag.h"
#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
+#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "./fuzztest/internal/googletest_adaptor.h"
+#include "./fuzztest/internal/io.h"
+#include "./fuzztest/internal/logging.h"
#include "./fuzztest/internal/registry.h"
#include "./fuzztest/internal/runtime.h"
@@ -124,6 +128,22 @@
std::exit(0);
}
+ const std::vector<std::string_view> binary_parts =
+ absl::StrSplit(*argv[0], "_replay_");
+ if (CheckCorpus) {
+ CheckCorpus(binary_parts[0]);
+ }
+
+ FUZZTEST_INTERNAL_CHECK(
+ internal::Runtime::instance().files_to_replay().empty(),
+ "You cannot manually set corpus files");
+ std::vector<std::string> corpus_files = internal::GetFileOrFilesInDir(
+ absl::StrCat("security/laser/sundew/blaze/corpora/", binary_parts[0],
+ "/minimized"));
+ if (!corpus_files.empty()) {
+ internal::Runtime::instance().SetFilesToReplay(corpus_files);
+ }
+
const auto test_to_fuzz = absl::GetFlag(FUZZTEST_FLAG(fuzz));
const bool is_test_to_fuzz_specified = test_to_fuzz != kUnspecified;
if (is_test_to_fuzz_specified) {
@@ -140,7 +160,16 @@
internal::Runtime::instance().SetFuzzTimeLimit(duration);
}
- internal::RegisterFuzzTestsAsGoogleTests(argc, argv);
+ std::vector<std::string> crashing_files;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ const bool reproduce_crashes = binary_parts.size() > 1;
+ if (reproduce_crashes) {
+ crashing_files = internal::GetFileOrFilesInDir(
+ absl::StrCat("security/laser/sundew/blaze/corpora/", binary_parts[0],
+ "/crashing_inputs"));
+ }
+#endif
+ internal::RegisterFuzzTestsAsGoogleTests(argc, argv, crashing_files);
const RunMode run_mode = is_test_to_fuzz_specified || is_duration_specified
? RunMode::kFuzz
diff --git a/fuzztest/init_fuzztest.h b/fuzztest/init_fuzztest.h
index 547e7ff..8e5f57a 100644
--- a/fuzztest/init_fuzztest.h
+++ b/fuzztest/init_fuzztest.h
@@ -54,6 +54,8 @@
// REQUIRES: Binary must be built with SanCov instrumentation on.
void RunSpecifiedFuzzTest(std::string_view name);
+void __attribute__((weak)) CheckCorpus(std::string_view corpus);
+
} // namespace fuzztest
#endif // FUZZTEST_FUZZTEST_INIT_FUZZTEST_H_
diff --git a/fuzztest/internal/any_test.cc b/fuzztest/internal/any_test.cc
index d073fc3..6ea51d2 100644
--- a/fuzztest/internal/any_test.cc
+++ b/fuzztest/internal/any_test.cc
@@ -20,9 +20,13 @@
#include <utility>
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "absl/strings/str_cat.h"
namespace fuzztest::internal {
+
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
TEST(CopyableAny, BasicOperationsWork) {
diff --git a/fuzztest/internal/centipede_adaptor.cc b/fuzztest/internal/centipede_adaptor.cc
index be8fd66..16a5e6f 100644
--- a/fuzztest/internal/centipede_adaptor.cc
+++ b/fuzztest/internal/centipede_adaptor.cc
@@ -19,6 +19,7 @@
#include <cstring>
#include <functional>
#include <memory>
+#include <optional>
#include <random>
#include <string>
#include <thread>
@@ -26,6 +27,7 @@
#include <vector>
#include "absl/algorithm/container.h"
+#include "absl/strings/string_view.h"
#include "./centipede/runner_interface.h"
#include "./fuzztest/internal/domains/domain_base.h"
#include "./fuzztest/internal/logging.h"
@@ -154,9 +156,10 @@
const FuzzTest& test, std::unique_ptr<UntypedFixtureDriver> fixture_driver)
: test_(test), fuzzer_impl_(test_, std::move(fixture_driver)) {}
-void CentipedeFuzzerAdaptor::RunInUnitTestMode() {
+void CentipedeFuzzerAdaptor::RunInUnitTestMode(
+ std::optional<absl::string_view> input) {
// Run the unit test mode directly without using Centipede.
- fuzzer_impl_.RunInUnitTestMode();
+ fuzzer_impl_.RunInUnitTestMode(input);
}
int CentipedeFuzzerAdaptor::RunInFuzzingMode(int* argc, char*** argv) {
diff --git a/fuzztest/internal/centipede_adaptor.h b/fuzztest/internal/centipede_adaptor.h
index 4ce3033..e0d256f 100644
--- a/fuzztest/internal/centipede_adaptor.h
+++ b/fuzztest/internal/centipede_adaptor.h
@@ -27,7 +27,7 @@
public:
CentipedeFuzzerAdaptor(const FuzzTest& test,
std::unique_ptr<UntypedFixtureDriver> fixture_driver);
- void RunInUnitTestMode() override;
+ void RunInUnitTestMode(std::optional<absl::string_view> input) override;
int RunInFuzzingMode(int* argc, char*** argv) override;
private:
diff --git a/fuzztest/internal/fixture_driver_test.cc b/fuzztest/internal/fixture_driver_test.cc
index 8459ade..fd6ec6a 100644
--- a/fuzztest/internal/fixture_driver_test.cc
+++ b/fuzztest/internal/fixture_driver_test.cc
@@ -19,6 +19,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "absl/types/span.h"
#include "./fuzztest/domain_core.h"
#include "./fuzztest/internal/any.h"
@@ -26,6 +27,9 @@
#include "./fuzztest/internal/registration.h"
namespace fuzztest::internal {
+
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
using ::testing::UnorderedElementsAre;
diff --git a/fuzztest/internal/googletest_adaptor.cc b/fuzztest/internal/googletest_adaptor.cc
index e2c2952..eb30ecd 100644
--- a/fuzztest/internal/googletest_adaptor.cc
+++ b/fuzztest/internal/googletest_adaptor.cc
@@ -1,18 +1,36 @@
#include "./fuzztest/internal/googletest_adaptor.h"
+#include <optional>
+#include <string>
+#include <vector>
+
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
+#include "absl/strings/str_cat.h"
#include "./fuzztest/internal/registry.h"
namespace fuzztest::internal {
-void RegisterFuzzTestsAsGoogleTests(int* argc, char*** argv) {
+void RunExpectExit(absl::FunctionRef<void()> test) {
+#if defined(__APPLE__) || defined(_MSC_VER)
+ test();
+#else
+ EXPECT_EXIT(test(), ::testing::ExitedWithCode(0), "");
+#endif
+}
+
+#define run
+void RegisterFuzzTestsAsGoogleTests(
+ int* argc, char*** argv, const std::vector<std::string>& crashing_inputs) {
::fuzztest::internal::ForEachTest([&](auto& test) {
auto fixture_factory =
[argc, argv, &test]() -> ::fuzztest::internal::GTest_TestAdaptor* {
- return new ::fuzztest::internal::GTest_TestAdaptor(test, argc, argv);
+ return new ::fuzztest::internal::GTest_TestAdaptor(test, argc, argv,
+ std::nullopt);
};
auto test_factory = [argc, argv, &test]() -> ::testing::Test* {
- return new ::fuzztest::internal::GTest_TestAdaptor(test, argc, argv);
+ return new ::fuzztest::internal::GTest_TestAdaptor(test, argc, argv,
+ std::nullopt);
};
if (test.uses_fixture()) {
::testing::RegisterTest(test.suite_name(), test.test_name(), nullptr,
diff --git a/fuzztest/internal/googletest_adaptor.h b/fuzztest/internal/googletest_adaptor.h
index 9b96d22..64b99d9 100644
--- a/fuzztest/internal/googletest_adaptor.h
+++ b/fuzztest/internal/googletest_adaptor.h
@@ -17,9 +17,11 @@
#include <cstdlib>
#include <memory>
+#include <optional>
#include <utility>
#include "gtest/gtest.h"
+#include "absl/strings/string_view.h"
#include "./fuzztest/internal/registry.h"
#include "./fuzztest/internal/runtime.h"
@@ -27,13 +29,18 @@
class GTest_TestAdaptor : public ::testing::Test {
public:
- explicit GTest_TestAdaptor(FuzzTest& test, int* argc, char*** argv)
- : test_(test), argc_(argc), argv_(argv) {}
+ explicit GTest_TestAdaptor(FuzzTest& test, int* argc, char*** argv,
+ std::optional<absl::string_view> input)
+ : test_(test), argc_(argc), argv_(argv), input_(input) {}
void TestBody() override {
- auto test = std::move(test_).make();
+ std::cout << "In Test Body..." << std::endl;
+ std::cout << "unit test? "
+ << (Runtime::instance().run_mode() == RunMode::kUnitTest)
+ << std::endl;
+ auto test = test_.make();
if (Runtime::instance().run_mode() == RunMode::kUnitTest) {
- test->RunInUnitTestMode();
+ test->RunInUnitTestMode(input_);
} else {
ASSERT_EQ(0, test->RunInFuzzingMode(argc_, argv_)) << "Fuzzing failure.";
}
@@ -55,6 +62,7 @@
FuzzTest& test_;
int* argc_;
char*** argv_;
+ std::optional<absl::string_view> input_;
};
template <typename Base, typename TestPartResult>
@@ -77,7 +85,8 @@
};
// Registers FUZZ_TEST as GoogleTest TEST-s.
-void RegisterFuzzTestsAsGoogleTests(int* argc, char*** argv);
+void RegisterFuzzTestsAsGoogleTests(
+ int* argc, char*** argv, const std::vector<std::string>& crashing_inputs);
} // namespace fuzztest::internal
diff --git a/fuzztest/internal/io.cc b/fuzztest/internal/io.cc
index 14dc4b2..6804f72 100644
--- a/fuzztest/internal/io.cc
+++ b/fuzztest/internal/io.cc
@@ -65,6 +65,10 @@
FUZZTEST_INTERNAL_CHECK(false, "Can't replay in iOS/MacOS");
}
+std::vector<std::string> GetFileOrFilesInDir(std::string_view file_or_dir) {
+ FUZZTEST_INTERNAL_CHECK(false, "Can't replay in iOS/MacOS");
+}
+
#else // defined(__APPLE__)
bool WriteFile(std::string_view filename, std::string_view contents) {
@@ -134,6 +138,36 @@
return out;
}
+namespace {
+
+void GetAllFilesRecursively(std::string_view dir,
+ std::vector<std::string>& files) {
+ std::vector<std::string> entries = ListDirectory(dir);
+ for (const auto& entry : entries) {
+ absl::FPrintF(GetStderr(), "entry: %s\n", entry);
+ if (!std::filesystem::is_directory(entry)) {
+ files.push_back(entry);
+ } else {
+ GetAllFilesRecursively(entry, files);
+ }
+ }
+}
+
+} // namespace
+
+std::vector<std::string> GetFileOrFilesInDir(std::string_view file_or_dir) {
+ // Try as a directory path first.
+ std::vector<std::string> files;
+ GetAllFilesRecursively(file_or_dir, files);
+ // If not, consider it a file path.
+ if (files.empty()) {
+ if (std::filesystem::is_regular_file(file_or_dir)) {
+ files.push_back(std::string(file_or_dir));
+ }
+ }
+ return files;
+}
+
#endif // defined(STUB_FILESYSTEM)
} // namespace fuzztest::internal
diff --git a/fuzztest/internal/io.h b/fuzztest/internal/io.h
index 22e12b5..84365fe 100644
--- a/fuzztest/internal/io.h
+++ b/fuzztest/internal/io.h
@@ -46,6 +46,8 @@
// returns an empty list.
std::vector<std::string> ListDirectory(std::string_view dir);
+std::vector<std::string> GetFileOrFilesInDir(std::string_view file_or_dir);
+
} // namespace fuzztest::internal
#endif // FUZZTEST_FUZZTEST_INTERNAL_IO_H_
diff --git a/fuzztest/internal/io_test.cc b/fuzztest/internal/io_test.cc
index 98841f1..7029e5a 100644
--- a/fuzztest/internal/io_test.cc
+++ b/fuzztest/internal/io_test.cc
@@ -27,10 +27,14 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "absl/strings/str_cat.h"
#include "./fuzztest/fuzztest.h"
namespace fuzztest::internal {
+
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
using ::testing::Eq;
diff --git a/fuzztest/internal/registration.h b/fuzztest/internal/registration.h
index c9e032c..7b0e940 100644
--- a/fuzztest/internal/registration.h
+++ b/fuzztest/internal/registration.h
@@ -26,6 +26,7 @@
#include "absl/functional/any_invocable.h"
#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "./fuzztest/domain.h"
#include "./fuzztest/internal/domains/aggregate_of_impl.h"
@@ -41,6 +42,7 @@
const char* file = nullptr;
int line = 0;
bool uses_fixture = false;
+ std::function<void*(absl::string_view)> factory;
};
// Use base classes to progressively add members/behavior to the registerer
diff --git a/fuzztest/internal/registry.h b/fuzztest/internal/registry.h
index a169308..699d1e9 100644
--- a/fuzztest/internal/registry.h
+++ b/fuzztest/internal/registry.h
@@ -15,6 +15,8 @@
#ifndef FUZZTEST_FUZZTEST_INTERNAL_REGISTRY_H_
#define FUZZTEST_FUZZTEST_INTERNAL_REGISTRY_H_
+#include <stdbool.h>
+
#include <memory>
#include <string_view>
#include <type_traits>
diff --git a/fuzztest/internal/runtime.cc b/fuzztest/internal/runtime.cc
index d2089db..041245e 100644
--- a/fuzztest/internal/runtime.cc
+++ b/fuzztest/internal/runtime.cc
@@ -57,6 +57,8 @@
namespace fuzztest::internal {
+extern void RunExpectExit(absl::FunctionRef<void()> test);
+
void (*crash_handler_hook)();
void Runtime::DumpReproducer(std::string_view outdir) const {
@@ -315,9 +317,8 @@
}
bool FuzzTestFuzzerImpl::ReplayInputsIfAvailable() {
- runtime_.SetRunMode(RunMode::kFuzz);
-
- if (const auto file_paths = GetFilesToReplay()) {
+ if (bool early_return;
+ const auto file_paths = GetFilesToReplay(early_return)) {
for (const std::string& path : *file_paths) {
const auto content = ReadFile(path);
if (!content) {
@@ -337,9 +338,10 @@
absl::FPrintF(GetStderr(), "[.] Replaying %s\n", path);
RunOneInput({*corpus_value});
}
- return true;
+ if (early_return) return true;
}
+ runtime_.SetRunMode(RunMode::kFuzz);
if (const auto to_minimize = ReadReproducerToMinimize()) {
absl::FPrintF(GetStderr(),
"[!] Looking for smaller mutations indefinitely: please "
@@ -386,16 +388,17 @@
return false;
}
-std::optional<std::vector<std::string>> FuzzTestFuzzerImpl::GetFilesToReplay() {
+std::optional<std::vector<std::string>> FuzzTestFuzzerImpl::GetFilesToReplay(
+ bool& early_return) {
auto file_or_dir = absl::NullSafeStringView(getenv("FUZZTEST_REPLAY"));
- if (file_or_dir.empty()) return std::nullopt;
- // Try as a directory path first.
- std::vector<std::string> files = ListDirectory(std::string(file_or_dir));
- // If not, consider it a file path.
- if (files.empty()) {
- files.push_back(std::string(file_or_dir));
+ if (file_or_dir.empty()) {
+ early_return = false;
+ auto result = Runtime::instance().files_to_replay();
+ if (result.empty()) return std::nullopt;
+ return result;
}
- return files;
+ early_return = true;
+ return GetFileOrFilesInDir(file_or_dir);
}
std::optional<corpus_type> FuzzTestFuzzerImpl::ReadReproducerToMinimize() {
@@ -599,12 +602,36 @@
}
}
-void FuzzTestFuzzerImpl::RunInUnitTestMode() {
+void FuzzTestFuzzerImpl::RunInUnitTestMode(
+ std::optional<absl::string_view> input) {
+ // std::cout << "In UnitTest mode" << std::endl;
fixture_driver_->SetUpFuzzTest();
[&] {
runtime_.EnableReporter(&stats_, [] { return absl::Now(); });
runtime_.SetCurrentTest(&test_);
+ if (input.has_value()) {
+ // std::cout << "has crashing input!" << std::endl;
+ const auto content = ReadFile(*input);
+ if (!content) {
+ absl::FPrintF(GetStderr(),
+ "[!] Failed to read FUZZTEST_REPLAY file or directory "
+ "(might be empty): %s\n",
+ *input);
+ } else {
+ auto corpus_value = TryParse(*content);
+ if (!corpus_value) {
+ absl::FPrintF(GetStderr(),
+ "[!] Skipping invalid input file %s.\n===\n%s\n===\n",
+ *input, *content);
+ } else {
+ absl::FPrintF(GetStderr(), "[.] Replaying %s\n", *input);
+ RunOneInput({*corpus_value}, /*expect_pass=*/true);
+ }
+ }
+ return;
+ }
+
// TODO(sbenzaquen): Currently, some infrastructure code assumes that replay
// works in unit test mode, so we support it. However, we would like to
// limit replaying to fuzzing mode only, where we can guarantee that only
@@ -660,7 +687,7 @@
}
FuzzTestFuzzerImpl::RunResult FuzzTestFuzzerImpl::RunOneInput(
- const Input& input) {
+ const Input& input, bool expect_pass) {
++stats_.runs;
auto untyped_args = params_domain_->UntypedGetValue(input.args);
Runtime::Args debug_args{input.args, *params_domain_};
@@ -681,7 +708,11 @@
}
fixture_driver_->SetUpIteration();
- fixture_driver_->Test(std::move(untyped_args));
+ if (expect_pass) {
+ RunExpectExit([&]() { fixture_driver_->Test(std::move(untyped_args)); });
+ } else {
+ fixture_driver_->Test(std::move(untyped_args));
+ }
fixture_driver_->TearDownIteration();
if (execution_coverage_ != nullptr) {
execution_coverage_->SetIsTracing(false);
diff --git a/fuzztest/internal/runtime.h b/fuzztest/internal/runtime.h
index 085963f..d430014 100644
--- a/fuzztest/internal/runtime.h
+++ b/fuzztest/internal/runtime.h
@@ -64,7 +64,7 @@
class FuzzTestFuzzer {
public:
virtual ~FuzzTestFuzzer() = default;
- virtual void RunInUnitTestMode() = 0;
+ virtual void RunInUnitTestMode(std::optional<absl::string_view> input) = 0;
// Returns fuzzing mode's exit code. Zero indicates success.
virtual int RunInFuzzingMode(int* argc, char*** argv) = 0;
};
@@ -151,6 +151,15 @@
}
absl::Duration fuzz_time_limit() const { return fuzz_time_limit_; }
+ void SetFilesToReplay(absl::Span<const std::string> files_to_replay) {
+ FUZZTEST_INTERNAL_CHECK(files_to_replay_.empty(),
+ "Replay files are set already!");
+ files_to_replay_ = std::vector<std::string>(files_to_replay.begin(),
+ files_to_replay.end());
+ }
+
+ std::vector<std::string>& files_to_replay() { return files_to_replay_; }
+
void EnableReporter(const RuntimeStats* stats, absl::Time (*clock_fn)()) {
reporter_enabled_ = true;
stats_ = stats;
@@ -200,6 +209,7 @@
RunMode run_mode_ = RunMode::kUnitTest;
absl::Duration fuzz_time_limit_ = absl::InfiniteDuration();
+ std::vector<std::string> files_to_replay_;
bool reporter_enabled_ = false;
Args* current_args_ = nullptr;
@@ -230,7 +240,7 @@
private:
// TODO(fniksic): Refactor to reduce code complexity and improve readability.
- void RunInUnitTestMode() override;
+ void RunInUnitTestMode(std::optional<absl::string_view> input) override;
// TODO(fniksic): Refactor to reduce code complexity and improve readability.
int RunInFuzzingMode(int* argc, char*** argv) override;
@@ -255,7 +265,7 @@
bool ReplayInputsIfAvailable();
- std::optional<std::vector<std::string>> GetFilesToReplay();
+ std::optional<std::vector<std::string>> GetFilesToReplay(bool& early_return);
std::optional<corpus_type> ReadReproducerToMinimize();
@@ -291,7 +301,7 @@
void InitializeCorpus(absl::BitGenRef prng);
- RunResult RunOneInput(const Input& input);
+ RunResult RunOneInput(const Input& input, bool expect_pass = false);
bool ShouldStop();
diff --git a/fuzztest/internal/runtime_test.cc b/fuzztest/internal/runtime_test.cc
index 0fbbad9..c063ea2 100644
--- a/fuzztest/internal/runtime_test.cc
+++ b/fuzztest/internal/runtime_test.cc
@@ -19,11 +19,14 @@
#include <tuple>
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "absl/time/time.h"
#include "./fuzztest/domain.h"
#include "./fuzztest/internal/test_protobuf.pb.h"
namespace fuzztest::internal {
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
TEST(OnFailureTest, Output) {
diff --git a/fuzztest/internal/seed_seq_test.cc b/fuzztest/internal/seed_seq_test.cc
index 5f9ed7a..6208823 100644
--- a/fuzztest/internal/seed_seq_test.cc
+++ b/fuzztest/internal/seed_seq_test.cc
@@ -26,12 +26,16 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/types/span.h"
namespace fuzztest::internal {
+
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
using ::testing::ElementsAre;
diff --git a/fuzztest/internal/serialization_test.cc b/fuzztest/internal/serialization_test.cc
index 7780f9b..ba09c1f 100644
--- a/fuzztest/internal/serialization_test.cc
+++ b/fuzztest/internal/serialization_test.cc
@@ -30,11 +30,15 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "./fuzztest/internal/test_protobuf.pb.h"
#include "google/protobuf/text_format.h"
#include "google/protobuf/util/message_differencer.h"
namespace fuzztest::internal {
+
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
using testing::_;
diff --git a/fuzztest/internal/subprocess_test.cc b/fuzztest/internal/subprocess_test.cc
index bfb3c3a..146bdd2 100644
--- a/fuzztest/internal/subprocess_test.cc
+++ b/fuzztest/internal/subprocess_test.cc
@@ -20,10 +20,14 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "absl/strings/str_cat.h"
#include "absl/time/time.h"
namespace fuzztest::internal {
+
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
using ::testing::HasSubstr;
diff --git a/fuzztest/internal/table_of_recent_compares_test.cc b/fuzztest/internal/table_of_recent_compares_test.cc
index 9178744..01146c3 100644
--- a/fuzztest/internal/table_of_recent_compares_test.cc
+++ b/fuzztest/internal/table_of_recent_compares_test.cc
@@ -7,9 +7,13 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "absl/random/random.h"
namespace fuzztest::internal {
+
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
// TODO(JunyangShao) : Make these functions neater (https://abseil.io/tips/122).
diff --git a/fuzztest/internal/type_support_test.cc b/fuzztest/internal/type_support_test.cc
index 9a119ba..fd626de 100644
--- a/fuzztest/internal/type_support_test.cc
+++ b/fuzztest/internal/type_support_test.cc
@@ -35,6 +35,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "absl/functional/function_ref.h"
#include "absl/numeric/int128.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
@@ -44,6 +45,9 @@
#include "./fuzztest/internal/test_protobuf.pb.h"
namespace fuzztest::internal {
+
+void RunExpectExit(absl::FunctionRef<void()> test) { test(); }
+
namespace {
using ::testing::AllOf;