1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
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
16 #include <gtest/gtest.h>
17 #include <thread>
18
19 #include "db_common.h"
20 #include "db_constant.h"
21 #include "db_types.h"
22 #include "distributeddb_data_generate_unit_test.h"
23 #include "ikvdb_raw_cursor.h"
24 #include "kv_store_nb_delegate_impl.h"
25 #include "kvdb_manager.h"
26 #include "platform_specific.h"
27 #include "result_entries_window.h"
28 #include "sqlite_single_ver_forward_cursor.h"
29 #include "sqlite_single_ver_natural_store.h"
30 #include "sqlite_single_ver_natural_store_connection.h"
31
32 using namespace testing::ext;
33 using namespace DistributedDB;
34 using namespace DistributedDBUnitTest;
35 using namespace std;
36
37 namespace {
38 string g_testDir;
39 string g_identifier;
40 IKvDBRawCursor *g_rawCursor = nullptr;
41 KvStoreDelegateManager g_mgr(APP_ID, USER_ID);
42 KvStoreConfig g_config;
43 KvStoreNbDelegate *g_kvNbDelegatePtr = nullptr;
44 DBStatus g_kvDelegateStatus = INVALID_ARGS;
45 SQLiteSingleVerNaturalStore *g_store = nullptr;
46 DistributedDB::SQLiteSingleVerNaturalStoreConnection *g_connection = nullptr;
47 const string STORE_ID = STORE_ID_SYNC;
48 auto g_kvNbDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback,
49 placeholders::_1, placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvNbDelegatePtr));
50 const int TIME_LAG = 100;
51 const int INITIAL_POSITION = 0;
52 const int SECOND_POSITION = 1;
53 const int TOTAL_COUNT = 3;
54 const Key KEY_PREFIX = {'K'};
55 const Key LOCAL_KEY_1 = {'K', '1'};
56 const Key LOCAL_KEY_2 = {'K', '2'};
57 const Key LOCAL_KEY_3 = {'K', '3'};
58 const Key LOCAL_KEY_4 = {'K', '4'};
59 }
60
61 class DistributedDBInterfacesSingleVersionResultSetTest : public testing::Test {
62 public:
63 static void SetUpTestCase(void);
64 static void TearDownTestCase(void);
65 void SetUp();
66 void TearDown();
67 };
68
SetUpTestCase(void)69 void DistributedDBInterfacesSingleVersionResultSetTest::SetUpTestCase(void)
70 {
71 DistributedDBToolsUnitTest::TestDirInit(g_testDir);
72 g_config.dataDir = g_testDir;
73 g_mgr.SetKvStoreConfig(g_config);
74 std::string origIdentifier = USER_ID + "-" + APP_ID + "-" + STORE_ID;
75 std::string identifier = DBCommon::TransferHashString(origIdentifier);
76 g_identifier = DBCommon::TransferStringToHex(identifier);
77 string dir = g_testDir + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR;
78 DIR *dirTmp = opendir(dir.c_str());
79 if (dirTmp == nullptr) {
80 OS::MakeDBDirectory(dir);
81 } else {
82 closedir(dirTmp);
83 }
84 }
85
TearDownTestCase(void)86 void DistributedDBInterfacesSingleVersionResultSetTest::TearDownTestCase(void)
87 {
88 if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + STORE_ID + "/" + DBConstant::SINGLE_SUB_DIR) != 0) {
89 LOGE("rm test db files error!");
90 }
91
92 std::this_thread::sleep_for(std::chrono::milliseconds(TIME_LAG));
93 }
94
SetUp(void)95 void DistributedDBInterfacesSingleVersionResultSetTest::SetUp(void)
96 {
97 DistributedDBToolsUnitTest::PrintTestCaseInfo();
98 KvStoreNbDelegate::Option delegateOption = {true};
99 g_mgr.GetKvStore(STORE_ID, delegateOption, g_kvNbDelegateCallback);
100 EXPECT_TRUE(g_kvDelegateStatus == OK);
101 ASSERT_TRUE(g_kvNbDelegatePtr != nullptr);
102
103 KvDBProperties property;
104 property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir);
105 property.SetStringProp(KvDBProperties::STORE_ID, STORE_ID);
106 property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier);
107 property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE);
108
109 g_store = new (std::nothrow) SQLiteSingleVerNaturalStore;
110 ASSERT_NE(g_store, nullptr);
111 ASSERT_EQ(g_store->Open(property), E_OK);
112
113 int errCode = E_OK;
114 g_connection = static_cast<SQLiteSingleVerNaturalStoreConnection *>(g_store->GetDBConnection(errCode));
115 ASSERT_NE(g_connection, nullptr);
116 g_store->DecObjRef(g_store);
117 EXPECT_EQ(errCode, E_OK);
118
119 /**
120 * @tc.steps:step1. Put 3 data items.
121 * @tc.expected: step1.
122 */
123 IOption option;
124 option.dataType = IOption::SYNC_DATA;
125 g_connection->Clear(option);
126 ASSERT_EQ(g_connection->Put(option, LOCAL_KEY_1, VALUE_1), E_OK);
127 ASSERT_EQ(g_connection->Put(option, LOCAL_KEY_2, VALUE_2), E_OK);
128 ASSERT_EQ(g_connection->Put(option, LOCAL_KEY_3, VALUE_3), E_OK);
129
130 EXPECT_EQ(errCode, E_OK);
131 g_rawCursor = new (std::nothrow) SQLiteSingleVerForwardCursor(g_store, KEY_PREFIX);
132 ASSERT_NE(g_rawCursor, nullptr);
133 }
134
TearDown(void)135 void DistributedDBInterfacesSingleVersionResultSetTest::TearDown(void)
136 {
137 if (g_connection != nullptr) {
138 g_connection->Close();
139 g_connection = nullptr;
140 }
141
142 g_store = nullptr;
143
144 if (g_kvNbDelegatePtr != nullptr) {
145 EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK);
146 g_kvNbDelegatePtr = nullptr;
147 EXPECT_TRUE(g_mgr.DeleteKvStore(STORE_ID) == OK);
148 }
149
150 if (g_rawCursor != nullptr) {
151 delete g_rawCursor;
152 g_rawCursor = nullptr;
153 }
154
155 std::this_thread::sleep_for(std::chrono::milliseconds(TIME_LAG));
156 }
157
158 /**
159 * @tc.name: SingleVersionResultSetTest001
160 * @tc.desc: CursorWindow Class: Return error when the window size too large.
161 * @tc.type: FUNC
162 * @tc.require: AR000D08KT
163 * @tc.author: maokeheng
164 */
165 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest001, TestSize.Level1)
166 {
167 /**
168 * @tc.steps:step1. Let the WindowSize be INT_MAX, which is larger than the upper limit.
169 * @tc.expected: step1. Expect return -E_INVALID_ARGS.
170 */
171 ResultEntriesWindow resultWindow;
172 double scale = 1;
173 int64_t windoweSize = 0x100000000L; // 4G
174 EXPECT_EQ(resultWindow.Init(g_rawCursor, windoweSize, scale), -E_INVALID_ARGS);
175 }
176
177 /**
178 * @tc.name: SingleVersionResultSetTest002
179 * @tc.desc: CursorWindow Class: Return error when the window size is negative.
180 * @tc.type: FUNC
181 * @tc.require: AR000D08KT
182 * @tc.author: maokeheng
183 */
184 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest002, TestSize.Level1)
185 {
186 /**
187 * @tc.steps:step1. Let the WindowSize be -1.
188 * @tc.expected: step1. Expect return -E_INVALID_ARGS.
189 */
190 ResultEntriesWindow resultWindow;
191 double scale = 1;
192 int windowSize = -1;
193 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), -E_INVALID_ARGS);
194 }
195
196 /**
197 * @tc.name: SingleVersionResultSetTest003
198 * @tc.desc: CursorWindow Class: Return error when the window size is zero.
199 * @tc.type: FUNC
200 * @tc.require: AR000D08KT
201 * @tc.author: maokeheng
202 */
203 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest003, TestSize.Level1)
204 {
205 /**
206 * @tc.steps:step1. Let the WindowSize be 0.
207 * @tc.expected: step1. Expect return -E_INVALID_ARGS.
208 */
209 ResultEntriesWindow resultWindow;
210 double scale = 1;
211 int windowSize = 0;
212 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), -E_INVALID_ARGS);
213 }
214
215 /**
216 * @tc.name: SingleVersionResultSetTest004
217 * @tc.desc: CursorWindow Class: Return OK when the window size is positive.
218 * @tc.type: FUNC
219 * @tc.require: AR000D08KT
220 * @tc.author: maokeheng
221 */
222 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest004, TestSize.Level1)
223 {
224 /**
225 * @tc.steps:step1. Let the WindowSize be 100, which is smaller than the upper limit.
226 * @tc.expected: step1. Expect return OK.
227 */
228 ResultEntriesWindow resultWindow;
229 double scale = 1;
230 int windowSize = 100;
231 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), E_OK);
232 }
233
234 /**
235 * @tc.name: SingleVersionResultSetTest005
236 * @tc.desc: CursorWindow Class: Return -E_INVALID_ARGS when the window scale is negative.
237 * @tc.type: FUNC
238 * @tc.require: AR000D08KT
239 * @tc.author: maokeheng
240 */
241 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest005, TestSize.Level1)
242 {
243 /**
244 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be negative (-1).
245 * @tc.expected: step1. Expect return -E_INVALID_ARGS.
246 */
247 ResultEntriesWindow resultWindow;
248 double scale = -1;
249 int windowSize = 100;
250 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), -E_INVALID_ARGS);
251 }
252
253 /**
254 * @tc.name: SingleVersionResultSetTest006
255 * @tc.desc: CursorWindow Class: Return -E_INVALID_ARGS when the window scale is larger than 1.
256 * @tc.type: FUNC
257 * @tc.require: AR000D08KT
258 * @tc.author: maokeheng
259 */
260 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest006, TestSize.Level1)
261 {
262 /**
263 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 2.
264 * @tc.expected: step1. Expect return -E_INVALID_ARGS.
265 */
266 ResultEntriesWindow resultWindow;
267 double scale = 2;
268 int windowSize = 100;
269 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), -E_INVALID_ARGS);
270 }
271
272 /**
273 * @tc.name: SingleVersionResultSetTest007
274 * @tc.desc: CursorWindow Class: Return -E_INVALID_ARGS when the window scale 0.
275 * @tc.type: FUNC
276 * @tc.require: AR000D08KT
277 * @tc.author: maokeheng
278 */
279 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest007, TestSize.Level1)
280 {
281 /**
282 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 0.
283 * @tc.expected: step1. Expect return -E_INVALID_ARGS.
284 */
285 ResultEntriesWindow resultWindow;
286 double scale = 0;
287 int windowSize = 100;
288 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), -E_INVALID_ARGS);
289 }
290
291 /**
292 * @tc.name: SingleVersionResultSetTest008
293 * @tc.desc: CursorWindow Class: Return OK when the window scale is between 0 and 1.
294 * @tc.type: FUNC
295 * @tc.require: AR000D08KT
296 * @tc.author: maokeheng
297 */
298 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest008, TestSize.Level1)
299 {
300 /**
301 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 0.5.
302 * @tc.expected: step1. Expect return OK.
303 */
304 ResultEntriesWindow resultWindow;
305 double scale = 0.5;
306 int windowSize = 100;
307 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), E_OK);
308 }
309
310 /**
311 * @tc.name: SingleVersionResultSetTest009
312 * @tc.desc: CursorWindow Class: Return -E_INVALID_ARGS when the g_rawCursor is nulSSSlptr.
313 * @tc.type: FUNC
314 * @tc.require: AR000D08KT
315 * @tc.author: maokeheng
316 */
317 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest009, TestSize.Level1)
318 {
319 /**
320 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 1 and resultWindow be null pointer.
321 * @tc.expected: step1. Expect return -E_INVALID_ARGS.
322 */
323 IKvDBRawCursor *rawCursor = nullptr;
324 ResultEntriesWindow resultWindow;
325 double scale = 1;
326 int windowSize = 100;
327 EXPECT_EQ(resultWindow.Init(rawCursor, windowSize, scale), -E_INVALID_ARGS);
328 }
329
330 /**
331 * @tc.name: SingleVersionResultSetTest010
332 * @tc.desc: CursorWindow Class: Check if get total count is feasible.
333 * @tc.type: FUNC
334 * @tc.require: AR000D08KT
335 * @tc.author: maokeheng
336 */
337 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest010, TestSize.Level1)
338 {
339 /**
340 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 1 and resultWindow be null pointer.
341 * @tc.expected: step1. Expect return OK.
342 */
343 ResultEntriesWindow resultWindow;
344 double scale = 1;
345 int windowSize = 100;
346 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), E_OK);
347
348 /**
349 * @tc.steps:step2. Get the total count.
350 * @tc.expected: step2. Expect return 3.
351 */
352 EXPECT_EQ(resultWindow.GetTotalCount(), TOTAL_COUNT);
353 }
354
355 /**
356 * @tc.name: SingleVersionResultSetTest011
357 * @tc.desc: CursorWindow Class: Check if get total count is feasible and the inserted items after
358 * creating ResultEntriesWindow have not been counted.
359 * @tc.type: FUNC
360 * @tc.require: AR000D08KT
361 * @tc.author: maokeheng
362 */
363 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest011, TestSize.Level1)
364 {
365 /**
366 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 1 and resultWindow be null pointer.
367 * @tc.expected: step1. Expect return OK.
368 */
369 ResultEntriesWindow resultWindow;
370 double scale = 1;
371 int windowSize = 100;
372 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), E_OK);
373
374 /**
375 * @tc.steps:step2. Get the total count.
376 * @tc.expected: step2. Expect return 3.
377 */
378 EXPECT_EQ(resultWindow.GetTotalCount(), TOTAL_COUNT);
379
380 /**
381 * @tc.steps:step3. Put one more item
382 * @tc.expected: step3.
383 */
384 IOption option;
385 option.dataType = IOption::SYNC_DATA;
386 ASSERT_EQ(g_connection->Put(option, LOCAL_KEY_4, VALUE_4), E_OK);
387
388 /**
389 * @tc.steps:step4. Get the total count.
390 * @tc.expected: step4. Expect return 3.
391 */
392 EXPECT_EQ(resultWindow.GetTotalCount(), TOTAL_COUNT);
393 }
394
395 /**
396 * @tc.name: SingleVersionResultSetTest012
397 * @tc.desc: CursorWindow Class: Check if current position after initialization is at 0.
398 * @tc.type: FUNC
399 * @tc.require: AR000D08KT
400 * @tc.author: maokeheng
401 */
402 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest012, TestSize.Level1)
403 {
404 /**
405 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 1 and resultWindow be null pointer.
406 * @tc.expected: step1. Expect return OK.
407 */
408 ResultEntriesWindow resultWindow;
409 double scale = 1;
410 int windowSize = 100;
411 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), E_OK);
412
413 /**
414 * @tc.steps:step2. Get initial position.
415 * @tc.expected: step2. Expect return INITIAL_POSITION (which is 0).
416 */
417 EXPECT_EQ(resultWindow.GetCurrentPosition(), INITIAL_POSITION);
418
419 /**
420 * @tc.steps:step3. Get entry .
421 * @tc.expected: step3. Expect return E_OK.
422 */
423 Entry entry;
424 EXPECT_EQ(resultWindow.GetEntry(entry), E_OK);
425 EXPECT_EQ(entry.key, LOCAL_KEY_1);
426 EXPECT_EQ(entry.value, VALUE_1);
427 }
428
429 /**
430 * @tc.name: SingleVersionResultSetTest013
431 * @tc.desc: CursorWindow Class: Check if current position after move is at the right place+.
432 * @tc.type: FUNC
433 * @tc.require: AR000D08KT
434 * @tc.author: maokeheng
435 */
436 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest013, TestSize.Level1)
437 {
438 /**
439 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 1 and resultWindow be null pointer.
440 * @tc.expected: step1. Expect return OK.
441 */
442 ResultEntriesWindow resultWindow;
443 double scale = 1;
444 int windowSize = 100;
445 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), E_OK);
446
447 /**
448 * @tc.steps:step2. move to second position.
449 * @tc.expected: step2. Expect return SECOND_POSITION (which is 2).
450 */
451 EXPECT_EQ(resultWindow.MoveToPosition(SECOND_POSITION), true);
452 EXPECT_EQ(resultWindow.GetCurrentPosition(), SECOND_POSITION);
453
454 /**
455 * @tc.steps:step3. Get entry .
456 * @tc.expected: step3. Expect return OK and entry corresponds to the right item.
457 */
458 Entry entry;
459 EXPECT_EQ(resultWindow.GetEntry(entry), E_OK);
460 EXPECT_EQ(entry.key, LOCAL_KEY_2);
461 EXPECT_EQ(entry.value, VALUE_2);
462 }
463
464 /**
465 * @tc.name: SingleVersionResultSetTest014
466 * @tc.desc: CursorWindow Class: Move to negative position and the position bounces back to zero.
467 * @tc.type: FUNC
468 * @tc.require: AR000D08KT
469 * @tc.author: maokeheng
470 */
471 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest014, TestSize.Level1)
472 {
473 /**
474 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 1 and resultWindow be null pointer.
475 * @tc.expected: step1. Expect return OK.
476 */
477 ResultEntriesWindow resultWindow;
478 double scale = 1;
479 int windowSize = 100;
480 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), E_OK);
481
482 /**
483 * @tc.steps:step2. move to second position.
484 * @tc.expected: step2. Expect return false and initial position.
485 */
486 int negativePosition = -2;
487 EXPECT_EQ(resultWindow.MoveToPosition(negativePosition), false);
488 EXPECT_EQ(resultWindow.GetCurrentPosition(), INITIAL_POSITION);
489
490 /**
491 * @tc.steps:step3. Get entry .
492 * @tc.expected: step3. Expect return E_OK.
493 */
494 Entry entry;
495 EXPECT_EQ(resultWindow.GetEntry(entry), E_OK);
496 EXPECT_EQ(entry.key, LOCAL_KEY_1);
497 EXPECT_EQ(entry.value, VALUE_1);
498 }
499
500 /**
501 * @tc.name: SingleVersionResultSetTest015
502 * @tc.desc: CursorWindow Class: Move to position larger than N and the position bounces back to original position.
503 * @tc.type: FUNC
504 * @tc.require: AR000D08KT
505 * @tc.author: maokeheng
506 */
507 HWTEST_F(DistributedDBInterfacesSingleVersionResultSetTest, SingleVersionResultSetTest015, TestSize.Level1)
508 {
509 /**
510 * @tc.steps:step1. Let the WindowSize be 100, and window scale to be 1 and resultWindow be null pointer.
511 * @tc.expected: step1. Expect return OK.
512 */
513 ResultEntriesWindow resultWindow;
514 double scale = 1;
515 int windowSize = 100;
516 EXPECT_EQ(resultWindow.Init(g_rawCursor, windowSize, scale), E_OK);
517
518 /**
519 * @tc.steps:step2. move to second position.
520 * @tc.expected: step2. Expect return false and move to total count.
521 */
522 int largePosition = TOTAL_COUNT + 1;
523 EXPECT_EQ(resultWindow.MoveToPosition(largePosition), false);
524 EXPECT_EQ(resultWindow.GetCurrentPosition(), INITIAL_POSITION);
525
526 /**
527 * @tc.steps:step3. Get entry .
528 * @tc.expected: step3. Expect return VALUE_1.
529 */
530 Entry entry;
531 EXPECT_EQ(resultWindow.GetEntry(entry), E_OK);
532 EXPECT_EQ(entry.key, LOCAL_KEY_1);
533 EXPECT_EQ(entry.value, VALUE_1);
534 }