1 /*
2 * Copyright (c) 2022 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 <condition_variable>
17 #include <gtest/gtest.h>
18 #include <thread>
19
20 #include "db_constant.h"
21 #include "distributeddb_data_generate_unit_test.h"
22 #include "distributeddb_tools_unit_test.h"
23 #include "kv_store_nb_delegate.h"
24 #include "kv_virtual_device.h"
25 #include "platform_specific.h"
26 #include "relational_store_manager.h"
27 #include "runtime_config.h"
28
29 using namespace testing::ext;
30 using namespace DistributedDB;
31 using namespace DistributedDBUnitTest;
32 using namespace std;
33
34 namespace {
35 std::shared_ptr<std::string> g_testDir = nullptr;
36 VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr;
37 const std::string DEVICE_A = "real_device";
38 const std::string DEVICE_B = "deviceB";
39 const std::string KEY_INSTANCE_ID = "INSTANCE_ID";
40 KvVirtualDevice *g_deviceB = nullptr;
41 DistributedDBToolsUnitTest g_tool;
42
OpenDelegate(const std::string & dlpPath,KvStoreNbDelegate * & delegatePtr,KvStoreDelegateManager & mgr,bool syncDualTupleMode=false)43 DBStatus OpenDelegate(const std::string &dlpPath, KvStoreNbDelegate *&delegatePtr,
44 KvStoreDelegateManager &mgr, bool syncDualTupleMode = false)
45 {
46 if (g_testDir == nullptr) {
47 return DB_ERROR;
48 }
49 std::string dbPath = *g_testDir + dlpPath;
50 KvStoreConfig storeConfig;
51 storeConfig.dataDir = dbPath;
52 OS::MakeDBDirectory(dbPath);
53 mgr.SetKvStoreConfig(storeConfig);
54
55 string dir = dbPath + "/single_ver";
56 DIR* dirTmp = opendir(dir.c_str());
57 if (dirTmp == nullptr) {
58 OS::MakeDBDirectory(dir);
59 } else {
60 closedir(dirTmp);
61 }
62
63 KvStoreNbDelegate::Option option;
64 option.syncDualTupleMode = syncDualTupleMode;
65 DBStatus res = OK;
66 mgr.GetKvStore(STORE_ID_1, option, [&delegatePtr, &res](DBStatus status, KvStoreNbDelegate *delegate) {
67 delegatePtr = delegate;
68 res = status;
69 });
70 return res;
71 }
72
OpenDelegate(const std::string & dlpPath,RelationalStoreDelegate * & rdbDelegatePtr,RelationalStoreManager & mgr)73 DBStatus OpenDelegate(const std::string &dlpPath, RelationalStoreDelegate *&rdbDelegatePtr,
74 RelationalStoreManager &mgr)
75 {
76 if (g_testDir == nullptr) {
77 return DB_ERROR;
78 }
79 std::string dbDir = *g_testDir + dlpPath;
80 OS::MakeDBDirectory(dbDir);
81 std::string dbPath = dbDir + "/test.db";
82 auto db = RelationalTestUtils::CreateDataBase(dbPath);
83 EXPECT_EQ(sqlite3_exec(db, "PRAGMA journal_mode=WAL;", nullptr, nullptr, nullptr), SQLITE_OK);
84 RelationalStoreDelegate::Option option;
85 return mgr.OpenStore(dbPath, STORE_ID_1, option, rdbDelegatePtr);
86 }
87
CloseDelegate(KvStoreNbDelegate * & delegatePtr,KvStoreDelegateManager & mgr,std::string storeID)88 void CloseDelegate(KvStoreNbDelegate *&delegatePtr, KvStoreDelegateManager &mgr, std::string storeID)
89 {
90 if (delegatePtr == nullptr) {
91 return;
92 }
93 EXPECT_EQ(mgr.CloseKvStore(delegatePtr), OK);
94 delegatePtr = nullptr;
95 EXPECT_EQ(mgr.DeleteKvStore(storeID), OK);
96 }
97
CloseDelegate(RelationalStoreDelegate * & delegatePtr,RelationalStoreManager & mgr)98 void CloseDelegate(RelationalStoreDelegate *&delegatePtr, RelationalStoreManager &mgr)
99 {
100 if (delegatePtr == nullptr) {
101 return;
102 }
103 EXPECT_EQ(mgr.CloseStore(delegatePtr), OK);
104 delegatePtr = nullptr;
105 }
106 }
107
108 class DistributedDBSingleVerDLPTest : public testing::Test {
109 public:
110 static void SetUpTestCase(void);
111 static void TearDownTestCase(void);
112 void SetUp();
113 void TearDown();
114 };
115
SetUpTestCase(void)116 void DistributedDBSingleVerDLPTest::SetUpTestCase(void)
117 {
118 /**
119 * @tc.setup: Init datadir and Virtual Communicator.
120 */
121 std::string testDir;
122 DistributedDBToolsUnitTest::TestDirInit(testDir);
123 if (g_testDir == nullptr) {
124 g_testDir = std::make_shared<std::string>(testDir);
125 }
126
127 g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
128 ASSERT_TRUE(g_communicatorAggregator != nullptr);
129 RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
130 }
131
TearDownTestCase(void)132 void DistributedDBSingleVerDLPTest::TearDownTestCase(void)
133 {
134 /**
135 * @tc.teardown: Release virtual Communicator and clear data dir.
136 */
137 if (g_testDir != nullptr && DistributedDBToolsUnitTest::RemoveTestDbFiles(*g_testDir) != 0) {
138 LOGE("rm test db files error!");
139 }
140 RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
141 }
142
SetUp(void)143 void DistributedDBSingleVerDLPTest::SetUp(void)
144 {
145 DistributedDBToolsUnitTest::PrintTestCaseInfo();
146 g_deviceB = new (std::nothrow) KvVirtualDevice(DEVICE_B);
147 ASSERT_TRUE(g_deviceB != nullptr);
148 VirtualSingleVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface();
149 ASSERT_TRUE(syncInterfaceB != nullptr);
150 ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK);
151 }
152
TearDown(void)153 void DistributedDBSingleVerDLPTest::TearDown(void)
154 {
155 if (g_deviceB != nullptr) {
156 delete g_deviceB;
157 g_deviceB = nullptr;
158 }
159 PermissionCheckCallbackV3 nullCallback = nullptr;
160 RuntimeConfig::SetPermissionCheckCallback(nullCallback);
161 SyncActivationCheckCallbackV2 activeCallBack = nullptr;
162 RuntimeConfig::SetSyncActivationCheckCallback(activeCallBack);
163 RuntimeConfig::SetPermissionConditionCallback(nullptr);
164 }
165
166 /**
167 * @tc.name: SameDelegateTest001
168 * @tc.desc: Test kv delegate open with diff instanceID.
169 * @tc.type: FUNC
170 * @tc.require: SR000H0JSC
171 * @tc.author: zhangqiquan
172 */
173 HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest001, TestSize.Level1)
174 {
175 KvStoreDelegateManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
176 KvStoreNbDelegate *delegatePtr1 = nullptr;
177 EXPECT_EQ(OpenDelegate("/dlp1", delegatePtr1, mgr1), OK);
178 ASSERT_NE(delegatePtr1, nullptr);
179
180 KvStoreDelegateManager mgr2(APP_ID, USER_ID, INSTANCE_ID_2);
181 KvStoreNbDelegate *delegatePtr2 = nullptr;
182 EXPECT_EQ(OpenDelegate("/dlp2", delegatePtr2, mgr2), OK);
183 ASSERT_NE(delegatePtr2, nullptr);
184
185 Key key1 = {'k', '1'};
186 Value value1 = {'v', '1'};
187 delegatePtr1->Put(key1, value1);
188 Key key2 = {'k', '2'};
189 Value value2 = {'v', '2'};
190 delegatePtr2->Put(key2, value2);
191
192 Value value;
193 EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
194 EXPECT_EQ(value1, value);
195 EXPECT_EQ(delegatePtr2->Get(key2, value), OK);
196 EXPECT_EQ(value2, value);
197
198 EXPECT_EQ(delegatePtr1->Get(key2, value), NOT_FOUND);
199 EXPECT_EQ(delegatePtr2->Get(key1, value), NOT_FOUND);
200
201 CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
202 CloseDelegate(delegatePtr2, mgr2, STORE_ID_1);
203 }
204
205 /**
206 * @tc.name: SameDelegateTest002
207 * @tc.desc: Test rdb delegate open with diff instanceID.
208 * @tc.type: FUNC
209 * @tc.require: SR000H0JSC
210 * @tc.author: zhangqiquan
211 */
212 HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest002, TestSize.Level1)
213 {
214 RelationalStoreManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
215 RelationalStoreDelegate *rdbDelegatePtr1 = nullptr;
216 EXPECT_EQ(OpenDelegate("/dlp1", rdbDelegatePtr1, mgr1), OK);
217 ASSERT_NE(rdbDelegatePtr1, nullptr);
218
219 RelationalStoreManager mgr2(APP_ID, USER_ID, INSTANCE_ID_2);
220 RelationalStoreDelegate *rdbDelegatePtr2 = nullptr;
221 EXPECT_EQ(OpenDelegate("/dlp2", rdbDelegatePtr2, mgr2), OK);
222 ASSERT_NE(rdbDelegatePtr2, nullptr);
223
224 CloseDelegate(rdbDelegatePtr1, mgr1);
225 CloseDelegate(rdbDelegatePtr2, mgr2);
226 }
227
228 /**
229 * @tc.name: DlpDelegateCRUDTest001
230 * @tc.desc: Test dlp delegate crud function.
231 * @tc.type: FUNC
232 * @tc.require: SR000H0JSC
233 * @tc.author: zhangqiquan
234 */
235 HWTEST_F(DistributedDBSingleVerDLPTest, DlpDelegateCRUDTest001, TestSize.Level1)
236 {
237 KvStoreDelegateManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
238 KvStoreNbDelegate *delegatePtr1 = nullptr;
239 EXPECT_EQ(OpenDelegate("/dlp1", delegatePtr1, mgr1), OK);
240 ASSERT_NE(delegatePtr1, nullptr);
241
242 Key key1 = {'k', '1'};
243 Value value1 = {'v', '1'};
244 delegatePtr1->Put(key1, value1);
245
246 Value value;
247 EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
248 EXPECT_EQ(value1, value);
249
250 Value value2 = {'v', '2'};
251 delegatePtr1->Put(key1, value2);
252 EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
253 EXPECT_EQ(value2, value);
254
255 EXPECT_EQ(delegatePtr1->Delete(key1), OK);
256 EXPECT_EQ(delegatePtr1->Get(key1, value), NOT_FOUND);
257
258 CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
259 }
260
261 /**
262 * @tc.name: SandboxDelegateSync001
263 * @tc.desc: Test dlp delegate sync function.
264 * @tc.type: FUNC
265 * @tc.require: SR000H0JSC
266 * @tc.author: zhangqiquan
267 */
268 HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync001, TestSize.Level1)
269 {
270 KvStoreDelegateManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
__anon698725dc0302(const PermissionCheckParam ¶m, uint8_t flag) 271 RuntimeConfig::SetPermissionCheckCallback([](const PermissionCheckParam ¶m, uint8_t flag) {
272 if ((flag & PermissionCheckFlag::CHECK_FLAG_RECEIVE) != 0) {
273 bool res = false;
274 if (param.extraConditions.find(KEY_INSTANCE_ID) != param.extraConditions.end()) {
275 res = param.extraConditions.at(KEY_INSTANCE_ID) == std::to_string(INSTANCE_ID_1);
276 }
277 return res;
278 }
279 if (param.userId != USER_ID || param.appId != APP_ID || param.storeId != STORE_ID_1 ||
280 (param.instanceId != INSTANCE_ID_1 && param.instanceId != 0)) {
281 return false;
282 }
283 return true;
284 });
__anon698725dc0402(const PermissionConditionParam ¶m) 285 RuntimeConfig::SetPermissionConditionCallback([](const PermissionConditionParam ¶m) {
286 std::map<std::string, std::string> res;
287 res.emplace(KEY_INSTANCE_ID, std::to_string(INSTANCE_ID_1));
288 return res;
289 });
290
291 KvStoreNbDelegate *delegatePtr1 = nullptr;
292 EXPECT_EQ(OpenDelegate("/dlp1", delegatePtr1, mgr1), OK);
293 ASSERT_NE(delegatePtr1, nullptr);
294
295 Key key1 = {'k', '1'};
296 Value value1 = {'v', '1'};
297 delegatePtr1->Put(key1, value1);
298
299 std::map<std::string, DBStatus> result;
300 DBStatus status = g_tool.SyncTest(delegatePtr1, { DEVICE_B }, SYNC_MODE_PUSH_ONLY, result);
301 EXPECT_TRUE(status == OK);
302 EXPECT_EQ(result[DEVICE_B], OK);
303
304 CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
305 }
306
307 /**
308 * @tc.name: SandboxDelegateSync002
309 * @tc.desc: Test dlp delegate sync active if callback return true.
310 * @tc.type: FUNC
311 * @tc.require: SR000H0JSC
312 * @tc.author: zhangqiquan
313 */
314 HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync002, TestSize.Level1)
315 {
316 KvStoreDelegateManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
__anon698725dc0502(const ActivationCheckParam ¶m) 317 RuntimeConfig::SetSyncActivationCheckCallback([](const ActivationCheckParam ¶m) {
318 if (param.userId == USER_ID && param.appId == APP_ID && param.storeId == STORE_ID_1 &&
319 param.instanceId == INSTANCE_ID_1) {
320 return true;
321 }
322 return false;
323 });
324
325 KvStoreNbDelegate *delegatePtr1 = nullptr;
326 EXPECT_EQ(OpenDelegate("/dlp1", delegatePtr1, mgr1, true), OK);
327 ASSERT_NE(delegatePtr1, nullptr);
328
329 std::map<std::string, DBStatus> result;
330 DBStatus status = g_tool.SyncTest(delegatePtr1, { DEVICE_B }, SYNC_MODE_PUSH_ONLY, result);
331 EXPECT_EQ(status, OK);
332 EXPECT_EQ(result[DEVICE_B], OK);
333
334 CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
335 }