message: test/fuzz: add a seed corpus generation option to the test_runner
diff: @@ -56,6 +56,14 @@ def main():
  '--m_dir',
  help='Merge inputs from this directory into the seed_dir. Needs /target subdirectory.',
  )
  + parser.add_argument(
  + '-g',
  + '--generate',
  + action='store_true',
  + help='Create new corpus seeds (or extend the existing ones) by running'
  + ' the given targets for a finite number of times. Outputs them to'
  + ' the passed seed_dir.'
  + )
  args = parser.parse_args()
  @@ -100,6 +108,7 @@ def main():
  logging.info("{} of {} detected fuzz target(s) selected: {}".format(len(test_list_selection), len(test_list_all), " ".join(test_list_selection)))
  + if not args.generate:
  test_list_seedless = []
  for t in test_list_selection:
  corpus_path = os.path.join(args.seed_dir, t)
  @@ -133,6 +142,14 @@ def main():
  sys.exit(1)
  with ThreadPoolExecutor(max_workers=args.par) as fuzz_pool:
  + if args.generate:
  + return generate_corpus_seeds(
  + fuzz_pool=fuzz_pool,
  + build_dir=config["environment"]["BUILDDIR"],
  + seed_dir=args.seed_dir,
  + targets=test_list_selection,
  + )
  +
  if args.m_dir:
  merge_inputs(
  fuzz_pool=fuzz_pool,
  @@ -152,6 +169,37 @@ def main():
  )
  +def generate_corpus_seeds(*, fuzz_pool, build_dir, seed_dir, targets):
  + """Generates new corpus seeds.
  +
  + Run {targets} without input, and outputs the generated corpus seeds to
  + {seed_dir}.
  + """
  + logging.info("Generating corpus seeds to {}".format(seed_dir))
  +
  + def job(command):
  + logging.debug("Running '{}'\n".format(" ".join(command)))
  + logging.debug("Command '{}' output:\n'{}'\n".format(
  + ' '.join(command),
  + subprocess.run(command, check=True, stderr=subprocess.PIPE,
  + universal_newlines=True).stderr
  + ))
  +
  + futures = []
  + for target in targets:
  + target_seed_dir = os.path.join(seed_dir, target)
  + os.makedirs(target_seed_dir, exist_ok=True)
  + command = [
  + os.path.join(build_dir, "src", "test", "fuzz", target),
  + "-runs=100000",
  + target_seed_dir,
  + ]
  + futures.append(fuzz_pool.submit(job, command))
  +
  + for future in as_completed(futures):
  + future.result()
  +
  +
  def merge_inputs(*, fuzz_pool, corpus, test_list, build_dir, merge_dir):
  logging.info("Merge the inputs in the passed dir into the seed_dir. Passed dir {}".format(merge_dir))
  jobs = []
  