Fail loudly when FUZZ_TEST is used with custom main() without InitFuzzTest

PiperOrigin-RevId: 998932557
diff --git a/cmake/FuzzTestHelpers.cmake b/cmake/FuzzTestHelpers.cmake
index 2869a77..354e241 100644
--- a/cmake/FuzzTestHelpers.cmake
+++ b/cmake/FuzzTestHelpers.cmake
@@ -433,7 +433,7 @@
   set(generated_include_dir "${generated_target_dir}")
   if (NOT ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX} STREQUAL "")
     set(generated_include_dir "${generated_include_dir}/${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX}")
-    list(APPEND FLATBUFFERS_GENERATE_HEADERS_FLAGS 
+    list(APPEND FLATBUFFERS_GENERATE_HEADERS_FLAGS
          "--include-prefix" ${FLATBUFFERS_GENERATE_HEADERS_INCLUDE_PREFIX})
   endif()
 
diff --git a/e2e_tests/BUILD b/e2e_tests/BUILD
index e58abc9..b392ee6 100644
--- a/e2e_tests/BUILD
+++ b/e2e_tests/BUILD
@@ -48,6 +48,7 @@
         "@com_google_fuzztest//centipede:centipede_uninstrumented",
         "@com_google_fuzztest//e2e_tests/testdata:data",
         "@com_google_fuzztest//e2e_tests/testdata:dynamically_registered_fuzz_tests.stripped",
+        "@com_google_fuzztest//e2e_tests/testdata:fuzz_test_without_init_fuzztest.stripped",
         "@com_google_fuzztest//e2e_tests/testdata:fuzz_tests_for_functional_testing.stripped",
         "@com_google_fuzztest//e2e_tests/testdata:fuzz_tests_with_invalid_seeds.stripped",
         "@com_google_fuzztest//e2e_tests/testdata:llvm_fuzzer_with_custom_mutator.stripped",
diff --git a/e2e_tests/functional_test.cc b/e2e_tests/functional_test.cc
index 943eb72..c3263b2 100644
--- a/e2e_tests/functional_test.cc
+++ b/e2e_tests/functional_test.cc
@@ -730,6 +730,16 @@
               Optional(IsXmlWithExactlyFuzzTestsHavingFuzzTestProperty()));
 }
 
+TEST_F(UnitTestModeTest, FailsLoudlyWhenInitFuzzTestIsNotCalled) {
+  auto [status, std_out, std_err] =
+      RunWithExactFuzzerFlags("*", "testdata/fuzz_test_without_init_fuzztest");
+
+  EXPECT_THAT(status, Ne(ExitCode(0)));
+  EXPECT_THAT_LOG(
+      std_out, HasSubstr("FUZZ_TEST(MySuite, MyFuzzTest) was registered, but "
+                         "InitFuzzTest was never called in main()."));
+}
+
 // Tests for the FuzzTest command line interface.
 class GenericCommandLineInterfaceTest : public ::testing::Test {
  protected:
diff --git a/e2e_tests/testdata/BUILD b/e2e_tests/testdata/BUILD
index 0db3a80..bc41e92 100644
--- a/e2e_tests/testdata/BUILD
+++ b/e2e_tests/testdata/BUILD
@@ -138,6 +138,16 @@
 )
 
 cc_binary(
+    name = "fuzz_test_without_init_fuzztest",
+    testonly = 1,
+    srcs = ["fuzz_test_without_init_fuzztest.cc"],
+    deps = [
+        "@com_google_fuzztest//fuzztest",
+        "@googletest//:gtest",
+    ],
+)
+
+cc_binary(
     name = "fuzz_tests_for_corpus_database_testing",
     testonly = 1,
     srcs = ["fuzz_tests_for_corpus_database_testing.cc"],
diff --git a/e2e_tests/testdata/CMakeLists.txt b/e2e_tests/testdata/CMakeLists.txt
index ec93a80..c1b7eb5 100644
--- a/e2e_tests/testdata/CMakeLists.txt
+++ b/e2e_tests/testdata/CMakeLists.txt
@@ -116,3 +116,19 @@
   PROPERTIES RUNTIME_OUTPUT_DIRECTORY
   "${CMAKE_BINARY_DIR}/_main/e2e_tests/testdata"
 )
+
+add_executable(
+  fuzz_test_without_init_fuzztest.stripped
+  fuzz_test_without_init_fuzztest.cc
+)
+target_link_libraries(
+  fuzz_test_without_init_fuzztest.stripped
+  PRIVATE
+  fuzztest::fuzztest
+  GTest::gtest
+)
+set_target_properties(
+  fuzz_test_without_init_fuzztest.stripped
+  PROPERTIES RUNTIME_OUTPUT_DIRECTORY
+  "${CMAKE_BINARY_DIR}/_main/e2e_tests/testdata"
+)
diff --git a/e2e_tests/testdata/fuzz_test_without_init_fuzztest.cc b/e2e_tests/testdata/fuzz_test_without_init_fuzztest.cc
new file mode 100644
index 0000000..8f95aed
--- /dev/null
+++ b/e2e_tests/testdata/fuzz_test_without_init_fuzztest.cc
@@ -0,0 +1,28 @@
+// Copyright 2026 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "gtest/gtest.h"
+#include "./fuzztest/fuzztest.h"
+
+namespace {
+
+void MyFuzzTest(int) {}
+FUZZ_TEST(MySuite, MyFuzzTest);
+
+}  // namespace
+
+int main(int argc, char** argv) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/fuzztest/BUILD b/fuzztest/BUILD
index ab25066..f6fb89e 100644
--- a/fuzztest/BUILD
+++ b/fuzztest/BUILD
@@ -55,10 +55,13 @@
 
 cc_library(
     name = "fuzztest",
+    testonly = True,
     hdrs = ["fuzztest.h"],
     deps = [
         ":domain",
         ":fuzztest_macros",
+        # TODO(b/570019271): Remove dependency once bug is fixed.
+        "@com_google_fuzztest//fuzztest/internal:googletest_adaptor",
     ],
 )
 
@@ -161,7 +164,6 @@
     testonly = True,
     srcs = ["llvm_fuzzer_wrapper.cc"],
     deps = [
-        ":fuzztest",
         ":fuzztest_macros",
         "@abseil-cpp//absl/base:core_headers",
         "@abseil-cpp//absl/base:no_destructor",
diff --git a/fuzztest/CMakeLists.txt b/fuzztest/CMakeLists.txt
index c42d529..a06867a 100644
--- a/fuzztest/CMakeLists.txt
+++ b/fuzztest/CMakeLists.txt
@@ -92,6 +92,7 @@
   DEPS
     fuzztest::domain
     fuzztest::fuzztest_macros
+    fuzztest::googletest_adaptor
 )
 
 fuzztest_cc_library(
diff --git a/fuzztest/init_fuzztest.cc b/fuzztest/init_fuzztest.cc
index 74c1bc5..5b09d54 100644
--- a/fuzztest/init_fuzztest.cc
+++ b/fuzztest/init_fuzztest.cc
@@ -447,6 +447,8 @@
 
 void InitFuzzTest(int* argc, char*** argv, std::string_view binary_id) {
   auto& runtime = internal::Runtime::instance();
+  runtime.SetInitFuzzTestCalled();
+  runtime.SetArgs(argc, argv);
   const bool is_listing = absl::GetFlag(FUZZTEST_FLAG(list_fuzz_tests));
   if (is_listing) {
     for (const auto& name : ListRegisteredTests()) {
@@ -494,7 +496,9 @@
   internal::Configuration configuration =
       CreateConfigurationsFromFlags(derived_binary_id);
   configuration.reproduction_command_template = reproduction_command_template;
-  internal::RegisterFuzzTestsAsGoogleTests(argc, argv, configuration);
+  runtime.SetInitConfiguration(configuration);
+  internal::RegisterSeparateRegressionTestsForEachCrashingInput(configuration);
+  internal::RegisterGoogleTestEventListener();
 
   const bool is_fuzzing_or_replaying =
       (fuzzing_time_limit || replay_corpus_time_limit);
diff --git a/fuzztest/internal/BUILD b/fuzztest/internal/BUILD
index 1219ada..27f9e67 100644
--- a/fuzztest/internal/BUILD
+++ b/fuzztest/internal/BUILD
@@ -383,6 +383,7 @@
         "@abseil-cpp//absl/container:flat_hash_map",
         "@abseil-cpp//absl/functional:function_ref",
         "@abseil-cpp//absl/strings:string_view",
+        "@com_google_fuzztest//common:logging",
     ] + select({
         "@com_google_fuzztest//fuzztest:use_centipede": [":centipede_adaptor"],
         "//conditions:default": [],
diff --git a/fuzztest/internal/CMakeLists.txt b/fuzztest/internal/CMakeLists.txt
index 1ccc8a3..4f90993 100644
--- a/fuzztest/internal/CMakeLists.txt
+++ b/fuzztest/internal/CMakeLists.txt
@@ -352,6 +352,7 @@
   SRCS
     "registry.cc"
   DEPS
+    fuzztest::common_logging
     fuzztest::compatibility_mode
     fuzztest::fixture_driver
     fuzztest::registration
diff --git a/fuzztest/internal/googletest_adaptor.cc b/fuzztest/internal/googletest_adaptor.cc
index d36d498..44f9f90 100644
--- a/fuzztest/internal/googletest_adaptor.cc
+++ b/fuzztest/internal/googletest_adaptor.cc
@@ -2,6 +2,7 @@
 #include "./fuzztest/internal/googletest_adaptor.h"
 
 #include <cstdlib>
+#include <optional>
 #include <string>
 #include <type_traits>
 #include <utility>
@@ -25,12 +26,13 @@
 
 namespace fuzztest::internal {
 
-std::vector<std::string> GTest_TestAdaptor::GetFuzzTestsInCurrentShard() const {
+std::vector<std::string> GTest_TestAdaptor::GetFuzzTestsInCurrentShard(
+    const Configuration& configuration) const {
   std::vector<std::string> result;
   for (const auto* test : GetRegisteredTests()) {
     if (!test->should_run()) continue;
     if (test->is_in_another_shard()) continue;
-    for (const auto& fuzztest : configuration_.fuzz_tests) {
+    for (const auto& fuzztest : configuration.fuzz_tests) {
       if (fuzztest ==
           absl::StrCat(test->test_suite_name(), ".", test->name())) {
         result.push_back(fuzztest);
@@ -43,13 +45,12 @@
 
 namespace {
 template <typename T>
-void RegisterFuzzTestAsGTest(int* argc, char*** argv, FuzzTest& test,
-                             const Configuration& configuration,
-                             absl::string_view crashing_input_path = "") {
-  auto fixture_factory = [argc, argv, &test,
-                          configuration = configuration]() mutable -> T* {
-    return new ::fuzztest::internal::GTest_TestAdaptor(
-        test, argc, argv, std::move(configuration));
+void RegisterFuzzTestAsGTest(
+    FuzzTest& test, std::optional<Configuration> configuration = std::nullopt,
+    absl::string_view crashing_input_path = "") {
+  auto fixture_factory = [&test,
+                          configuration = std::move(configuration)]() -> T* {
+    return new ::fuzztest::internal::GTest_TestAdaptor(test, configuration);
   };
   if (crashing_input_path.empty()) {
     ::testing::RegisterTest(test.suite_name().c_str(), test.test_name().c_str(),
@@ -72,9 +73,8 @@
 }
 
 template <typename T>
-void RegisterSeparateRegressionTestForEachCrashingInput(
-    int* argc, char*** argv, FuzzTest& test,
-    const Configuration& configuration) {
+void RegisterRegressionTestsForTest(FuzzTest& test,
+                                    const Configuration& configuration) {
   if (!configuration.reproduce_findings_as_separate_tests) return;
 #ifdef FUZZTEST_USE_CENTIPEDE
   const std::vector<std::string> crash_inputs =
@@ -87,31 +87,33 @@
   for (const std::string& input : crash_inputs) {
     Configuration updated_configuration = configuration;
     updated_configuration.crashing_input_to_reproduce = input;
-    RegisterFuzzTestAsGTest<T>(argc, argv, test, updated_configuration, input);
+    RegisterFuzzTestAsGTest<T>(test, updated_configuration, input);
   }
 }
 
-template <typename T>
-void RegisterTests(int* argc, char*** argv, FuzzTest& test,
-                   const Configuration& configuration) {
-  RegisterFuzzTestAsGTest<T>(argc, argv, test, configuration);
-  RegisterSeparateRegressionTestForEachCrashingInput<T>(argc, argv, test,
-                                                        configuration);
-}
-
 }  // namespace
 
-void RegisterFuzzTestsAsGoogleTests(int* argc, char*** argv,
-                                    const Configuration& configuration) {
+void RegisterFuzzTestAsGoogleTest(FuzzTest& test) {
+  if (test.uses_fixture()) {
+    RegisterFuzzTestAsGTest<::fuzztest::internal::GTest_TestAdaptor>(test);
+  } else {
+    RegisterFuzzTestAsGTest<::testing::Test>(test);
+  }
+}
+
+void RegisterSeparateRegressionTestsForEachCrashingInput(
+    const Configuration& configuration) {
   ::fuzztest::internal::ForEachTest([&](auto& test) {
     if (test.uses_fixture()) {
-      RegisterTests<::fuzztest::internal::GTest_TestAdaptor>(argc, argv, test,
-                                                             configuration);
+      RegisterRegressionTestsForTest<::fuzztest::internal::GTest_TestAdaptor>(
+          test, configuration);
     } else {
-      RegisterTests<::testing::Test>(argc, argv, test, configuration);
+      RegisterRegressionTestsForTest<::testing::Test>(test, configuration);
     }
   });
+}
 
+void RegisterGoogleTestEventListener() {
   ::testing::UnitTest::GetInstance()->listeners().Append(
       new ::fuzztest::internal::GTest_EventListener<
           ::testing::EmptyTestEventListener, ::testing::TestPartResult>());
diff --git a/fuzztest/internal/googletest_adaptor.h b/fuzztest/internal/googletest_adaptor.h
index 39ffcab..0303d75 100644
--- a/fuzztest/internal/googletest_adaptor.h
+++ b/fuzztest/internal/googletest_adaptor.h
@@ -16,6 +16,7 @@
 #define FUZZTEST_FUZZTEST_GOOGLETEST_ADAPTOR_H_
 
 #include <cstdlib>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -30,23 +31,33 @@
 
 class GTest_TestAdaptor : public ::testing::Test {
  public:
-  explicit GTest_TestAdaptor(FuzzTest& test, int* argc, char*** argv,
-                             Configuration configuration)
-      : test_(test),
-        argc_(argc),
-        argv_(argv),
-        configuration_(std::move(configuration)) {}
+  explicit GTest_TestAdaptor(
+      FuzzTest& test, std::optional<Configuration> configuration = std::nullopt)
+      : test_(test), configuration_(std::move(configuration)) {}
 
   void TestBody() override {
+    if (!Runtime::instance().init_fuzztest_called()) {
+      ADD_FAILURE()
+          << "FUZZ_TEST(" << test_.suite_name() << ", " << test_.test_name()
+          << ") was registered, but InitFuzzTest was never called in main(). "
+          << "If you are using a custom main(), please call "
+          << "fuzztest::InitFuzzTest(&argc, &argv)"
+          << " before RUN_ALL_TESTS().";
+      return;
+    }
     RecordProperty("fuzz_test", "true");
     auto test = test_.make();
-    configuration_.fuzz_tests_in_current_shard = GetFuzzTestsInCurrentShard();
+    Configuration configuration =
+        configuration_.has_value() ? *configuration_
+                                   : Runtime::instance().init_configuration();
+    configuration.fuzz_tests_in_current_shard =
+        GetFuzzTestsInCurrentShard(configuration);
     // We replay a reproducer in the same process to help debugging when
     // (1) we're replaying a single reproducer and (2) we're running locally.
     const bool running_locally =
         !std::getenv("FUZZTEST_RUNNING_UNDER_CI");
-    configuration_.replay_in_single_process =
-        configuration_.crashing_input_to_reproduce.has_value() &&
+    configuration.replay_in_single_process =
+        configuration.crashing_input_to_reproduce.has_value() &&
         testing::UnitTest::GetInstance()->test_to_run_count() == 1 &&
         running_locally;
     if (Runtime::instance().run_mode() == RunMode::kUnitTest) {
@@ -54,8 +65,8 @@
       // bugs, i.e., run multiple tests that lead to a crash.
 #if defined(GTEST_HAS_DEATH_TEST) && !defined(FUZZTEST_USE_CENTIPEDE)
       const bool needs_subprocess =
-          configuration_.crashing_input_to_reproduce.has_value() &&
-          (!configuration_.replay_in_single_process ||
+          configuration.crashing_input_to_reproduce.has_value() &&
+          (!configuration.replay_in_single_process ||
            // EXPECT_EXIT is required in the death-test subprocess, but in
            // the subprocess there's only one test to run.
            testing::internal::InDeathTestChild());
@@ -63,7 +74,7 @@
       const bool needs_subprocess = false;
 #endif
       if (needs_subprocess) {
-        configuration_.preprocess_crash_reproducing = [] {
+        configuration.preprocess_crash_reproducing = [] {
           // EXPECT_EXIT disables event forwarding in gtest and as a result,
           // EXPECT/ASSERT-s are disabled. Here, we overwrite this option.
           testing::UnitTest::GetInstance()->listeners().SuppressEventForwarding(
@@ -76,7 +87,7 @@
         // test below fails without terminating the process.
 #ifdef GTEST_HAS_DEATH_TEST
         EXPECT_EXIT(
-            (test->RunInUnitTestMode(configuration_),
+            (test->RunInUnitTestMode(configuration),
              void(
                  R"( FuzzTest failure! Please see 'actual message' below for the crash report. )"),
              std::exit(0)),
@@ -85,7 +96,7 @@
         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.";
@@ -93,7 +104,9 @@
     } 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(Runtime::instance().argc(),
+                                         Runtime::instance().argv(),
+                                         configuration) ||
                   Runtime::instance().skipping_requested())
           << "Failure(s) found in the fuzzing mode - please see the test log "
              "for more details.";
@@ -113,12 +126,11 @@
   }
 
  private:
-  std::vector<std::string> GetFuzzTestsInCurrentShard() const;
+  std::vector<std::string> GetFuzzTestsInCurrentShard(
+      const Configuration& configuration) const;
 
   FuzzTest& test_;
-  int* argc_;
-  char*** argv_;
-  Configuration configuration_;
+  std::optional<Configuration> configuration_;
 };
 
 template <typename Base, typename TestPartResult>
@@ -142,9 +154,14 @@
   }
 };
 
-// Registers FUZZ_TEST as GoogleTest TEST-s.
-void RegisterFuzzTestsAsGoogleTests(int* argc, char*** argv,
-                                    const Configuration& configuration);
+// Registers a separate GoogleTest TEST for each crashing input of each
+// FUZZ_TEST when `configuration.reproduce_findings_as_separate_tests` is true.
+void RegisterSeparateRegressionTestsForEachCrashingInput(
+    const Configuration& configuration);
+
+// Registers a GoogleTest event listener that reports assertion failures to
+// FuzzTest.
+void RegisterGoogleTestEventListener();
 
 // Set listing mode validator for GoogleTest to check that fuzz test listing was
 // properly handled.
diff --git a/fuzztest/internal/registry.cc b/fuzztest/internal/registry.cc
index ac695f0..563f684 100644
--- a/fuzztest/internal/registry.cc
+++ b/fuzztest/internal/registry.cc
@@ -21,6 +21,7 @@
 #include "absl/container/flat_hash_map.h"
 #include "absl/functional/function_ref.h"
 #include "absl/strings/string_view.h"
+#include "./common/logging.h"
 #include "./fuzztest/internal/registration.h"
 #include "./fuzztest/internal/runtime.h"
 
@@ -57,8 +58,10 @@
   for (auto& t : Regs()) func(t);
 }
 
-void RegisterImpl(BasicTestInfo test_info, FuzzTestFuzzerFactory factory) {
-  Regs().emplace_back(std::move(test_info), std::move(factory));
+FuzzTest& RegisterImpl(BasicTestInfo test_info, FuzzTestFuzzerFactory factory) {
+  FUZZTEST_CHECK(!Runtime::instance().init_fuzztest_called())
+      << "RegisterFuzzTest() must be called before InitFuzzTest().";
+  return Regs().emplace_back(std::move(test_info), std::move(factory));
 }
 
 void RegisterSetUpTearDownTestSuiteFunctions(
diff --git a/fuzztest/internal/registry.h b/fuzztest/internal/registry.h
index 0e8a446..77acabc 100644
--- a/fuzztest/internal/registry.h
+++ b/fuzztest/internal/registry.h
@@ -34,7 +34,10 @@
 namespace fuzztest {
 namespace internal {
 
-void RegisterImpl(BasicTestInfo test_info, FuzzTestFuzzerFactory factory);
+FuzzTest& RegisterImpl(BasicTestInfo test_info, FuzzTestFuzzerFactory factory);
+
+// TODO(b/570019271): Remove declaration once bug is fixed.
+void RegisterFuzzTestAsGoogleTest(FuzzTest& test);
 
 void ForEachTest(absl::FunctionRef<void(FuzzTest&)> func);
 
@@ -61,8 +64,8 @@
                                               &Fixture::TearDownTestSuite);
     }
     BasicTestInfo test_info = reg.test_info_;
-    RegisterImpl(std::move(test_info),
-                 GetFuzzTestFuzzerFactory(std::move(reg)));
+    RegisterFuzzTestAsGoogleTest(RegisterImpl(
+        std::move(test_info), GetFuzzTestFuzzerFactory(std::move(reg))));
     return *this;
   }
 
@@ -122,8 +125,7 @@
 // fuzz test registration by calling functions `GetRegistration()` and
 // `GetRegistrationWithFixture()`.
 //
-// Make sure to only call this function before calling
-// `RegisterFuzzTestsAsGoogleTests()`.
+// Make sure to only call this function before calling `InitFuzzTest()`.
 template <typename Registration>
 void RegisterFuzzTest(Registration&& reg) {
   ::fuzztest::internal::RegistrationToken{} = std::forward<Registration>(reg);
diff --git a/fuzztest/internal/runtime.h b/fuzztest/internal/runtime.h
index 1e0cbdd..38d16a9 100644
--- a/fuzztest/internal/runtime.h
+++ b/fuzztest/internal/runtime.h
@@ -163,6 +163,28 @@
   void SetRunMode(RunMode run_mode) { run_mode_ = run_mode; }
   RunMode run_mode() const { return run_mode_; }
 
+  // Records that `InitFuzzTest` has been called.
+  void SetInitFuzzTestCalled() { init_fuzztest_called_ = true; }
+  bool init_fuzztest_called() const { return init_fuzztest_called_; }
+
+  // Sets the command-line arguments passed to `InitFuzzTest`. `argc()` and
+  // `argv()` are only valid after `InitFuzzTest` has been called.
+  void SetArgs(int* argc, char*** argv) {
+    argc_ = argc;
+    argv_ = argv;
+  }
+  int* argc() const { return argc_; }
+  char*** argv() const { return argv_; }
+
+  // Sets the initial configuration created by `InitFuzzTest`.
+  // `init_configuration()` is only valid after `InitFuzzTest` has been called.
+  void SetInitConfiguration(Configuration configuration) {
+    init_configuration_ = std::move(configuration);
+  }
+  const Configuration& init_configuration() const {
+    return init_configuration_;
+  }
+
   // Enables the crash reporter.
   // REQUIRES: `SetCurrentTest()` has been called with non-null arguments.
   void EnableReporter(const RuntimeStats* stats, absl::Time (*clock_fn)()) {
@@ -265,6 +287,11 @@
   const RuntimeStats* stats_ = nullptr;
   absl::Time (*clock_fn_)() = nullptr;
 
+  bool init_fuzztest_called_ = false;
+  int* argc_ = nullptr;
+  char*** argv_ = nullptr;
+  Configuration init_configuration_;
+
   // We use a simple custom spinlock instead of absl::Mutex to reduce
   // dependencies and avoid potential issues with code instrumentation.
   class ABSL_LOCKABLE Spinlock {
diff --git a/fuzztest/llvm_fuzzer_wrapper.cc b/fuzztest/llvm_fuzzer_wrapper.cc
index 95e3d7c..ccaead0 100644
--- a/fuzztest/llvm_fuzzer_wrapper.cc
+++ b/fuzztest/llvm_fuzzer_wrapper.cc
@@ -16,7 +16,6 @@
 #include "absl/random/random.h"
 #include "absl/synchronization/mutex.h"
 #include "./common/logging.h"
-#include "./fuzztest/fuzztest.h"
 #include "./fuzztest/fuzztest_macros.h"
 #include "./fuzztest/internal/domains/arbitrary_impl.h"
 #include "./fuzztest/internal/domains/container_of_impl.h"