Skip to content

Commit f35b84c

Browse files
committed
Apply minimal Sonar-focused fixes in benchmark parser/script
1 parent 434e18a commit f35b84c

File tree

2 files changed

+43
-32
lines changed

2 files changed

+43
-32
lines changed

test/benchmark/json_benchmark.cc

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ struct Metrics {
6868
unsigned long long parse_error_count{0};
6969
};
7070

71+
class JsonBenchmarkError : public std::runtime_error {
72+
public:
73+
explicit JsonBenchmarkError(const std::string &message)
74+
: std::runtime_error(message) { }
75+
};
76+
7177
const char *const usage_message =
7278
"Usage: json_benchmark --scenario NAME [--iterations N] "
7379
"[--target-bytes N] [--depth N] [--include-invalid] [--output json]";
@@ -99,7 +105,7 @@ unsigned long long parseUnsignedLongLong(const char *value,
99105
const unsigned long long parsed = std::strtoull(value, &end, 10);
100106
if (errno != 0 || end == value || *end != '\0'
101107
|| (!allow_zero && parsed == 0)) {
102-
throw std::runtime_error(std::string("invalid numeric value for ")
108+
throw JsonBenchmarkError(std::string("invalid numeric value for ")
103109
+ flag_name + ": " + value);
104110
}
105111
return parsed;
@@ -109,7 +115,7 @@ std::size_t parseSize(const char *value, const char *flag_name) {
109115
const unsigned long long parsed =
110116
parseUnsignedLongLong(value, flag_name, true);
111117
if (parsed > std::numeric_limits<std::size_t>::max()) {
112-
throw std::runtime_error(std::string("value too large for ")
118+
throw JsonBenchmarkError(std::string("value too large for ")
113119
+ flag_name + ": " + value);
114120
}
115121
return static_cast<std::size_t>(parsed);
@@ -119,59 +125,62 @@ unsigned long long parseIterations(const char *value) {
119125
return parseUnsignedLongLong(value, "--iterations", false);
120126
}
121127

128+
const char *requireOptionValue(int argc, const char *argv[], int *index,
129+
const char *option_name) {
130+
if (*index + 1 >= argc) {
131+
throw JsonBenchmarkError(std::string("missing value for ")
132+
+ option_name);
133+
}
134+
*index += 1;
135+
return argv[*index];
136+
}
137+
122138
Options parseOptions(int argc, const char *argv[]) {
123139
Options options;
124140

125-
for (int i = 1; i < argc; i++) {
141+
int i = 1;
142+
while (i < argc) {
126143
const std::string current(argv[i]);
127144
if (current == "-h" || current == "-?" || current == "--help") {
128145
std::cout << usage_message << std::endl;
129146
std::exit(0);
130147
} else if (current == "--scenario") {
131-
if (i + 1 >= argc) {
132-
throw std::runtime_error("missing value for --scenario");
133-
}
134-
options.scenario.assign(argv[++i]);
148+
options.scenario.assign(
149+
requireOptionValue(argc, argv, &i, "--scenario"));
135150
} else if (current == "--iterations") {
136-
if (i + 1 >= argc) {
137-
throw std::runtime_error("missing value for --iterations");
138-
}
139-
options.iterations = parseIterations(argv[++i]);
151+
options.iterations = parseIterations(
152+
requireOptionValue(argc, argv, &i, "--iterations"));
140153
} else if (current == "--target-bytes") {
141-
if (i + 1 >= argc) {
142-
throw std::runtime_error("missing value for --target-bytes");
143-
}
144-
options.target_bytes = parseSize(argv[++i], "--target-bytes");
154+
options.target_bytes = parseSize(
155+
requireOptionValue(argc, argv, &i, "--target-bytes"),
156+
"--target-bytes");
145157
} else if (current == "--depth") {
146-
if (i + 1 >= argc) {
147-
throw std::runtime_error("missing value for --depth");
148-
}
149-
options.depth = parseSize(argv[++i], "--depth");
158+
options.depth = parseSize(
159+
requireOptionValue(argc, argv, &i, "--depth"), "--depth");
150160
} else if (current == "--include-invalid") {
151161
options.include_invalid = true;
152162
} else if (current == "--output") {
153-
if (i + 1 >= argc) {
154-
throw std::runtime_error("missing value for --output");
155-
}
156-
if (const std::string output_format(argv[++i]);
163+
if (const std::string output_format(
164+
requireOptionValue(argc, argv, &i, "--output"));
157165
output_format != "json") {
158-
throw std::runtime_error("unsupported output format: "
166+
throw JsonBenchmarkError("unsupported output format: "
159167
+ output_format);
160168
}
161169
options.output_json = true;
162170
} else {
163-
throw std::runtime_error("unknown option: " + current);
171+
throw JsonBenchmarkError("unknown option: " + current);
164172
}
173+
i++;
165174
}
166175

167176
if (options.scenario.empty()) {
168-
throw std::runtime_error("missing required --scenario");
177+
throw JsonBenchmarkError("missing required --scenario");
169178
}
170179

171180
if (const bool is_invalid_scenario = options.scenario == "truncated"
172181
|| options.scenario == "malformed";
173182
is_invalid_scenario && !options.include_invalid) {
174-
throw std::runtime_error(
183+
throw JsonBenchmarkError(
175184
"invalid JSON scenarios require --include-invalid");
176185
}
177186

@@ -301,7 +310,7 @@ std::string buildScenarioBody(const Options &options) {
301310
return body;
302311
}
303312

304-
throw std::runtime_error("unsupported scenario: " + options.scenario);
313+
throw JsonBenchmarkError("unsupported scenario: " + options.scenario);
305314
}
306315

307316
bool isResolvedZero(const std::unique_ptr<std::string> &value) {
@@ -332,13 +341,13 @@ Metrics runBenchmark(modsecurity::ModSecurity *modsec,
332341
reinterpret_cast<const unsigned char *>(body.data()), body.size());
333342
metrics.append_request_body_ns += elapsedNanos(append_start);
334343
if (append_ok == 0) {
335-
throw std::runtime_error(
344+
throw JsonBenchmarkError(
336345
"appendRequestBody reported partial body processing");
337346
}
338347

339348
const auto process_start = Clock::now();
340349
if (!transaction.processRequestBody()) {
341-
throw std::runtime_error("processRequestBody returned false");
350+
throw JsonBenchmarkError("processRequestBody returned false");
342351
}
343352
metrics.process_request_body_ns += elapsedNanos(process_start);
344353
metrics.total_transaction_ns += elapsedNanos(total_start);
@@ -349,7 +358,7 @@ Metrics runBenchmark(modsecurity::ModSecurity *modsec,
349358
transaction.m_variableReqbodyProcessorError.resolveFirst();
350359

351360
if (!reqbody_error || !processor_error) {
352-
throw std::runtime_error(
361+
throw JsonBenchmarkError(
353362
"unable to resolve JSON parse outcome variables");
354363
}
355364

@@ -358,7 +367,7 @@ Metrics runBenchmark(modsecurity::ModSecurity *modsec,
358367
if (const bool parse_error = !isResolvedZero(reqbody_error)
359368
|| !isResolvedZero(processor_error);
360369
parse_success == parse_error) {
361-
throw std::runtime_error(
370+
throw JsonBenchmarkError(
362371
"ambiguous JSON parse outcome observed in benchmark");
363372
}
364373

test/benchmark/run-json-benchmarks.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ run_scenarios() {
7575
"${binary}" --scenario "${scenario}" --include-invalid --output json >> "${output_file}"
7676
done
7777
fi
78+
79+
return 0
7880
}
7981

8082
: > "${output_file}"

0 commit comments

Comments
 (0)