1 | /** |
2 | * Copyright 2021 Alibaba, Inc. and its affiliates. All Rights Reserved. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | * |
16 | * \author hongqing.hu |
17 | * \date Dec 2020 |
18 | * \brief |
19 | */ |
20 | |
21 | #include <gtest/gtest.h> |
22 | |
23 | #define private public |
24 | #include "repository/binlog/info_fetcher.h" |
25 | #include "mock_mysql_connector.h" |
26 | #undef private |
27 | |
28 | #include "repository/repository_common/error_code.h" |
29 | |
30 | using namespace ::proxima::be; |
31 | using namespace proxima::be::repository; |
32 | |
33 | class InfoFetcherTest : public testing::Test { |
34 | protected: |
35 | void SetUp() { |
36 | mgr_ = std::make_shared<MysqlConnectorManager>(); |
37 | ASSERT_TRUE(mgr_); |
38 | connector_ = std::make_shared<MockMysqlConnector>(); |
39 | ASSERT_TRUE(connector_); |
40 | mgr_->put(connector_); |
41 | connection_uri_ = "mysql://root:[email protected]:3306/mytest" ; |
42 | user_ = "root" ; |
43 | password_ = "root" ; |
44 | ASSERT_TRUE(ailego::Uri::Parse(connection_uri_.c_str(), &uri_)); |
45 | table_name_ = "table" ; |
46 | |
47 | InitFetcher(); |
48 | } |
49 | |
50 | void TearDown() {} |
51 | |
52 | MockMysqlResultWrapperPtr BuildQuerySchemaResult() { |
53 | MockMysqlResultWrapperPtr result = |
54 | std::make_shared<MockMysqlResultWrapper>(); |
55 | result->append_field_meta("id" , MYSQL_TYPE_LONG, 11, 0, |
56 | AUTO_INCREMENT_FLAG); |
57 | result->append_field_meta("name" , MYSQL_TYPE_VAR_STRING, 100); |
58 | result->append_field_meta("age" , MYSQL_TYPE_LONG, 11); |
59 | result->append_field_meta("score" , MYSQL_TYPE_FLOAT, 12); |
60 | result->append_field_meta("vector1" , MYSQL_TYPE_VAR_STRING, 1024); |
61 | result->append_field_meta("vector2" , MYSQL_TYPE_VAR_STRING, 1024); |
62 | result->append_field_meta("vector3" , MYSQL_TYPE_VAR_STRING, 1024); |
63 | |
64 | std::vector<std::string> values1 = { |
65 | "1" , "name1" , "18" , "123.456" , "1,2,3,4" , "1,2,3,5" , "1,2,3,6" }; |
66 | result->append_row_values(values1); |
67 | std::vector<std::string> values2 = { |
68 | "2" , "name2" , "19" , "223.456" , "2,2,3,4" , "2,2,3,5" , "2,2,3,6" }; |
69 | result->append_row_values(values2); |
70 | std::vector<std::string> values3 = { |
71 | "3" , "name3" , "29" , "323.456" , "3,2,3,4" , "3,2,3,5" , "3,2,3,6" }; |
72 | result->append_row_values(values3); |
73 | |
74 | return result; |
75 | } |
76 | |
77 | MockMysqlResultWrapperPtr BuildQueryCollationResult() { |
78 | MockMysqlResultWrapperPtr result = |
79 | std::make_shared<MockMysqlResultWrapper>(); |
80 | result->append_field_meta("Field" , MYSQL_TYPE_VAR_STRING, 11); |
81 | result->append_field_meta("Type" , MYSQL_TYPE_VAR_STRING, 100); |
82 | result->append_field_meta("Collation" , MYSQL_TYPE_VAR_STRING, 11); |
83 | |
84 | std::vector<std::string> values1 = {"id" , "" , "" }; |
85 | result->append_row_values(values1); |
86 | std::vector<std::string> values2 = {"name" , "" , "utf8_general_ci" }; |
87 | result->append_row_values(values2); |
88 | std::vector<std::string> values3 = {"age" , "" , "" }; |
89 | result->append_row_values(values3); |
90 | std::vector<std::string> values4 = {"score" , "" , "utf8_general_ci" }; |
91 | result->append_row_values(values4); |
92 | std::vector<std::string> values5 = {"vector1" , "" , "utf8_general_ci" }; |
93 | result->append_row_values(values5); |
94 | std::vector<std::string> values6 = {"vector2" , "" , "utf8_general_ci" }; |
95 | result->append_row_values(values6); |
96 | std::vector<std::string> values7 = {"vector3" , "" , "utf8_general_ci" }; |
97 | result->append_row_values(values7); |
98 | |
99 | return result; |
100 | } |
101 | |
102 | MockMysqlResultWrapperPtr BuildInvalidQueryCollationResult() { |
103 | MockMysqlResultWrapperPtr result = |
104 | std::make_shared<MockMysqlResultWrapper>(); |
105 | result->append_field_meta("Field" , MYSQL_TYPE_VAR_STRING, 11); |
106 | result->append_field_meta("invalid" , MYSQL_TYPE_VAR_STRING, 100); |
107 | result->append_field_meta("Type" , MYSQL_TYPE_VAR_STRING, 100); |
108 | result->append_field_meta("Collation" , MYSQL_TYPE_VAR_STRING, 11); |
109 | |
110 | std::vector<std::string> values1 = {"id" , "" , "" , "" }; |
111 | result->append_row_values(values1); |
112 | std::vector<std::string> values2 = {"name" , "" , "" , "utf8_general_ci" }; |
113 | result->append_row_values(values2); |
114 | std::vector<std::string> values3 = {"age" , "" , "" , "" }; |
115 | result->append_row_values(values3); |
116 | std::vector<std::string> values4 = {"score" , "" , "" , "utf8_general_ci" }; |
117 | result->append_row_values(values4); |
118 | std::vector<std::string> values5 = {"vector1" , "" , "" , "utf8_general_ci" }; |
119 | result->append_row_values(values5); |
120 | std::vector<std::string> values6 = {"vector2" , "" , "" , "utf8_general_ci" }; |
121 | result->append_row_values(values6); |
122 | std::vector<std::string> values7 = {"vector3" , "" , "" , "utf8_general_ci" }; |
123 | result->append_row_values(values7); |
124 | |
125 | return result; |
126 | } |
127 | |
128 | MockMysqlResultWrapperPtr BuildSnapshotResult() { |
129 | MockMysqlResultWrapperPtr result = |
130 | std::make_shared<MockMysqlResultWrapper>(); |
131 | result->append_field_meta("File" ); |
132 | result->append_field_meta("Position" ); |
133 | result->append_field_meta("Binlog_Do_DB" ); |
134 | result->append_field_meta("Binlog_Ignore_DB" ); |
135 | result->append_field_meta("Executed_Gtid_Set" ); |
136 | |
137 | std::vector<std::string> values1 = {"binlog.000001" , "10240" , "" , "" , "" }; |
138 | result->append_row_values(values1); |
139 | |
140 | return result; |
141 | } |
142 | |
143 | MockMysqlResultWrapperPtr BuildInvalidRowsSnapshotResult() { |
144 | MockMysqlResultWrapperPtr result = |
145 | std::make_shared<MockMysqlResultWrapper>(); |
146 | result->append_field_meta("File" ); |
147 | result->append_field_meta("Position" ); |
148 | result->append_field_meta("Binlog_Do_DB" ); |
149 | result->append_field_meta("Binlog_Ignore_DB" ); |
150 | result->append_field_meta("Executed_Gtid_Set" ); |
151 | |
152 | return result; |
153 | } |
154 | |
155 | MockMysqlResultWrapperPtr BuildEmptySnapshotResult() { |
156 | MockMysqlResultWrapperPtr result = |
157 | std::make_shared<MockMysqlResultWrapper>(); |
158 | result->append_field_meta("File" ); |
159 | result->append_field_meta("Position" ); |
160 | result->append_field_meta("Binlog_Do_DB" ); |
161 | result->append_field_meta("Binlog_Ignore_DB" ); |
162 | result->append_field_meta("Executed_Gtid_Set" ); |
163 | |
164 | return result; |
165 | } |
166 | |
167 | MockMysqlResultWrapperPtr BuildInvalidFieldSnapshotResult() { |
168 | MockMysqlResultWrapperPtr result = |
169 | std::make_shared<MockMysqlResultWrapper>(); |
170 | result->append_field_meta("File" ); |
171 | result->append_field_meta("Position" ); |
172 | result->append_field_meta("Binlog_Do_DB" ); |
173 | result->append_field_meta("Binlog_Ignore_DB" ); |
174 | // result->append_field_meta("Executed_Gtid_Set"); |
175 | std::vector<std::string> values1 = {"binlog.000001" , "10240" , "" , "" }; |
176 | result->append_row_values(values1); |
177 | return result; |
178 | } |
179 | |
180 | MockMysqlResultWrapperPtr BuildInvalidSnapshotResult() { |
181 | MockMysqlResultWrapperPtr result = |
182 | std::make_shared<MockMysqlResultWrapper>(); |
183 | result->append_field_meta("Invalid" ); |
184 | result->append_field_meta("Position" ); |
185 | result->append_field_meta("Binlog_Do_DB" ); |
186 | result->append_field_meta("Binlog_Ignore_DB" ); |
187 | result->append_field_meta("Executed_Gtid_Set" ); |
188 | |
189 | std::vector<std::string> values1 = {"binlog.000001" , "10240" , "" , "" , "" }; |
190 | result->append_row_values(values1); |
191 | |
192 | return result; |
193 | } |
194 | |
195 | void BuildCollectionConfig(CollectionConfig &config) { |
196 | auto *repo = config.mutable_repository_config(); |
197 | repo->set_repository_type(CollectionConfig::RepositoryConfig::RT_DATABASE); |
198 | repo->set_repository_name(table_name_); |
199 | auto *database = repo->mutable_database(); |
200 | database->set_connection_uri(connection_uri_); |
201 | database->set_table_name(table_name_); |
202 | database->set_user(user_); |
203 | database->set_password(password_); |
204 | |
205 | config.add_forward_column_names("name" ); |
206 | config.add_forward_column_names("age" ); |
207 | auto *index1 = config.add_index_column_params(); |
208 | index1->set_column_name("vector1" ); |
209 | auto *index2 = config.add_index_column_params(); |
210 | index2->set_column_name("vector2" ); |
211 | } |
212 | |
213 | void InitFetcher() { |
214 | CollectionConfig config; |
215 | BuildCollectionConfig(config); |
216 | |
217 | // init |
218 | ailego::Uri test_uri = uri_; |
219 | EXPECT_CALL(*connector_, uri()) |
220 | .WillOnce( |
221 | Invoke([&test_uri]() -> const ailego::Uri & { return test_uri; })) |
222 | .RetiresOnSaturation(); |
223 | fetcher_ = std::make_shared<InfoFetcher>(config, mgr_); |
224 | int ret = fetcher_->init(); |
225 | ASSERT_EQ(ret, 0); |
226 | ASSERT_EQ(fetcher_->database(), "mytest" ); |
227 | } |
228 | |
229 | protected: |
230 | MysqlConnectorManagerPtr mgr_{}; |
231 | MockMysqlConnectorPtr connector_{}; |
232 | std::string connection_uri_{}; |
233 | std::string user_{}; |
234 | std::string password_{}; |
235 | ailego::Uri uri_{}; |
236 | std::string table_name_{}; |
237 | InfoFetcherPtr fetcher_{}; |
238 | }; |
239 | |
240 | TEST_F(InfoFetcherTest, TestSimple) { |
241 | // build schema result |
242 | MockMysqlResultWrapperPtr result1 = BuildQueryCollationResult(); |
243 | MockMysqlResultWrapperPtr result = BuildQuerySchemaResult(); |
244 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
245 | .Times(2) |
246 | .WillOnce(Invoke([&result1](const std::string &, |
247 | MysqlResultWrapperPtr *out, bool) -> int { |
248 | *out = result1; |
249 | return 0; |
250 | })) |
251 | .WillOnce(Invoke([&result](const std::string &, |
252 | MysqlResultWrapperPtr *out, bool) -> int { |
253 | *out = result; |
254 | return 0; |
255 | })) |
256 | .RetiresOnSaturation(); |
257 | // get table schema |
258 | TableSchemaPtr schema; |
259 | int ret = fetcher_->get_table_schema(table_name_, &schema); |
260 | ASSERT_EQ(ret, 0); |
261 | auto &forward_ids = schema->selected_forward_ids(); |
262 | ASSERT_EQ(forward_ids.size(), (size_t)2); |
263 | ASSERT_EQ(forward_ids[0], (size_t)1); |
264 | ASSERT_EQ(forward_ids[1], (size_t)2); |
265 | auto &index_ids = schema->selected_index_ids(); |
266 | ASSERT_EQ(index_ids.size(), (size_t)2); |
267 | ASSERT_EQ(index_ids[0], (size_t)4); |
268 | ASSERT_EQ(index_ids[1], (size_t)5); |
269 | |
270 | // get table snapshot |
271 | MysqlResultWrapperPtr snapshot_result = BuildSnapshotResult(); |
272 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
273 | .Times(3) |
274 | .WillOnce(testing::Return(0)) |
275 | .WillOnce( |
276 | Invoke([&snapshot_result](const std::string &, |
277 | MysqlResultWrapperPtr *out, bool) -> int { |
278 | *out = snapshot_result; |
279 | return 0; |
280 | })) |
281 | .WillOnce(testing::Return(0)) |
282 | .RetiresOnSaturation(); |
283 | std::string file_name; |
284 | uint64_t position; |
285 | ret = fetcher_->get_table_snapshot(table_name_, &file_name, &position); |
286 | ASSERT_EQ(ret, 0); |
287 | ASSERT_EQ(file_name, "binlog.000001" ); |
288 | ASSERT_EQ(position, (uint64_t)10240); |
289 | } |
290 | |
291 | TEST_F(InfoFetcherTest, TestGetTableSchemaWithExecuteQueryFailed) { |
292 | // build schema result |
293 | MockMysqlResultWrapperPtr result1 = BuildQueryCollationResult(); |
294 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
295 | .Times(2) |
296 | .WillOnce(Invoke([&result1](const std::string &, |
297 | MysqlResultWrapperPtr *out, bool) -> int { |
298 | *out = result1; |
299 | return 0; |
300 | })) |
301 | .WillOnce(Invoke([](const std::string &, MysqlResultWrapperPtr *out, |
302 | bool) -> int { return 1; })) |
303 | .RetiresOnSaturation(); |
304 | // execute query failed |
305 | TableSchemaPtr schema; |
306 | int ret = fetcher_->get_table_schema(table_name_, &schema); |
307 | ASSERT_EQ(ret, 1); |
308 | } |
309 | |
310 | TEST_F(InfoFetcherTest, TestGetTableSchemaWithGetCollationInfoFailed) { |
311 | // build schema result |
312 | MockMysqlResultWrapperPtr result1 = BuildQueryCollationResult(); |
313 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
314 | .Times(1) |
315 | .WillOnce(Invoke([&result1](const std::string &, |
316 | MysqlResultWrapperPtr *out, bool) -> int { |
317 | *out = result1; |
318 | return 1; |
319 | })) |
320 | .RetiresOnSaturation(); |
321 | // execute query failed |
322 | TableSchemaPtr schema; |
323 | int ret = fetcher_->get_table_schema(table_name_, &schema); |
324 | ASSERT_EQ(ret, ErrorCode_ExecuteMysql); |
325 | } |
326 | |
327 | TEST_F(InfoFetcherTest, TestGetTableSchemaWithParseTableSchemaFailed) { |
328 | MockMysqlResultWrapperPtr result = BuildQuerySchemaResult(); |
329 | MockMysqlResultWrapperPtr result1 = BuildQueryCollationResult(); |
330 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
331 | .Times(2) |
332 | .WillOnce(Invoke([&result1](const std::string &, |
333 | MysqlResultWrapperPtr *out, bool) -> int { |
334 | *out = result1; |
335 | return 0; |
336 | })) |
337 | .WillOnce(Invoke([&result](const std::string &, |
338 | MysqlResultWrapperPtr *out, bool) -> int { |
339 | *out = result; |
340 | return 0; |
341 | })) |
342 | .RetiresOnSaturation(); |
343 | // parse table schema failed |
344 | TableSchemaPtr schema; |
345 | fetcher_->selected_fields_->index_fields_.push_back("invalid_column" ); |
346 | int ret = fetcher_->get_table_schema(table_name_, &schema); |
347 | ASSERT_EQ(ret, ErrorCode_InvalidCollectionConfig); |
348 | } |
349 | |
350 | TEST_F(InfoFetcherTest, TestGetTableSchemaSuccess) { |
351 | MockMysqlResultWrapperPtr result1 = BuildQueryCollationResult(); |
352 | MockMysqlResultWrapperPtr result = BuildQuerySchemaResult(); |
353 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
354 | .Times(2) |
355 | .WillOnce(Invoke([&result1](const std::string &, |
356 | MysqlResultWrapperPtr *out, bool) -> int { |
357 | *out = result1; |
358 | return 0; |
359 | })) |
360 | .WillOnce(Invoke([&result](const std::string &, |
361 | MysqlResultWrapperPtr *out, bool) -> int { |
362 | *out = result; |
363 | return 0; |
364 | })) |
365 | .RetiresOnSaturation(); |
366 | // success |
367 | TableSchemaPtr schema; |
368 | int ret = fetcher_->get_table_schema(table_name_, &schema); |
369 | ASSERT_EQ(ret, 0); |
370 | } |
371 | |
372 | TEST_F(InfoFetcherTest, TestGetCollationInfoSuccess) { |
373 | MockMysqlResultWrapperPtr result1 = BuildQueryCollationResult(); |
374 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
375 | .Times(1) |
376 | .WillOnce(Invoke([&result1](const std::string &, |
377 | MysqlResultWrapperPtr *out, bool) -> int { |
378 | *out = result1; |
379 | return 0; |
380 | })) |
381 | .RetiresOnSaturation(); |
382 | std::map<std::string, std::string> kv; |
383 | int ret = fetcher_->get_collation_info("t1" , kv); |
384 | ASSERT_EQ(ret, 0); |
385 | EXPECT_EQ(kv.size(), (size_t)7); |
386 | EXPECT_EQ(kv["id" ], "" ); |
387 | EXPECT_EQ(kv["name" ], "utf8_general_ci" ); |
388 | EXPECT_EQ(kv["age" ], "" ); |
389 | EXPECT_EQ(kv["score" ], "utf8_general_ci" ); |
390 | EXPECT_EQ(kv["vector1" ], "utf8_general_ci" ); |
391 | EXPECT_EQ(kv["vector2" ], "utf8_general_ci" ); |
392 | EXPECT_EQ(kv["vector3" ], "utf8_general_ci" ); |
393 | } |
394 | |
395 | TEST_F(InfoFetcherTest, TestGetCollationInfoWithExecuteFailed) { |
396 | MockMysqlResultWrapperPtr result1 = BuildQueryCollationResult(); |
397 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
398 | .Times(1) |
399 | .WillOnce(Invoke([&result1](const std::string &, |
400 | MysqlResultWrapperPtr *out, bool) -> int { |
401 | *out = result1; |
402 | return 1; |
403 | })) |
404 | .RetiresOnSaturation(); |
405 | std::map<std::string, std::string> kv; |
406 | int ret = fetcher_->get_collation_info("t1" , kv); |
407 | ASSERT_EQ(ret, ErrorCode_ExecuteMysql); |
408 | } |
409 | |
410 | TEST_F(InfoFetcherTest, TestGetCollationInfoWithInvalidResultFailed) { |
411 | MockMysqlResultWrapperPtr result1 = BuildInvalidQueryCollationResult(); |
412 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
413 | .Times(1) |
414 | .WillOnce(Invoke([&result1](const std::string &, |
415 | MysqlResultWrapperPtr *out, bool) -> int { |
416 | *out = result1; |
417 | return 0; |
418 | })) |
419 | .RetiresOnSaturation(); |
420 | std::map<std::string, std::string> kv; |
421 | int ret = fetcher_->get_collation_info("t1" , kv); |
422 | ASSERT_EQ(ret, ErrorCode_InvalidMysqlResult); |
423 | } |
424 | |
425 | TEST_F(InfoFetcherTest, TestGetTableSnapshotSuccess) { |
426 | // get table snapshot |
427 | MysqlResultWrapperPtr snapshot_result = BuildSnapshotResult(); |
428 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
429 | .Times(3) |
430 | .WillOnce(testing::Return(0)) |
431 | .WillOnce( |
432 | Invoke([&snapshot_result](const std::string &, |
433 | MysqlResultWrapperPtr *out, bool) -> int { |
434 | *out = snapshot_result; |
435 | return 0; |
436 | })) |
437 | .WillOnce(testing::Return(0)) |
438 | .RetiresOnSaturation(); |
439 | std::string file_name; |
440 | uint64_t position; |
441 | int ret = fetcher_->get_table_snapshot(table_name_, &file_name, &position); |
442 | ASSERT_EQ(ret, 0); |
443 | ASSERT_EQ(file_name, "binlog.000001" ); |
444 | ASSERT_EQ(position, (uint64_t)10240); |
445 | } |
446 | |
447 | TEST_F(InfoFetcherTest, TestGetTableSnapshotWithLockTableFailed) { |
448 | // get table snapshot |
449 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
450 | .Times(1) |
451 | .WillOnce(testing::Return(1)) |
452 | .RetiresOnSaturation(); |
453 | std::string file_name; |
454 | uint64_t position; |
455 | int ret = fetcher_->get_table_snapshot(table_name_, &file_name, &position); |
456 | ASSERT_EQ(ret, ErrorCode_ExecuteMysql); |
457 | } |
458 | |
459 | TEST_F(InfoFetcherTest, TestGetTableSnapshotWithGetInternalFailed) { |
460 | // get table snapshot |
461 | MysqlResultWrapperPtr snapshot_result = BuildSnapshotResult(); |
462 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
463 | .Times(3) |
464 | .WillOnce(testing::Return(0)) |
465 | .WillOnce( |
466 | Invoke([&snapshot_result](const std::string &, |
467 | MysqlResultWrapperPtr *out, bool) -> int { |
468 | *out = snapshot_result; |
469 | return 1; |
470 | })) |
471 | .WillOnce(testing::Return(0)) |
472 | .RetiresOnSaturation(); |
473 | std::string file_name; |
474 | uint64_t position; |
475 | int ret = fetcher_->get_table_snapshot(table_name_, &file_name, &position); |
476 | ASSERT_EQ(ret, ErrorCode_ExecuteMysql); |
477 | } |
478 | |
479 | TEST_F(InfoFetcherTest, TestGetTableSnapshotInternalSuccess) { |
480 | // get table snapshot |
481 | MysqlResultWrapperPtr snapshot_result = BuildSnapshotResult(); |
482 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
483 | .Times(1) |
484 | .WillOnce( |
485 | Invoke([&snapshot_result](const std::string &, |
486 | MysqlResultWrapperPtr *out, bool) -> int { |
487 | *out = snapshot_result; |
488 | return 0; |
489 | })) |
490 | .RetiresOnSaturation(); |
491 | std::string file_name; |
492 | uint64_t position; |
493 | int ret = fetcher_->get_table_snapshot_internal(&file_name, &position); |
494 | ASSERT_EQ(ret, 0); |
495 | ASSERT_EQ(file_name, "binlog.000001" ); |
496 | ASSERT_EQ(position, (uint64_t)10240); |
497 | } |
498 | |
499 | TEST_F(InfoFetcherTest, TestGetTableSnapshotInternalWithExecuteQueryFailed) { |
500 | // get table snapshot |
501 | MysqlResultWrapperPtr snapshot_result = BuildSnapshotResult(); |
502 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
503 | .Times(1) |
504 | .WillOnce( |
505 | Invoke([&snapshot_result](const std::string &, |
506 | MysqlResultWrapperPtr *out, bool) -> int { |
507 | *out = snapshot_result; |
508 | return 1; |
509 | })) |
510 | .RetiresOnSaturation(); |
511 | std::string file_name; |
512 | uint64_t position; |
513 | int ret = fetcher_->get_table_snapshot_internal(&file_name, &position); |
514 | ASSERT_EQ(ret, ErrorCode_ExecuteMysql); |
515 | } |
516 | |
517 | TEST_F(InfoFetcherTest, TestGetTableSnapshotInternalWithInvaildRowsResult) { |
518 | // get table snapshot |
519 | MysqlResultWrapperPtr snapshot_result = BuildInvalidRowsSnapshotResult(); |
520 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
521 | .Times(1) |
522 | .WillOnce( |
523 | Invoke([&snapshot_result](const std::string &, |
524 | MysqlResultWrapperPtr *out, bool) -> int { |
525 | *out = snapshot_result; |
526 | return 0; |
527 | })) |
528 | .RetiresOnSaturation(); |
529 | std::string file_name; |
530 | uint64_t position; |
531 | int ret = fetcher_->get_table_snapshot_internal(&file_name, &position); |
532 | ASSERT_EQ(ret, ErrorCode_InvalidMysqlResult); |
533 | } |
534 | |
535 | TEST_F(InfoFetcherTest, TestGetTableSnapshotInternalWithEmptyRow) { |
536 | // get table snapshot |
537 | MysqlResultWrapperPtr snapshot_result = BuildEmptySnapshotResult(); |
538 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
539 | .Times(1) |
540 | .WillOnce( |
541 | Invoke([&snapshot_result](const std::string &, |
542 | MysqlResultWrapperPtr *out, bool) -> int { |
543 | *out = snapshot_result; |
544 | return 0; |
545 | })) |
546 | .RetiresOnSaturation(); |
547 | std::string file_name; |
548 | uint64_t position; |
549 | int ret = fetcher_->get_table_snapshot_internal(&file_name, &position); |
550 | ASSERT_EQ(ret, ErrorCode_InvalidMysqlResult); |
551 | } |
552 | |
553 | TEST_F(InfoFetcherTest, TestGetTableSnapshotInternalWithInvalidFieldsNum) { |
554 | // get table snapshot |
555 | MysqlResultWrapperPtr snapshot_result = BuildInvalidFieldSnapshotResult(); |
556 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
557 | .Times(1) |
558 | .WillOnce( |
559 | Invoke([&snapshot_result](const std::string &, |
560 | MysqlResultWrapperPtr *out, bool) -> int { |
561 | *out = snapshot_result; |
562 | return 0; |
563 | })) |
564 | .RetiresOnSaturation(); |
565 | std::string file_name; |
566 | uint64_t position; |
567 | int ret = fetcher_->get_table_snapshot_internal(&file_name, &position); |
568 | ASSERT_EQ(ret, ErrorCode_InvalidMysqlResult); |
569 | } |
570 | |
571 | TEST_F(InfoFetcherTest, TestGetTableSnapshotInternalWithInvalidResult) { |
572 | // get table snapshot |
573 | MysqlResultWrapperPtr snapshot_result = BuildInvalidSnapshotResult(); |
574 | EXPECT_CALL(*connector_, execute_query(_, _, _)) |
575 | .Times(1) |
576 | .WillOnce( |
577 | Invoke([&snapshot_result](const std::string &, |
578 | MysqlResultWrapperPtr *out, bool) -> int { |
579 | *out = snapshot_result; |
580 | return 0; |
581 | })) |
582 | .RetiresOnSaturation(); |
583 | std::string file_name; |
584 | uint64_t position; |
585 | int ret = fetcher_->get_table_snapshot_internal(&file_name, &position); |
586 | ASSERT_EQ(ret, ErrorCode_InvalidMysqlResult); |
587 | } |
588 | |