1 // Copyright 2017 Google Inc.
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/bigtable/table.h"
16 #include "google/cloud/bigtable/testing/mock_read_rows_reader.h"
17 #include "google/cloud/bigtable/testing/table_test_fixture.h"
18 #include "google/cloud/testing_util/assert_ok.h"
19
20 namespace bigtable = google::cloud::bigtable;
21 using testing::_;
22 using testing::DoAll;
23 using testing::Return;
24 using testing::SetArgPointee;
25
26 /// Define helper types and functions for this test.
27 namespace {
28 class TableReadRowsTest : public bigtable::testing::TableTestFixture {};
29 using bigtable::testing::MockReadRowsReader;
30 } // anonymous namespace
31
TEST_F(TableReadRowsTest,ReadRowsCanReadOneRow)32 TEST_F(TableReadRowsTest, ReadRowsCanReadOneRow) {
33 auto response = bigtable::testing::ReadRowsResponseFromString(R"(
34 chunks {
35 row_key: "r1"
36 family_name { value: "fam" }
37 qualifier { value: "qual" }
38 timestamp_micros: 42000
39 value: "value"
40 commit_row: true
41 }
42 )");
43
44 // must be a new pointer, it is wrapped in unique_ptr by ReadRows
45 auto stream = new MockReadRowsReader("google.bigtable.v2.Bigtable.ReadRows");
46 EXPECT_CALL(*stream, Read(_))
47 .WillOnce(DoAll(SetArgPointee<0>(response), Return(true)))
48 .WillOnce(Return(false));
49 EXPECT_CALL(*stream, Finish()).WillOnce(Return(grpc::Status::OK));
50 EXPECT_CALL(*client_, ReadRows(_, _)).WillOnce(stream->MakeMockReturner());
51
52 auto reader =
53 table_.ReadRows(bigtable::RowSet(), bigtable::Filter::PassAllFilter());
54
55 auto it = reader.begin();
56 EXPECT_NE(it, reader.end());
57 ASSERT_STATUS_OK(*it);
58 EXPECT_EQ((*it)->row_key(), "r1");
59 EXPECT_EQ(++it, reader.end());
60 }
61
TEST_F(TableReadRowsTest,ReadRowsCanReadWithRetries)62 TEST_F(TableReadRowsTest, ReadRowsCanReadWithRetries) {
63 auto response = bigtable::testing::ReadRowsResponseFromString(R"(
64 chunks {
65 row_key: "r1"
66 family_name { value: "fam" }
67 qualifier { value: "qual" }
68 timestamp_micros: 42000
69 value: "value"
70 commit_row: true
71 }
72 )");
73
74 auto response_retry = bigtable::testing::ReadRowsResponseFromString(R"(
75 chunks {
76 row_key: "r2"
77 family_name { value: "fam" }
78 qualifier { value: "qual" }
79 timestamp_micros: 42000
80 value: "value"
81 commit_row: true
82 }
83 )");
84
85 // must be a new pointer, it is wrapped in unique_ptr by ReadRows
86 auto stream = new MockReadRowsReader("google.bigtable.v2.Bigtable.ReadRows");
87 auto stream_retry =
88 new MockReadRowsReader("google.bigtable.v2.Bigtable.ReadRows");
89
90 EXPECT_CALL(*client_, ReadRows(_, _))
91 .WillOnce(stream->MakeMockReturner())
92 .WillOnce(stream_retry->MakeMockReturner());
93
94 EXPECT_CALL(*stream, Read(_))
95 .WillOnce(DoAll(SetArgPointee<0>(response), Return(true)))
96 .WillOnce(Return(false));
97
98 EXPECT_CALL(*stream, Finish())
99 .WillOnce(
100 Return(grpc::Status(grpc::StatusCode::UNAVAILABLE, "try-again")));
101
102 EXPECT_CALL(*stream_retry, Read(_))
103 .WillOnce(DoAll(SetArgPointee<0>(response_retry), Return(true)))
104 .WillOnce(Return(false));
105
106 EXPECT_CALL(*stream_retry, Finish()).WillOnce(Return(grpc::Status::OK));
107
108 auto reader =
109 table_.ReadRows(bigtable::RowSet(), bigtable::Filter::PassAllFilter());
110
111 auto it = reader.begin();
112 EXPECT_NE(it, reader.end());
113 ASSERT_STATUS_OK(*it);
114 EXPECT_EQ((*it)->row_key(), "r1");
115 ++it;
116 EXPECT_NE(it, reader.end());
117 ASSERT_STATUS_OK(*it);
118 EXPECT_EQ((*it)->row_key(), "r2");
119 EXPECT_EQ(++it, reader.end());
120 }
121
TEST_F(TableReadRowsTest,ReadRowsThrowsWhenTooManyErrors)122 TEST_F(TableReadRowsTest, ReadRowsThrowsWhenTooManyErrors) {
123 EXPECT_CALL(*client_, ReadRows(_, _)).WillRepeatedly(testing::WithoutArgs([] {
124 auto stream =
125 new MockReadRowsReader("google.bigtable.v2.Bigtable.ReadRows");
126 EXPECT_CALL(*stream, Read(_)).WillOnce(Return(false));
127 EXPECT_CALL(*stream, Finish())
128 .WillOnce(
129 Return(grpc::Status(grpc::StatusCode::UNAVAILABLE, "broken")));
130 return stream->AsUniqueMocked();
131 }));
132
133 auto table = bigtable::Table(
134 client_, "table_id", bigtable::LimitedErrorCountRetryPolicy(3),
135 bigtable::ExponentialBackoffPolicy(std::chrono::seconds(0),
136 std::chrono::seconds(0)),
137 bigtable::SafeIdempotentMutationPolicy());
138 auto reader =
139 table.ReadRows(bigtable::RowSet(), bigtable::Filter::PassAllFilter());
140
141 auto it = reader.begin();
142 ASSERT_NE(reader.end(), it);
143 ASSERT_FALSE(*it);
144 ++it;
145 ASSERT_EQ(reader.end(), it);
146 }
147