Skip to content
This repository was archived by the owner on Dec 8, 2021. It is now read-only.

Commit 8b555af

Browse files
authored
test: write integration test for SessionPool (#1442)
Make sure the low-level functions to make async calls actually work, the value of unit tests for these is limited (we would be re-testing the retry loop, but we have tests for that). An integration test verifies we are filling the protos with the right data. Note that some of these functions are not exercised in the other integration tests because they run too infrequently.
1 parent 26c26cd commit 8b555af

File tree

4 files changed

+130
-1
lines changed

4 files changed

+130
-1
lines changed

google/cloud/spanner/integration_tests/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ function (spanner_client_define_integration_tests)
3535
data_types_integration_test.cc
3636
database_admin_integration_test.cc
3737
instance_admin_integration_test.cc
38-
rpc_failure_threshold_integration_test.cc)
38+
rpc_failure_threshold_integration_test.cc
39+
session_pool_integration_test.cc)
3940

4041
# Export the list of unit tests to a .bzl file so we do not need to maintain
4142
# the list in two places.
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
// Copyright 2019 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "google/cloud/spanner/internal/session_pool.h"
16+
#include "google/cloud/spanner/testing/database_environment.h"
17+
#include "google/cloud/testing_util/assert_ok.h"
18+
#include "google/cloud/testing_util/init_google_mock.h"
19+
#include <gmock/gmock.h>
20+
21+
namespace google {
22+
namespace cloud {
23+
namespace spanner {
24+
inline namespace SPANNER_CLIENT_NS {
25+
namespace internal {
26+
struct SessionPoolFriendForTest {
27+
static future<StatusOr<google::spanner::v1::BatchCreateSessionsResponse>>
28+
AsyncBatchCreateSessions(std::shared_ptr<SessionPool> const& session_pool,
29+
CompletionQueue& cq,
30+
std::shared_ptr<SpannerStub> stub,
31+
std::map<std::string, std::string> const& labels,
32+
int num_sessions) {
33+
return session_pool->AsyncBatchCreateSessions(cq, std::move(stub), labels,
34+
num_sessions);
35+
}
36+
37+
static future<StatusOr<google::protobuf::Empty>> AsyncDeleteSession(
38+
std::shared_ptr<SessionPool> const& session_pool, CompletionQueue& cq,
39+
std::shared_ptr<SpannerStub> stub, std::string session_name) {
40+
return session_pool->AsyncDeleteSession(cq, std::move(stub),
41+
std::move(session_name));
42+
}
43+
44+
static future<StatusOr<google::spanner::v1::Session>> AsyncGetSession(
45+
std::shared_ptr<SessionPool> const& session_pool, CompletionQueue& cq,
46+
std::shared_ptr<SpannerStub> stub, std::string session_name) {
47+
return session_pool->AsyncGetSession(cq, std::move(stub),
48+
std::move(session_name));
49+
}
50+
};
51+
namespace {
52+
53+
TEST(SessionPoolIntegrationTest, SessionAsyncCRUD) {
54+
google::cloud::CompletionQueue cq;
55+
std::thread t([&cq] { cq.Run(); });
56+
auto const db = spanner_testing::DatabaseEnvironment::GetDatabase();
57+
auto stub = CreateDefaultSpannerStub(ConnectionOptions{}, /*channel_id=*/0);
58+
auto session_pool =
59+
MakeSessionPool(db, {stub}, SessionPoolOptions{}, cq,
60+
LimitedTimeRetryPolicy(std::chrono::minutes(5)).clone(),
61+
ExponentialBackoffPolicy(std::chrono::seconds(10),
62+
std::chrono::minutes(1), 2.0)
63+
.clone());
64+
65+
// Make an asynchronous request, but immediately block until the response
66+
// arrives
67+
auto constexpr kNumTestSession = 4;
68+
auto create_response = SessionPoolFriendForTest::AsyncBatchCreateSessions(
69+
session_pool, cq, stub, {}, kNumTestSession)
70+
.get();
71+
ASSERT_STATUS_OK(create_response);
72+
EXPECT_EQ(kNumTestSession, create_response->session_size());
73+
74+
using ::google::spanner::v1::Session;
75+
std::vector<future<bool>> async_get;
76+
for (auto const& s : create_response->session()) {
77+
auto const& session_name = s.name();
78+
async_get.push_back(SessionPoolFriendForTest::AsyncGetSession(
79+
session_pool, cq, stub, session_name)
80+
.then([session_name](future<StatusOr<Session>> f) {
81+
auto session = f.get();
82+
EXPECT_STATUS_OK(session);
83+
if (!session) return false;
84+
EXPECT_EQ(session->name(), session_name);
85+
return session->name() == session_name;
86+
}));
87+
}
88+
for (auto& ag : async_get) {
89+
auto matched = ag.get();
90+
EXPECT_TRUE(matched);
91+
}
92+
93+
std::vector<future<Status>> async_delete;
94+
for (auto const& s : create_response->session()) {
95+
auto const& session_name = s.name();
96+
async_delete.push_back(
97+
SessionPoolFriendForTest::AsyncDeleteSession(session_pool, cq, stub,
98+
session_name)
99+
.then([](future<StatusOr<google::protobuf::Empty>> f) {
100+
return f.get().status();
101+
}));
102+
}
103+
for (auto& ad : async_delete) {
104+
auto status = ad.get();
105+
EXPECT_STATUS_OK(status);
106+
}
107+
108+
cq.Shutdown();
109+
t.join();
110+
}
111+
112+
} // namespace
113+
} // namespace internal
114+
} // namespace SPANNER_CLIENT_NS
115+
} // namespace spanner
116+
} // namespace cloud
117+
} // namespace google
118+
119+
int main(int argc, char* argv[]) {
120+
::google::cloud::testing_util::InitGoogleMock(argc, argv);
121+
(void)::testing::AddGlobalTestEnvironment(
122+
new google::cloud::spanner_testing::DatabaseEnvironment());
123+
124+
return RUN_ALL_TESTS();
125+
}

google/cloud/spanner/integration_tests/spanner_client_integration_tests.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ spanner_client_integration_tests = [
2424
"database_admin_integration_test.cc",
2525
"instance_admin_integration_test.cc",
2626
"rpc_failure_threshold_integration_test.cc",
27+
"session_pool_integration_test.cc",
2728
]

google/cloud/spanner/internal/session_pool.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ namespace cloud {
4343
namespace spanner {
4444
inline namespace SPANNER_CLIENT_NS {
4545
namespace internal {
46+
struct SessionPoolFriendForTest;
4647

4748
/**
4849
* Maintains a pool of `Session` objects.
@@ -134,6 +135,7 @@ class SessionPool : public std::enable_shared_from_this<SessionPool> {
134135
SessionHolder MakeSessionHolder(std::unique_ptr<Session> session,
135136
bool dissociate_from_pool);
136137

138+
friend struct SessionPoolFriendForTest; // To test Async*()
137139
// Asynchronous calls used to maintain the pool.
138140
future<StatusOr<google::spanner::v1::BatchCreateSessionsResponse>>
139141
AsyncBatchCreateSessions(CompletionQueue& cq,

0 commit comments

Comments
 (0)