Skip to content

Commit c02dd30

Browse files
committed
test: add unit test to confirm absence of pageToken param in listBuckets request, which causes the 1000+ buckets infinite pagination loop
1 parent 10a45ea commit c02dd30

File tree

4 files changed

+48
-0
lines changed

4 files changed

+48
-0
lines changed

google/cloud/storage/internal/rest/stub.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ StatusOr<ListBucketsResponse> RestStub::ListBuckets(
183183
if (!headers.ok()) return headers;
184184
request.AddOptionsToHttpRequest(builder);
185185
builder.AddQueryParameter("project", request.project_id());
186+
if (!request.page_token().empty()) {
187+
builder.AddQueryParameter("pageToken", request.page_token());
188+
}
186189
return ParseFromRestResponse<ListBucketsResponse>(
187190
storage_rest_client_->Get(context, std::move(builder).BuildRequest()));
188191
}

google/cloud/storage/internal/rest/stub_test.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ using ::testing::Contains;
3939
using ::testing::ElementsAre;
4040
using ::testing::Eq;
4141
using ::testing::HasSubstr;
42+
using ::testing::IsTrue;
4243
using ::testing::Matcher;
4344
using ::testing::Pair;
4445
using ::testing::ResultOf;
@@ -193,6 +194,48 @@ TEST(RestStubTest, CreateBucket) {
193194
StatusIs(PermanentError().code(), PermanentError().message()));
194195
}
195196

197+
TEST(RestStubTest, ListBucketsIncludesPageTokenWhenPresentInRequest) {
198+
auto mock = std::make_shared<MockRestClient>();
199+
std::string expected_token = "test-page-token";
200+
ListBucketsRequest request("test-project-id");
201+
request.set_page_token(expected_token);
202+
203+
EXPECT_CALL(*mock,
204+
Get(ExpectedContext(),
205+
ResultOf(
206+
"request parameters contain expected pageToken",
207+
[](RestRequest const& r) { return r.parameters(); },
208+
Contains(Pair("pageToken", expected_token)))))
209+
.WillOnce(Return(PermanentError()));
210+
211+
auto tested = std::make_unique<RestStub>(Options{}, mock, mock);
212+
auto context = TestContext();
213+
tested->ListBuckets(context, TestOptions(), request);
214+
}
215+
216+
TEST(RestStubTest, ListBucketsOmitsPageTokenWhenEmptyInRequest) {
217+
auto mock = std::make_shared<MockRestClient>();
218+
ListBucketsRequest request("test-project-id");
219+
220+
EXPECT_CALL(*mock, Get(ExpectedContext(),
221+
ResultOf(
222+
"request parameters do not contain 'pageToken'",
223+
[](RestRequest const& r) {
224+
for (auto const& param : r.parameters()) {
225+
if (param.first == "pageToken") {
226+
return false;
227+
}
228+
}
229+
return true;
230+
},
231+
IsTrue())))
232+
.WillOnce(Return(PermanentError()));
233+
234+
auto tested = std::make_unique<RestStub>(Options{}, mock, mock);
235+
auto context = TestContext();
236+
tested->ListBuckets(context, TestOptions(), request);
237+
}
238+
196239
TEST(RestStubTest, GetBucketMetadata) {
197240
auto mock = std::make_shared<MockRestClient>();
198241
EXPECT_CALL(*mock, Get(ExpectedContext(), ExpectedRequest()))

google/cloud/storage/tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
set(storage_client_integration_tests
1818
# cmake-format : sort
19+
elie_test.cc
1920
async_client_integration_test.cc
2021
auto_finalize_integration_test.cc
2122
bucket_integration_test.cc

google/cloud/storage/tests/storage_client_integration_tests.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ storage_client_integration_tests = [
2626
"curl_sign_blob_integration_test.cc",
2727
"decompressive_transcoding_integration_test.cc",
2828
"default_object_acl_integration_test.cc",
29+
"elie_test.cc",
2930
"error_injection_integration_test.cc",
3031
"error_parsing_integration_test.cc",
3132
"grpc_bucket_metadata_integration_test.cc",

0 commit comments

Comments
 (0)