1 /*
2 * Copyright (c) 2025 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 "kv_general_ut.h"
17 #include "kv_store_nb_delegate_impl.h"
18
19 namespace DistributedDB {
20 using namespace testing::ext;
21 using namespace DistributedDB;
22 using namespace DistributedDBUnitTest;
23
24 class DistributedDBKvDeviceSyncTest : public KVGeneralUt {
25 public:
26 void SetUp() override;
27 protected:
28 static constexpr const char *DEVICE_A = "DEVICE_A";
29 static constexpr const char *DEVICE_B = "DEVICE_B";
30 DistributedDBToolsUnitTest g_tool;
31 };
32
SetUp()33 void DistributedDBKvDeviceSyncTest::SetUp()
34 {
35 KVGeneralUt::SetUp();
36 auto storeInfo1 = GetStoreInfo1();
37 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo1, DEVICE_A), E_OK);
38 auto storeInfo2 = GetStoreInfo2();
39 ASSERT_EQ(BasicUnitTest::InitDelegate(storeInfo2, DEVICE_B), E_OK);
40 }
41
42 /**
43 * @tc.name: NormalSyncTest001
44 * @tc.desc: Test normal sync without retry.
45 * @tc.type: FUNC
46 * @tc.require:
47 * @tc.author: liaoyonghuang
48 */
49 HWTEST_F(DistributedDBKvDeviceSyncTest, NormalSyncTest001, TestSize.Level0)
50 {
51 /**
52 * @tc.steps: step1. dev1 put (k,v)
53 * @tc.expected: step1. return OK
54 */
55 auto storeInfo1 = GetStoreInfo1();
56 auto store1 = GetDelegate(storeInfo1);
57 ASSERT_NE(store1, nullptr);
58 Key key = {'k'};
59 Value expectValue = {'v'};
60 EXPECT_EQ(store1->Put(key, expectValue), OK);
61 /**
62 * @tc.steps: step2. dev1 sync to dev2
63 * @tc.expected: step2. return OK and dev2 exist (k,v)
64 */
65 DeviceSyncOption option;
66 option.devices = {DEVICE_B};
67 option.mode = SYNC_MODE_PUSH_ONLY;
68 option.isRetry = false;
69 std::map<std::string, DBStatus> syncRet;
70 EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), OK);
71 for (const auto &ret : syncRet) {
72 EXPECT_EQ(ret.first, DEVICE_B);
73 EXPECT_EQ(ret.second, OK);
74 }
75 auto storeInfo2 = GetStoreInfo2();
76 auto store2 = GetDelegate(storeInfo2);
77 ASSERT_NE(store2, nullptr);
78 Value actualValue;
79 EXPECT_EQ(store2->Get(key, actualValue), OK);
80 EXPECT_EQ(actualValue, expectValue);
81 }
82
83 /**
84 * @tc.name: NormalSyncTest002
85 * @tc.desc: Test normal sync with multiple devices with the same name.
86 * @tc.type: FUNC
87 * @tc.require:
88 * @tc.author: liaoyonghuang
89 */
90 HWTEST_F(DistributedDBKvDeviceSyncTest, NormalSyncTest002, TestSize.Level1)
91 {
92 /**
93 * @tc.steps: step1. dev1 put (k,v)
94 * @tc.expected: step1. return OK
95 */
96 auto storeInfo1 = GetStoreInfo1();
97 auto store1 = GetDelegate(storeInfo1);
98 ASSERT_NE(store1, nullptr);
99 Key key = {'k'};
100 Value expectValue = {'v'};
101 EXPECT_EQ(store1->Put(key, expectValue), OK);
102 /**
103 * @tc.steps: step2. dev1 sync to dev2
104 * @tc.expected: step2. return OK and dev2 exist (k,v)
105 */
106 DeviceSyncOption option;
107 option.devices = {DEVICE_B, DEVICE_B, DEVICE_B};
108 option.mode = SYNC_MODE_PUSH_ONLY;
109 option.isRetry = false;
110 std::map<std::string, DBStatus> syncRet;
111 EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), OK);
112 for (const auto &ret : syncRet) {
113 EXPECT_EQ(ret.first, DEVICE_B);
114 EXPECT_EQ(ret.second, OK);
115 }
116 auto storeInfo2 = GetStoreInfo2();
117 auto store2 = GetDelegate(storeInfo2);
118 ASSERT_NE(store2, nullptr);
119 Value actualValue;
120 EXPECT_EQ(store2->Get(key, actualValue), OK);
121 EXPECT_EQ(actualValue, expectValue);
122 }
123
124 /**
125 * @tc.name: AbnormalKvSyncTest001
126 * @tc.desc: Test sync with invalid args.
127 * @tc.type: FUNC
128 * @tc.author: liaoyonghuang
129 */
130 HWTEST_F(DistributedDBKvDeviceSyncTest, AbnormalKvSyncTest001, TestSize.Level1)
131 {
132 /**
133 * @tc.steps: step1. dev1 put (k,v)
134 * @tc.expected: step1. return OK
135 */
136 auto storeInfo1 = GetStoreInfo1();
137 auto store1 = GetDelegate(storeInfo1);
138 ASSERT_NE(store1, nullptr);
139 Key key = {'k'};
140 Value expectValue = {'v'};
141 EXPECT_EQ(store1->Put(key, expectValue), OK);
142 /**
143 * @tc.steps: step2. dev1 sync to dev2 with invalid mode
144 * @tc.expected: step2. return NOT_SUPPORT
145 */
146 DeviceSyncOption option;
147 option.devices = {DEVICE_B};
148 option.mode = SYNC_MODE_CLOUD_MERGE;
149 option.isRetry = false;
150 std::map<std::string, DBStatus> syncRet;
151 EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT);
152 auto storeInfo2 = GetStoreInfo2();
153 auto store2 = GetDelegate(storeInfo2);
154 ASSERT_NE(store2, nullptr);
155 Value actualValue;
156 EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND);
157 option.mode = SYNC_MODE_PUSH_PULL;
158 /**
159 * @tc.steps: step3. dev1 sync to dev2 with invalid query
160 * @tc.expected: step3. return NOT_SUPPORT
161 */
162 option.isQuery = true;
163 option.query = Query::Select().FromTable({"table1", "table2"});
164 EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT);
165 EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND);
166 option.query = Query::Select().From("A").From("B");
167 EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), NOT_SUPPORT);
168 EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND);
169 /**
170 * @tc.steps: step4. dev1 sync to dev2 with empty devices
171 * @tc.expected: step4. return NOT_SUPPORT
172 */
173 option.devices.clear();
174 option.isQuery = false;
175 EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), INVALID_ARGS);
176 EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND);
177 /**
178 * @tc.steps: step5. dev1 sync to dev2 after close db
179 * @tc.expected: step5. return DB_ERROR
180 */
181 auto kvStoreImpl = static_cast<KvStoreNbDelegateImpl *>(store1);
182 EXPECT_EQ(kvStoreImpl->Close(), OK);
183 EXPECT_EQ(g_tool.SyncTest(store1, option, syncRet), DB_ERROR);
184 EXPECT_EQ(store2->Get(key, actualValue), NOT_FOUND);
185 }
186 }
187