Repository: google/benchmark
File: src/benchmark_runner.cc (C++)

Code before:

  if (value.back() == 'x') {
    const char* iters_str = value.c_str();
    char* p_end;
    // Reset error since atol will change it.
    const int old_errno = errno;
    errno = 0;
    IterationCount num_iters = std::strtol(iters_str, &p_end, 10);
    const int new_errno = errno;
    errno = old_errno;

    // After a valid parse, p_end should have been set to
    // point to the 'x' suffix.
    BM_CHECK(new_errno == 0 && p_end != nullptr && *p_end == 'x')
        << "Malformed iters value passed to --benchmark_min_time: `" << value
        << "`. Expected --benchmark_min_time=<integer>x.";

    ret.tag = BenchTimeType::ITERS;
    ret.iters = num_iters;
    return ret;
  }

  const char* time_str = value.c_str();
  bool has_suffix = value.back() == 's';
  if (!has_suffix) {
    BM_VLOG(2) << "Value passed to --benchmark_min_time should have a suffix. "
                  "Eg., `30s` for 30-seconds.";
  }

  char* p_end;
  // Reset error before it's changed by strtod.
  const int old_errno = errno;
  errno = 0;
  double min_time = std::strtod(time_str, &p_end);
  const int new_errno = errno;
  errno = old_errno;

  // After a successfull parse, p_end should point to the suffix 's'
  // or the end of the string, if the suffix was omitted.
  BM_CHECK(new_errno == 0 && p_end != nullptr &&
           (has_suffix && *p_end == 's' || *p_end == '\0'))
      << "Malformed seconds value passed to --benchmark_min_time: `" << value
      << "`. Expected --benchmark_min_time=<float>x.";

  ret.tag = BenchTimeType::TIME;
  ret.time = min_time;

  return ret;
}

double GetMinTime(const benchmark::internal::BenchmarkInstance& b,

Review comment (suggestion):
if this is something we want users to take action on, we need to log at a higher level than VLOG(2).

Code after:
  // min_time.
  if (iters_or_time.tag == BenchTimeType::ITERS) return kDefaultMinTime;

  return iters_or_time.time;
}

IterationCount ComputeIters(const benchmark::internal::BenchmarkInstance& b,
                            const BenchTimeType& iters_or_time) {
  if (b.iterations() != 0) return b.iterations();

  // We've already concluded that this flag is currently used to pass
  // iters but do a check here again anyway.
  BM_CHECK(iters_or_time.tag == BenchTimeType::ITERS);
  return iters_or_time.iters;
}

}  // end namespace

BenchTimeType ParseBenchMinTime(const std::string& value) {
  BenchTimeType ret;

  if (value.empty()) {
    ret.tag = BenchTimeType::TIME;
    ret.time = 0.0;
    return ret;
  }

  if (value.back() == 'x') {
    const char* iters_str = value.c_str();
    char* p_end;
    // Reset errno before it's changed by strtol.
    errno = 0;
    IterationCount num_iters = std::strtol(iters_str, &p_end, 10);

    // After a valid parse, p_end should have been set to
    // point to the 'x' suffix.
    BM_CHECK(errno == 0 && p_end != nullptr && *p_end == 'x')
        << "Malformed iters value passed to --benchmark_min_time: `" << value
        << "`. Expected --benchmark_min_time=<integer>x.";

    ret.tag = BenchTimeType::ITERS;
    ret.iters = num_iters;
    return ret;
  }

  const char* time_str = value.c_str();
  bool has_suffix = value.back() == 's';
  if (!has_suffix) {
    BM_VLOG(0) << "Value passed to --benchmark_min_time should have a suffix. "
                  "Eg., `30s` for 30-seconds.";
  }