Internal change

PiperOrigin-RevId: 521826652
diff --git a/e2e_tests/functional_test.cc b/e2e_tests/functional_test.cc
index 8bdbc7f..bada079 100644
--- a/e2e_tests/functional_test.cc
+++ b/e2e_tests/functional_test.cc
@@ -316,6 +316,14 @@
       1, CountSubstrs(std_err, "<<CallCountGoogleTest::TearDownTestSuite()>>"));
 }
 
+TEST(UnitTestModeTest, DynamicFuzzTestsAreUsed) {
+  auto [status, std_out, std_err] =
+      RunWith(GetGTestFilterFlag("MySuiteSeedsFixture.AddCall"));
+  EXPECT_THAT(
+      std_err,
+      HasSubstr("<MySuiteSeedsFixture::GuessedUnguessableExampleSeed>>"));
+}
+
 TEST(UnitTestModeTest, GoogleTestWorksWithProtoExtensionsUsedInSeeds) {
   auto [status, std_out, std_err] =
       RunWith(GetGTestFilterFlag("MySuite.CheckProtoExtensions"));
diff --git a/e2e_tests/testdata/BUILD b/e2e_tests/testdata/BUILD
index 382143e..b49dbf0 100644
--- a/e2e_tests/testdata/BUILD
+++ b/e2e_tests/testdata/BUILD
@@ -42,6 +42,7 @@
     name = "fuzz_tests_for_functional_testing",
     testonly = 1,
     srcs = [
+        "fuzz_test_with_dynamic_seeds.cc",
         "fuzz_tests_for_functional_testing.cc",
         "fuzz_tests_for_microbenchmarking.cc",
         "fuzz_tests_using_googletest.cc",
diff --git a/e2e_tests/testdata/fuzz_test_with_dynamic_seeds.cc b/e2e_tests/testdata/fuzz_test_with_dynamic_seeds.cc
new file mode 100644
index 0000000..fd03192
--- /dev/null
+++ b/e2e_tests/testdata/fuzz_test_with_dynamic_seeds.cc
@@ -0,0 +1,39 @@
+// Copyright 2022 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
+//
+//      http://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.
+
+// Example fuzz tests that require GoogleTest, for functional testing.
+//
+// Used by `functional_test` only. We separate these into a different .cc file
+// to show that regular FUZZ_TEST work without having to #include GoogleTest.
+
+#include <cstdio>
+#include <limits>
+
+#include "gtest/gtest.h"
+#include "./fuzztest/fuzztest.h"
+#include "./fuzztest/googletest_fixture_adapter.h"
+
+struct MySuiteSeedsFixture {
+  void AddCall(std::string s) {
+    if (s == "UnguessableExampleSeed") {
+      fprintf(stderr,
+              "<<MySuiteSeedsFixture::GuessedUnguessableExampleSeed>>\n");
+    }
+  }
+
+  std::vector<std::tuple<std::string>> GetDynamicFuzzTestSeeds() {
+    return {"UnguessableExampleSeed"};
+  }
+};
+FUZZ_TEST_F(MySuiteSeedsFixture, AddCall);
diff --git a/fuzztest/BUILD b/fuzztest/BUILD
index 7bd5dc7..72b487c 100644
--- a/fuzztest/BUILD
+++ b/fuzztest/BUILD
@@ -160,6 +160,7 @@
     srcs = ["internal/fixture_driver.cc"],
     hdrs = ["internal/fixture_driver.h"],
     deps = [
+        ":domain",
         ":logging",
         ":registration",
         ":type_support",
@@ -171,6 +172,7 @@
     size = "small",
     srcs = ["internal/fixture_driver_test.cc"],
     deps = [
+        ":any",
         ":domain",
         ":fixture_driver",
         ":registration",
diff --git a/fuzztest/internal/fixture_driver.cc b/fuzztest/internal/fixture_driver.cc
index e5c5443..c175c88 100644
--- a/fuzztest/internal/fixture_driver.cc
+++ b/fuzztest/internal/fixture_driver.cc
@@ -25,9 +25,15 @@
 void UntypedFixtureDriver::SetUpIteration() {}
 void UntypedFixtureDriver::TearDownIteration() {}
 void UntypedFixtureDriver::TearDownFuzzTest() {}
+std::vector<GenericDomainCorpusType> GetDynamicSeeds() { return {}; }
+
 std::vector<GenericDomainCorpusType> UntypedFixtureDriver::GetSeeds() const {
   return seeds_;
 }
+std::vector<GenericDomainCorpusType> UntypedFixtureDriver::GetDynamicSeeds() {
+  return {};
+}
+
 std::unique_ptr<UntypedDomainInterface> UntypedFixtureDriver::GetDomains()
     const {
   return domain_->Clone();
diff --git a/fuzztest/internal/fixture_driver.h b/fuzztest/internal/fixture_driver.h
index fc55add..77e8523 100644
--- a/fuzztest/internal/fixture_driver.h
+++ b/fuzztest/internal/fixture_driver.h
@@ -16,10 +16,12 @@
 #define FUZZTEST_FUZZTEST_INTERNAL_FIXTURE_DRIVER_H_
 
 #include <memory>
+#include <tuple>
 #include <type_traits>
 #include <utility>
 #include <vector>
 
+#include "./fuzztest/internal/domains/domain_base.h"
 #include "./fuzztest/internal/logging.h"
 #include "./fuzztest/internal/registration.h"
 #include "./fuzztest/internal/type_support.h"
@@ -78,6 +80,7 @@
   virtual void Test(MoveOnlyAny&& args_untyped) const = 0;
 
   std::vector<GenericDomainCorpusType> GetSeeds() const;
+  virtual std::vector<GenericDomainCorpusType> GetDynamicSeeds();
   std::unique_ptr<UntypedDomainInterface> GetDomains() const;
 
  private:
@@ -205,6 +208,16 @@
   using FixtureDriver<DomainT, NoFixture, TargetFunction>::FixtureDriver;
 };
 
+// HasGetDynamicSeeds<T>::value is true_type if T has a
+// GetDynamicSeeds() member.
+template <typename T, typename = void>
+struct HasGetDynamicFuzzTestSeeds : std::false_type {};
+
+template <typename T>
+struct HasGetDynamicFuzzTestSeeds<
+    T, std::void_t<decltype(std::declval<T>().GetDynamicFuzzTestSeeds())>>
+    : std::true_type {};
+
 // The fixture driver for default-constructible classes that act like fixtures:
 // their setup is in the constructor, teardown is in the destructor, and they
 // have a target function. Such fixtures are instantiated and destructed once
@@ -223,6 +236,19 @@
     this->fixture_ = std::make_unique<Fixture>();
   }
   void TearDownFuzzTest() override { this->fixture_ = nullptr; }
+
+  std::vector<GenericDomainCorpusType> GetDynamicSeeds() override {
+    std::vector<GenericDomainCorpusType> seeds;
+    if constexpr (HasGetDynamicFuzzTestSeeds<Fixture>::value) {
+      auto typed_seeds = this->fixture_->GetDynamicFuzzTestSeeds();
+      seeds.reserve(typed_seeds.size());
+      for (auto& seed : typed_seeds) {
+        seeds.emplace_back(std::in_place_type<std::decay_t<decltype(seed)>>,
+                           std::move(seed));
+      }
+    }
+    return seeds;
+  }
 };
 
 // The fixture driver for test fixtures with explicit setup that assume the
diff --git a/fuzztest/internal/fixture_driver_test.cc b/fuzztest/internal/fixture_driver_test.cc
index 45f6f26..2394a09 100644
--- a/fuzztest/internal/fixture_driver_test.cc
+++ b/fuzztest/internal/fixture_driver_test.cc
@@ -17,11 +17,13 @@
 #include <string>
 #include <tuple>
 #include <type_traits>
+#include <vector>
 
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "absl/types/span.h"
 #include "./fuzztest/domain.h"
+#include "./fuzztest/internal/any.h"
 #include "./fuzztest/internal/registration.h"
 #include "./fuzztest/internal/type_support.h"
 
@@ -98,6 +100,37 @@
   EXPECT_EQ(CallCountFixture::call_count, 3);
 }
 
+struct SeedsFixture {
+  void AddCall(int n) { calls.push_back(n); }
+  inline static std::vector<int> calls;
+  inline static std::vector<int> dynamic_seeds;
+
+  std::vector<int> GetDynamicFuzzTestSeeds() {
+    std::vector<int> ret;
+    ret.swap(dynamic_seeds);
+    return ret;
+  }
+};
+
+using AddCallFunc = decltype(&SeedsFixture::AddCall);
+using AddCallRegBase = DefaultRegistrationBase<CallCountFixture, AddCallFunc>;
+
+TEST(FixtureDriverTest, DynamicSeeds) {
+  FixtureDriverImpl<Domain<std::tuple<int>>, SeedsFixture, AddCallFunc>
+      fixture_driver(&SeedsFixture::AddCall, Arbitrary<std::tuple<int>>(), {});
+
+  fixture_driver.SetUpFuzzTest();
+  std::vector<int> seeds = {177, 182731};
+  SeedsFixture::dynamic_seeds = seeds;
+
+  auto output_seeds = fixture_driver.GetDynamicSeeds();
+  std::vector<int> int_outputs;
+  for (const auto& output_seed : output_seeds) {
+    int_outputs.push_back(output_seed.GetAs<int>());
+  }
+  EXPECT_THAT(int_outputs, UnorderedElementsAre(177, 182731));
+}
+
 struct LifecycleRecordingFixture {
   LifecycleRecordingFixture() { was_constructed = true; }
   ~LifecycleRecordingFixture() { was_destructed = true; }
diff --git a/fuzztest/internal/runtime.cc b/fuzztest/internal/runtime.cc
index 8d1a049..2bb7785 100644
--- a/fuzztest/internal/runtime.cc
+++ b/fuzztest/internal/runtime.cc
@@ -585,6 +585,10 @@
     TrySampleAndUpdateInMemoryCorpus(Input{seed},
                                      /*write_to_file=*/false);
   }
+  for (const auto& seed : fixture_driver_->GetDynamicSeeds()) {
+    TrySampleAndUpdateInMemoryCorpus(Input{seed},
+                                     /*write_to_file=*/false);
+  }
 }
 
 void FuzzTestFuzzerImpl::RunInUnitTestMode() {