Skip to content

Commit 4d1cbc3

Browse files
authored
test(storage): fix handling of optional ranges (#9808)
I confused myself on how to interpret the default read and offset ranges. The intent was to *not* set a `ReadRange()` option if the command line arguments were not set. The effect was to set an empty `ReadRange()` value, which produced an unexpected `Range:` header. Fortunately, the value of the header had no effect, but really confused me. With this change the optional parameters are represented by `absl::optional` values. Which makes it easier to treat them correctly.
1 parent 1cb7031 commit 4d1cbc3

File tree

4 files changed

+67
-22
lines changed

4 files changed

+67
-22
lines changed

google/cloud/storage/benchmarks/storage_throughput_vs_cpu_benchmark.cc

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,16 @@ int main(int argc, char* argv[]) {
166166
std::cout << "\n# " << name << " Range: [" << minimum << ',' << maximum
167167
<< "]\n# " << name << " Quantum: " << quantum;
168168
};
169+
auto output_optional_quantized_range =
170+
[](std::string const& name, auto minimum, auto maximum, auto quantum) {
171+
if (!minimum.has_value() || !maximum.has_value()) {
172+
std::cout << "\n# " << name << " Range: [not set]";
173+
} else {
174+
std::cout << "\n# " << name << " Range: [" << *minimum << ','
175+
<< *maximum << "]";
176+
}
177+
std::cout << "\n# " << name << " Quantum: " << quantum;
178+
};
169179

170180
std::cout << "# Start time: " << gcs_bm::CurrentTime() //
171181
<< "\n# Labels: " << options->labels //
@@ -204,12 +214,12 @@ int main(int argc, char* argv[]) {
204214
gcs_bm::PrintOptions(std::cout, "Grpc", options->grpc_options);
205215
gcs_bm::PrintOptions(std::cout, "Direct Path", options->direct_path_options);
206216

207-
output_quantized_range("Read Offset", options->minimum_read_offset,
208-
options->maximum_read_offset,
209-
options->read_offset_quantum);
210-
output_quantized_range("Read Size", options->minimum_read_size,
211-
options->maximum_read_size,
212-
options->read_size_quantum);
217+
output_optional_quantized_range("Read Offset", options->minimum_read_offset,
218+
options->maximum_read_offset,
219+
options->read_offset_quantum);
220+
output_optional_quantized_range("Read Size", options->minimum_read_size,
221+
options->maximum_read_size,
222+
options->read_size_quantum);
213223

214224
std::cout << "\n# Build info: " << notes << "\n";
215225
// Make the output generated so far immediately visible, helps with debugging.
@@ -356,15 +366,21 @@ void RunThread(ThroughputOptions const& options, std::string const& bucket_name,
356366
auto read_buffer_size_generator = quantized_range_generator(
357367
options.minimum_read_buffer_size, options.maximum_read_buffer_size,
358368
options.read_buffer_quantum);
359-
auto read_offset_generator = quantized_range_generator(
360-
options.minimum_read_offset, options.maximum_read_offset,
361-
options.read_offset_quantum);
362-
auto read_size_generator = quantized_range_generator(
363-
options.minimum_read_size, options.maximum_read_size,
364-
options.read_size_quantum);
365369

366370
auto read_range_generator = [&](auto& g, std::int64_t object_size)
367371
-> absl::optional<std::pair<std::int64_t, std::int64_t>> {
372+
if (!options.minimum_read_size.has_value() ||
373+
!options.maximum_read_size.has_value() ||
374+
!options.minimum_read_offset.has_value() ||
375+
!options.maximum_read_offset.has_value()) {
376+
return absl::nullopt;
377+
}
378+
auto read_offset_generator = quantized_range_generator(
379+
*options.minimum_read_offset, *options.maximum_read_offset,
380+
options.read_offset_quantum);
381+
auto read_size_generator = quantized_range_generator(
382+
*options.minimum_read_size, *options.maximum_read_size,
383+
options.read_size_quantum);
368384
auto offset = (std::min)(object_size, read_offset_generator(g));
369385
auto size = (std::min)(object_size - offset, read_size_generator(g));
370386
// This makes it easier to control the ratio of ranged vs. full reads from

google/cloud/storage/benchmarks/throughput_options.cc

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,27 @@ namespace {
2727
namespace gcs = ::google::cloud::storage;
2828
namespace gcs_ex = ::google::cloud::storage_experimental;
2929

30-
Status ValidateQuantizedRange(std::string const& name, std::int64_t minimum,
31-
std::int64_t maximum, std::int64_t quantum) {
30+
Status ValidateQuantizedRange(std::string const& name,
31+
absl::optional<std::int64_t> minimum,
32+
absl::optional<std::int64_t> maximum,
33+
std::int64_t quantum) {
3234
using ::google::cloud::StatusCode;
33-
if (minimum > maximum || minimum < 0 || maximum < 0) {
35+
if (!minimum.has_value() && !maximum.has_value()) return {};
36+
if (!minimum.has_value() || !maximum.has_value()) {
3437
std::ostringstream os;
35-
os << "Invalid range for " << name << " [" << minimum << ',' << maximum
38+
os << "One of the range limits for " << name << " is missing";
39+
return google::cloud::Status{StatusCode::kInvalidArgument, os.str()};
40+
}
41+
if (*minimum > *maximum || *minimum < 0 || *maximum < 0) {
42+
std::ostringstream os;
43+
os << "Invalid range for " << name << " [" << *minimum << ',' << *maximum
3644
<< "]";
3745
return google::cloud::Status{StatusCode::kInvalidArgument, os.str()};
3846
}
39-
if (quantum <= 0 || (quantum > minimum && minimum != 0)) {
47+
if (quantum <= 0 || (quantum > *minimum && *minimum != 0)) {
4048
std::ostringstream os;
4149
os << "Invalid quantum for " << name << " (" << quantum
42-
<< "), it should be in the (0," << minimum << "] range";
50+
<< "), it should be in the (0," << *minimum << "] range";
4351
return google::cloud::Status{StatusCode::kInvalidArgument, os.str()};
4452
}
4553

google/cloud/storage/benchmarks/throughput_options.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,11 @@ struct ThroughputOptions {
5757
std::vector<bool> enabled_crc32c = {false, true};
5858
std::vector<bool> enabled_md5 = {false, true};
5959
std::chrono::milliseconds minimum_sample_delay{};
60-
std::int64_t minimum_read_offset = 0;
61-
std::int64_t maximum_read_offset = 0;
60+
absl::optional<std::int64_t> minimum_read_offset;
61+
absl::optional<std::int64_t> maximum_read_offset;
6262
std::int64_t read_offset_quantum = 128 * kKiB;
63-
std::int64_t minimum_read_size = 0;
64-
std::int64_t maximum_read_size = 0;
63+
absl::optional<std::int64_t> minimum_read_size;
64+
absl::optional<std::int64_t> maximum_read_size;
6565
std::int64_t read_size_quantum = 128 * kKiB;
6666
Options client_options;
6767
Options rest_options;

google/cloud/storage/benchmarks/throughput_options_test.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,16 @@ TEST(ThroughputOptions, Validate) {
326326
"--maximum-read-offset=8",
327327
"--read-offset-quantum=5",
328328
}));
329+
EXPECT_FALSE(ParseThroughputOptions({
330+
"self-test",
331+
"--region=r",
332+
"--minimum-read-offset=4",
333+
}));
334+
EXPECT_FALSE(ParseThroughputOptions({
335+
"self-test",
336+
"--region=r",
337+
"--maximum-read-offset=4",
338+
}));
329339

330340
EXPECT_FALSE(ParseThroughputOptions({
331341
"self-test",
@@ -340,6 +350,17 @@ TEST(ThroughputOptions, Validate) {
340350
"--maximum-read-size=8",
341351
"--read-size-quantum=5",
342352
}));
353+
EXPECT_FALSE(ParseThroughputOptions({
354+
"self-test",
355+
"--region=r",
356+
"--minimum-read-size=8",
357+
}));
358+
EXPECT_FALSE(ParseThroughputOptions({
359+
"self-test",
360+
"--region=r",
361+
"--maximum-read-size=8",
362+
}));
363+
343364
EXPECT_FALSE(ParseThroughputOptions({
344365
"self-test",
345366
"--region=r",

0 commit comments

Comments
 (0)