async function runSmokehouse(smokeTestDefns, smokehouseOptions) {
  const {
    testRunnerOptions,
    jobs = DEFAULT_CONCURRENT_RUNS,
    retries = DEFAULT_RETRIES,
    lighthouseRunner = Object.assign(cliLighthouseRunner, {runnerName: 'cli'}),
    takeNetworkRequestUrls,
    setup,
  } = smokehouseOptions;
  assertPositiveInteger('jobs', jobs);
  assertNonNegativeInteger('retries', retries);

  try {
    await setup?.();
  } catch (err) {
    console.error(log.redify('\nERROR DURING SETUP:'));
    console.error(log.redify(err.stack || err));
    return {success: false, testResults: []};
  }

  // Run each testDefn in parallel based on the concurrencyLimit.
  const concurrentMapper = new ConcurrentMapper();

  const testOptions = {
    testRunnerOptions,
    jobs,
    retries,
    lighthouseRunner,
    takeNetworkRequestUrls,
  };
  const smokePromises = smokeTestDefns.map(testDefn => {
    // If defn is set to `runSerially`, we'll run it in succession with other tests, not parallel.
    const concurrency = testDefn.runSerially ? 1 : jobs;
    return concurrentMapper.runInPool(() => runSmokeTest(testDefn, testOptions), {concurrency});
  });
  const testResults = await Promise.all(smokePromises);

  // Print final summary.
  let passingCount = 0;
  let failingCount = 0;
  for (const testResult of testResults) {
    passingCount += testResult.passed;
    failingCount += testResult.failed;
  }
  if (passingCount) console.log(log.greenify(`${getAssertionLog(passingCount)} passing in total`));
  if (failingCount) console.log(log.redify(`${getAssertionLog(failingCount)} failing in total`));

  // Print id(s) and fail if there were failing tests.
  const failingDefns = testResults.filter(result => result.failed);
  if (failingDefns.length) {
    const testNames = failingDefns.map(d => d.id).join(', ');
    console.log(log.redify(`We have ${failingDefns.length} failing smoketest(s): ${testNames}`));
    return {success: false, testResults};
  }

  return {success: true, testResults};
}
Runs the selected smoke tests. Returns whether all assertions pass.
@param {Array<Smokehouse.TestDfn>} smokeTestDefns
@param {Partial<Smokehouse.SmokehouseOptions>} smokehouseOptions
@return {Promise<{success: boolean, testResults: SmokehouseResult[]}>}