Limit fuzzer tests so that they take less time to run (#2763)

The recently added fuzzer_replayer and fuzzer_shrinker tests were
rather heavyweight and were leading to CI timeouts.  This change
reduces the runtime of those tests by having them do fewer iterations.
diff --git a/test/fuzz/fuzzer_replayer_test.cpp b/test/fuzz/fuzzer_replayer_test.cpp
index 166e6ea..550c4fc 100644
--- a/test/fuzz/fuzzer_replayer_test.cpp
+++ b/test/fuzz/fuzzer_replayer_test.cpp
@@ -240,9 +240,9 @@
                OpFunctionEnd
   )";
 
-  // Do 10 fuzzer runs, starting from an initial seed of 0 (seed value chosen
+  // Do 5 fuzzer runs, starting from an initial seed of 0 (seed value chosen
   // arbitrarily).
-  RunFuzzerAndReplayer(shader, protobufs::FactSequence(), 0, 10);
+  RunFuzzerAndReplayer(shader, protobufs::FactSequence(), 0, 5);
 }
 
 TEST(FuzzerReplayerTest, Miscellaneous2) {
@@ -485,9 +485,9 @@
                OpFunctionEnd
   )";
 
-  // Do 10 fuzzer runs, starting from an initial seed of 10 (seed value chosen
+  // Do 5 fuzzer runs, starting from an initial seed of 10 (seed value chosen
   // arbitrarily).
-  RunFuzzerAndReplayer(shader, protobufs::FactSequence(), 10, 10);
+  RunFuzzerAndReplayer(shader, protobufs::FactSequence(), 10, 5);
 }
 
 TEST(FuzzerReplayerTest, Miscellaneous3) {
@@ -970,9 +970,9 @@
     *facts.mutable_fact()->Add() = temp;
   }
 
-  // Do 10 fuzzer runs, starting from an initial seed of 94 (seed value chosen
+  // Do 5 fuzzer runs, starting from an initial seed of 94 (seed value chosen
   // arbitrarily).
-  RunFuzzerAndReplayer(shader, facts, 94, 10);
+  RunFuzzerAndReplayer(shader, facts, 94, 5);
 }
 
 }  // namespace
diff --git a/test/fuzz/fuzzer_shrinker_test.cpp b/test/fuzz/fuzzer_shrinker_test.cpp
index 644ace4..85f41bc 100644
--- a/test/fuzz/fuzzer_shrinker_test.cpp
+++ b/test/fuzz/fuzzer_shrinker_test.cpp
@@ -111,20 +111,21 @@
 // |transformation_sequence_in| gets performed with respect to
 // |interestingness_function|.  If |expected_binary_out| is non-empty, it must
 // match the binary obtained by applying the final shrunk set of
-// transformations, in which case the number of such transforations should equal
-// |expected_transformations_out_size|.
+// transformations, in which case the number of such transformations should
+// equal |expected_transformations_out_size|.
+//
+// The |step_limit| parameter restricts the number of steps that the shrinker
+// will try; it can be set to something small for a faster (but less thorough)
+// test.
 void RunAndCheckShrinker(
     const spv_target_env& target_env, const std::vector<uint32_t>& binary_in,
     const protobufs::FactSequence& initial_facts,
     const protobufs::TransformationSequence& transformation_sequence_in,
     const Shrinker::InterestingnessFunction& interestingness_function,
     const std::vector<uint32_t>& expected_binary_out,
-    uint32_t expected_transformations_out_size) {
-  // We want tests to complete in reasonable time, so don't go on too long.
-  const uint32_t kStepLimit = 50;
-
+    uint32_t expected_transformations_out_size, uint32_t step_limit) {
   // Run the shrinker.
-  Shrinker shrinker(target_env, kStepLimit);
+  Shrinker shrinker(target_env, step_limit);
   shrinker.SetMessageConsumer(kSilentConsumer);
 
   std::vector<uint32_t> binary_out;
@@ -146,14 +147,13 @@
   }
 }
 
-// Assembles the given |shader| text, and then does the following |num_runs|
-// times, with successive seeds starting from |initial_seed|:
-// - Runs the fuzzer with the seed to yield a set of transformations
+// Assembles the given |shader| text, and then:
+// - Runs the fuzzer with |seed| to yield a set of transformations
 // - Shrinks the transformation with various interestingness functions,
 //   asserting some properties about the result each time
 void RunFuzzerAndShrinker(const std::string& shader,
                           const protobufs::FactSequence& initial_facts,
-                          uint32_t initial_seed, uint32_t num_runs) {
+                          uint32_t seed) {
   const auto env = SPV_ENV_UNIVERSAL_1_3;
 
   std::vector<uint32_t> binary_in;
@@ -161,47 +161,50 @@
   ASSERT_TRUE(t.Assemble(shader, &binary_in, kFuzzAssembleOption));
   ASSERT_TRUE(t.Validate(binary_in));
 
-  for (uint32_t seed = initial_seed; seed < initial_seed + num_runs; seed++) {
-    // Run the fuzzer and check that it successfully yields a valid binary.
-    std::vector<uint32_t> fuzzer_binary_out;
-    protobufs::TransformationSequence fuzzer_transformation_sequence_out;
-    spvtools::FuzzerOptions fuzzer_options;
-    spvFuzzerOptionsSetRandomSeed(fuzzer_options, seed);
-    Fuzzer fuzzer(env);
-    fuzzer.SetMessageConsumer(kSilentConsumer);
-    auto fuzzer_result_status =
-        fuzzer.Run(binary_in, initial_facts, fuzzer_options, &fuzzer_binary_out,
-                   &fuzzer_transformation_sequence_out);
-    ASSERT_EQ(Fuzzer::FuzzerResultStatus::kComplete, fuzzer_result_status);
-    ASSERT_TRUE(t.Validate(fuzzer_binary_out));
+  // Run the fuzzer and check that it successfully yields a valid binary.
+  std::vector<uint32_t> fuzzer_binary_out;
+  protobufs::TransformationSequence fuzzer_transformation_sequence_out;
+  spvtools::FuzzerOptions fuzzer_options;
+  spvFuzzerOptionsSetRandomSeed(fuzzer_options, seed);
+  Fuzzer fuzzer(env);
+  fuzzer.SetMessageConsumer(kSilentConsumer);
+  auto fuzzer_result_status =
+      fuzzer.Run(binary_in, initial_facts, fuzzer_options, &fuzzer_binary_out,
+                 &fuzzer_transformation_sequence_out);
+  ASSERT_EQ(Fuzzer::FuzzerResultStatus::kComplete, fuzzer_result_status);
+  ASSERT_TRUE(t.Validate(fuzzer_binary_out));
 
-    // With the AlwaysInteresting test, we should quickly shrink to the original
-    // binary with no transformations remaining.
-    RunAndCheckShrinker(env, binary_in, initial_facts,
-                        fuzzer_transformation_sequence_out,
-                        AlwaysInteresting().AsFunction(), binary_in, 0);
+  const uint32_t kReasonableStepLimit = 50;
+  const uint32_t kSmallStepLimit = 20;
 
-    // With the OnlyInterestingFirstTime test, no shrinking should be achieved.
-    RunAndCheckShrinker(
-        env, binary_in, initial_facts, fuzzer_transformation_sequence_out,
-        OnlyInterestingFirstTime().AsFunction(), fuzzer_binary_out,
-        static_cast<uint32_t>(
-            fuzzer_transformation_sequence_out.transformation_size()));
+  // With the AlwaysInteresting test, we should quickly shrink to the original
+  // binary with no transformations remaining.
+  RunAndCheckShrinker(
+      env, binary_in, initial_facts, fuzzer_transformation_sequence_out,
+      AlwaysInteresting().AsFunction(), binary_in, 0, kReasonableStepLimit);
 
-    // The PingPong test is unpredictable; passing an empty expected binary
-    // means that we don't check anything beyond that shrinking completes
-    // successfully.
-    RunAndCheckShrinker(env, binary_in, initial_facts,
-                        fuzzer_transformation_sequence_out,
-                        PingPong().AsFunction(), {}, 0);
+  // With the OnlyInterestingFirstTime test, no shrinking should be achieved.
+  RunAndCheckShrinker(
+      env, binary_in, initial_facts, fuzzer_transformation_sequence_out,
+      OnlyInterestingFirstTime().AsFunction(), fuzzer_binary_out,
+      static_cast<uint32_t>(
+          fuzzer_transformation_sequence_out.transformation_size()),
+      kReasonableStepLimit);
 
-    // The InterestingThenRandom test is unpredictable; passing an empty
-    // expected binary means that we do not check anything about shrinking
-    // results.
-    RunAndCheckShrinker(
-        env, binary_in, initial_facts, fuzzer_transformation_sequence_out,
-        InterestingThenRandom(PseudoRandomGenerator(seed)).AsFunction(), {}, 0);
-  }
+  // The PingPong test is unpredictable; passing an empty expected binary
+  // means that we don't check anything beyond that shrinking completes
+  // successfully.
+  RunAndCheckShrinker(env, binary_in, initial_facts,
+                      fuzzer_transformation_sequence_out,
+                      PingPong().AsFunction(), {}, 0, kSmallStepLimit);
+
+  // The InterestingThenRandom test is unpredictable; passing an empty
+  // expected binary means that we do not check anything about shrinking
+  // results.
+  RunAndCheckShrinker(
+      env, binary_in, initial_facts, fuzzer_transformation_sequence_out,
+      InterestingThenRandom(PseudoRandomGenerator(seed)).AsFunction(), {}, 0,
+      kSmallStepLimit);
 }
 
 TEST(FuzzerShrinkerTest, Miscellaneous1) {
@@ -369,9 +372,7 @@
 
   )";
 
-  // Do 2 fuzz-and-shrink runs, starting from an initial seed of 2 (seed value
-  // chosen arbitrarily).
-  RunFuzzerAndShrinker(shader, protobufs::FactSequence(), 2, 2);
+  RunFuzzerAndShrinker(shader, protobufs::FactSequence(), 2);
 }
 
 TEST(FuzzerShrinkerTest, Miscellaneous2) {
@@ -614,9 +615,7 @@
                OpFunctionEnd
   )";
 
-  // Do 2 fuzzer runs, starting from an initial seed of 19 (seed value chosen
-  // arbitrarily).
-  RunFuzzerAndShrinker(shader, protobufs::FactSequence(), 19, 2);
+  RunFuzzerAndShrinker(shader, protobufs::FactSequence(), 19);
 }
 
 TEST(FuzzerShrinkerTest, Miscellaneous3) {
@@ -1101,7 +1100,7 @@
 
   // Do 2 fuzzer runs, starting from an initial seed of 194 (seed value chosen
   // arbitrarily).
-  RunFuzzerAndShrinker(shader, facts, 194, 2);
+  RunFuzzerAndShrinker(shader, facts, 194);
 }
 
 }  // namespace