1313// limitations under the License.
1414
1515#include " google/cloud/bigtable/client.h"
16+ #include " google/cloud/bigtable/mocks/mock_data_connection.h"
17+ #include " google/cloud/bigtable/mocks/mock_query_row.h"
18+ #include " google/cloud/bigtable/mocks/mock_row_reader.h"
19+ #include " google/cloud/bigtable/query_row.h"
20+ #include " google/cloud/stream_range.h"
1621#include " google/cloud/testing_util/fake_completion_queue_impl.h"
1722#include " google/cloud/testing_util/status_matchers.h"
18- #include " mocks/mock_data_connection.h "
23+ #include < google/protobuf/text_format.h >
1924
2025namespace google {
2126namespace cloud {
@@ -24,7 +29,10 @@ GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
2429namespace {
2530
2631using ::google::bigtable::v2::PrepareQueryResponse;
32+ using ::google::cloud::testing_util::FakeCompletionQueueImpl;
33+ using ::google::cloud::testing_util::IsOkAndHolds;
2734using ::google::cloud::testing_util::StatusIs;
35+ using ::testing::Return;
2836
2937TEST (Client, PrepareQuery) {
3038 auto fake_cq_impl = std::make_shared<testing_util::FakeCompletionQueueImpl>();
@@ -71,23 +79,91 @@ TEST(Client, AsyncPrepareQuery) {
7179 fake_cq_impl->SimulateCompletion (false );
7280}
7381
74- TEST (Client, ExecuteQuery) {
75- auto fake_cq_impl = std::make_shared<testing_util::FakeCompletionQueueImpl>();
76- auto conn = MakeDataConnection ();
77- Client client (conn);
82+ class MockQueryRowSource : public ResultSourceInterface {
83+ public:
84+ MOCK_METHOD (StatusOr<QueryRow>, NextRow, (), (override ));
85+ MOCK_METHOD (absl::optional<google::bigtable::v2::ResultSetMetadata>, Metadata,
86+ (), (override ));
87+ };
88+
89+ TEST (ClientTest, ExecuteQuery) {
90+ auto conn_mock = std::make_shared<bigtable_mocks::MockDataConnection>();
91+ auto fake_cq_impl = std::make_shared<FakeCompletionQueueImpl>();
92+ auto refresh_fn = []() {
93+ return make_ready_future (
94+ StatusOr<google::bigtable::v2::PrepareQueryResponse>(
95+ Status{StatusCode::kUnimplemented , " not implemented" }));
96+ };
97+ PrepareQueryResponse pq_response;
98+ pq_response.set_prepared_query (" test-pq-id-54321" );
99+ auto constexpr kResultMetadataText = R"pb(
100+ proto_schema {
101+ columns {
102+ name: "key"
103+ type { string_type {} }
104+ }
105+ columns {
106+ name: "val"
107+ type { string_type {} }
108+ }
109+ }
110+ )pb" ;
111+ ASSERT_TRUE (google::protobuf::TextFormat::ParseFromString (
112+ kResultMetadataText , pq_response.mutable_metadata ()));
113+ EXPECT_CALL (*conn_mock, ExecuteQuery)
114+ .WillOnce (
115+ [&](bigtable::ExecuteQueryParams const &) -> StatusOr<RowStream> {
116+ auto mock_source = std::make_unique<MockQueryRowSource>();
117+ EXPECT_CALL (*mock_source, Metadata)
118+ .WillRepeatedly (Return (pq_response.metadata ()));
119+
120+ testing::InSequence s;
121+ EXPECT_CALL (*mock_source, NextRow)
122+ .WillOnce (Return (bigtable_mocks::MakeQueryRow (
123+ {{" key" , bigtable::Value (" r1" )},
124+ {" val" , bigtable::Value (" v1" )}})));
125+ EXPECT_CALL (*mock_source, NextRow)
126+ .WillOnce (Return (bigtable_mocks::MakeQueryRow (
127+ {{" key" , bigtable::Value (" r2" )},
128+ {" val" , bigtable::Value (" v2" )}})));
129+ EXPECT_CALL (*mock_source, NextRow)
130+ // Signal end of stream
131+ .WillOnce (
132+ Return (Status (StatusCode::kOutOfRange , " End of stream" )));
133+
134+ // Create RowStream with the mock result source
135+ RowStream row_stream (std::move (mock_source));
136+ return StatusOr<RowStream>(std::move (row_stream));
137+ });
138+
139+ Client client (conn_mock);
78140 InstanceResource instance (Project (" test-project" ), " test-instance" );
79141 SqlStatement sql (" SELECT * FROM `test-table`" );
80- auto prepared_query = PreparedQuery (CompletionQueue{fake_cq_impl}, instance,
81- sql, PrepareQueryResponse{});
142+ auto query_plan = bigtable_internal::QueryPlan::Create (
143+ CompletionQueue (fake_cq_impl), std::move (pq_response),
144+ std::move (refresh_fn));
145+ auto prepared_query = PreparedQuery (instance, sql, std::move (query_plan));
82146 auto bound_query = prepared_query.BindParameters ({});
83- auto row_stream = client.ExecuteQuery (std::move (bound_query));
84- // We expect a row stream with a single unimplemented status row while
85- // this is not implemented.
86- for (auto const & row : row_stream) {
87- EXPECT_THAT (row.status (),
88- StatusIs (StatusCode::kUnimplemented , " not implemented" ));
147+ RowStream row_stream = client.ExecuteQuery (std::move (bound_query));
148+ std::vector<StatusOr<bigtable::QueryRow>> rows;
149+ for (auto const & row : std::move (row_stream)) {
150+ rows.push_back (row);
89151 }
90- EXPECT_EQ (1 , std::distance (row_stream.begin (), row_stream.end ()));
152+
153+ ASSERT_EQ (rows.size (), 3 );
154+ ASSERT_STATUS_OK (rows[0 ]);
155+ auto const & row1 = *rows[0 ];
156+ EXPECT_EQ (row1.columns ().size (), 2 );
157+ EXPECT_THAT (row1.values ()[0 ].get <std::string>(), IsOkAndHolds (" r1" ));
158+ EXPECT_THAT (row1.values ()[1 ].get <std::string>(), IsOkAndHolds (" v1" ));
159+
160+ ASSERT_STATUS_OK (rows[1 ]);
161+ auto const & row2 = *rows[1 ];
162+ EXPECT_EQ (row2.columns ().size (), 2 );
163+ EXPECT_THAT (row2.values ()[0 ].get <std::string>(), IsOkAndHolds (" r2" ));
164+ EXPECT_THAT (row2.values ()[1 ].get <std::string>(), IsOkAndHolds (" v2" ));
165+
166+ EXPECT_THAT (rows[2 ], StatusIs (StatusCode::kOutOfRange , " End of stream" ));
91167
92168 // Cancel all pending operations, satisfying any remaining futures.
93169 fake_cq_impl->SimulateCompletion (false );
0 commit comments