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         EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK);
85         db = nullptr;
86         RelationalStoreDelegate::Option option;
87         return mgr.OpenStore(dbPath, STORE_ID_1, option, rdbDelegatePtr);
88     }
89 
CloseDelegate(KvStoreNbDelegate * & delegatePtr,KvStoreDelegateManager & mgr,std::string storeID)90     void CloseDelegate(KvStoreNbDelegate *&delegatePtr, KvStoreDelegateManager &mgr, std::string storeID)
91     {
92         if (delegatePtr == nullptr) {
93             return;
94         }
95         EXPECT_EQ(mgr.CloseKvStore(delegatePtr), OK);
96         delegatePtr = nullptr;
97         EXPECT_EQ(mgr.DeleteKvStore(storeID), OK);
98     }
99 
CloseDelegate(RelationalStoreDelegate * & delegatePtr,RelationalStoreManager & mgr)100     void CloseDelegate(RelationalStoreDelegate *&delegatePtr, RelationalStoreManager &mgr)
101     {
102         if (delegatePtr == nullptr) {
103             return;
104         }
105         EXPECT_EQ(mgr.CloseStore(delegatePtr), OK);
106         delegatePtr = nullptr;
107     }
108 }
109 
110 class DistributedDBSingleVerDLPTest : public testing::Test {
111 public:
112     static void SetUpTestCase(void);
113     static void TearDownTestCase(void);
114     void SetUp();
115     void TearDown();
116 };
117 
SetUpTestCase(void)118 void DistributedDBSingleVerDLPTest::SetUpTestCase(void)
119 {
120     /**
121      * @tc.setup: Init datadir and Virtual Communicator.
122      */
123     std::string testDir;
124     DistributedDBToolsUnitTest::TestDirInit(testDir);
125     if (g_testDir == nullptr) {
126         g_testDir = std::make_shared<std::string>(testDir);
127     }
128 
129     g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator();
130     ASSERT_TRUE(g_communicatorAggregator != nullptr);
131     RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator);
132 }
133 
TearDownTestCase(void)134 void DistributedDBSingleVerDLPTest::TearDownTestCase(void)
135 {
136     /**
137      * @tc.teardown: Release virtual Communicator and clear data dir.
138      */
139     if (g_testDir != nullptr && DistributedDBToolsUnitTest::RemoveTestDbFiles(*g_testDir) != 0) {
140         LOGE("rm test db files error!");
141     }
142     RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr);
143 }
144 
SetUp(void)145 void DistributedDBSingleVerDLPTest::SetUp(void)
146 {
147     DistributedDBToolsUnitTest::PrintTestCaseInfo();
148     g_deviceB = new (std::nothrow) KvVirtualDevice(DEVICE_B);
149     ASSERT_TRUE(g_deviceB != nullptr);
150     VirtualSingleVerSyncDBInterface *syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface();
151     ASSERT_TRUE(syncInterfaceB != nullptr);
152     ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK);
153 }
154 
TearDown(void)155 void DistributedDBSingleVerDLPTest::TearDown(void)
156 {
157     if (g_deviceB != nullptr) {
158         delete g_deviceB;
159         g_deviceB = nullptr;
160     }
161     PermissionCheckCallbackV3 nullCallback = nullptr;
162     RuntimeConfig::SetPermissionCheckCallback(nullCallback);
163     SyncActivationCheckCallbackV2 activeCallBack = nullptr;
164     RuntimeConfig::SetSyncActivationCheckCallback(activeCallBack);
165     RuntimeConfig::SetPermissionConditionCallback(nullptr);
166 }
167 
168 /**
169  * @tc.name: SameDelegateTest001
170  * @tc.desc: Test kv delegate open with diff instanceID.
171  * @tc.type: FUNC
172  * @tc.require: SR000H0JSC
173  * @tc.author: zhangqiquan
174  */
175 HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest001, TestSize.Level1)
176 {
177     KvStoreDelegateManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
178     KvStoreNbDelegate *delegatePtr1 = nullptr;
179     EXPECT_EQ(OpenDelegate("/dlp1", delegatePtr1, mgr1), OK);
180     ASSERT_NE(delegatePtr1, nullptr);
181 
182     KvStoreDelegateManager mgr2(APP_ID, USER_ID, INSTANCE_ID_2);
183     KvStoreNbDelegate *delegatePtr2 = nullptr;
184     EXPECT_EQ(OpenDelegate("/dlp2", delegatePtr2, mgr2), OK);
185     ASSERT_NE(delegatePtr2, nullptr);
186 
187     Key key1 = {'k', '1'};
188     Value value1 = {'v', '1'};
189     delegatePtr1->Put(key1, value1);
190     Key key2 = {'k', '2'};
191     Value value2 = {'v', '2'};
192     delegatePtr2->Put(key2, value2);
193 
194     Value value;
195     EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
196     EXPECT_EQ(value1, value);
197     EXPECT_EQ(delegatePtr2->Get(key2, value), OK);
198     EXPECT_EQ(value2, value);
199 
200     EXPECT_EQ(delegatePtr1->Get(key2, value), NOT_FOUND);
201     EXPECT_EQ(delegatePtr2->Get(key1, value), NOT_FOUND);
202 
203     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
204     CloseDelegate(delegatePtr2, mgr2, STORE_ID_1);
205 }
206 
207 /**
208  * @tc.name: SameDelegateTest002
209  * @tc.desc: Test rdb delegate open with diff instanceID.
210  * @tc.type: FUNC
211  * @tc.require: SR000H0JSC
212  * @tc.author: zhangqiquan
213  */
214 HWTEST_F(DistributedDBSingleVerDLPTest, SameDelegateTest002, TestSize.Level1)
215 {
216     RelationalStoreManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
217     RelationalStoreDelegate *rdbDelegatePtr1 = nullptr;
218     EXPECT_EQ(OpenDelegate("/dlp1", rdbDelegatePtr1, mgr1), OK);
219     ASSERT_NE(rdbDelegatePtr1, nullptr);
220 
221     RelationalStoreManager mgr2(APP_ID, USER_ID, INSTANCE_ID_2);
222     RelationalStoreDelegate *rdbDelegatePtr2 = nullptr;
223     EXPECT_EQ(OpenDelegate("/dlp2", rdbDelegatePtr2, mgr2), OK);
224     ASSERT_NE(rdbDelegatePtr2, nullptr);
225 
226     CloseDelegate(rdbDelegatePtr1, mgr1);
227     CloseDelegate(rdbDelegatePtr2, mgr2);
228 }
229 
230 /**
231  * @tc.name: DlpDelegateCRUDTest001
232  * @tc.desc: Test dlp delegate crud function.
233  * @tc.type: FUNC
234  * @tc.require: SR000H0JSC
235  * @tc.author: zhangqiquan
236  */
237 HWTEST_F(DistributedDBSingleVerDLPTest, DlpDelegateCRUDTest001, TestSize.Level1)
238 {
239     KvStoreDelegateManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
240     KvStoreNbDelegate *delegatePtr1 = nullptr;
241     EXPECT_EQ(OpenDelegate("/dlp1", delegatePtr1, mgr1), OK);
242     ASSERT_NE(delegatePtr1, nullptr);
243 
244     Key key1 = {'k', '1'};
245     Value value1 = {'v', '1'};
246     delegatePtr1->Put(key1, value1);
247 
248     Value value;
249     EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
250     EXPECT_EQ(value1, value);
251 
252     Value value2 = {'v', '2'};
253     delegatePtr1->Put(key1, value2);
254     EXPECT_EQ(delegatePtr1->Get(key1, value), OK);
255     EXPECT_EQ(value2, value);
256 
257     EXPECT_EQ(delegatePtr1->Delete(key1), OK);
258     EXPECT_EQ(delegatePtr1->Get(key1, value), NOT_FOUND);
259 
260     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
261 }
262 
263 /**
264  * @tc.name: SandboxDelegateSync001
265  * @tc.desc: Test dlp delegate sync function.
266  * @tc.type: FUNC
267  * @tc.require: SR000H0JSC
268  * @tc.author: zhangqiquan
269  */
270 HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync001, TestSize.Level1)
271 {
272     KvStoreDelegateManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
__anon80cb88940302(const PermissionCheckParam &param, uint8_t flag) 273     RuntimeConfig::SetPermissionCheckCallback([](const PermissionCheckParam &param, uint8_t flag) {
274         if ((flag & PermissionCheckFlag::CHECK_FLAG_RECEIVE) != 0) {
275             bool res = false;
276             if (param.extraConditions.find(KEY_INSTANCE_ID) != param.extraConditions.end()) {
277                 res = param.extraConditions.at(KEY_INSTANCE_ID) == std::to_string(INSTANCE_ID_1);
278             }
279             return res;
280         }
281         if (param.userId != USER_ID || param.appId != APP_ID || param.storeId != STORE_ID_1 ||
282             (param.instanceId != INSTANCE_ID_1 && param.instanceId != 0)) {
283             return false;
284         }
285         return true;
286     });
__anon80cb88940402(const PermissionConditionParam &param) 287     RuntimeConfig::SetPermissionConditionCallback([](const PermissionConditionParam &param) {
288         std::map<std::string, std::string> res;
289         res.emplace(KEY_INSTANCE_ID, std::to_string(INSTANCE_ID_1));
290         return res;
291     });
292 
293     KvStoreNbDelegate *delegatePtr1 = nullptr;
294     EXPECT_EQ(OpenDelegate("/dlp1", delegatePtr1, mgr1), OK);
295     ASSERT_NE(delegatePtr1, nullptr);
296 
297     Key key1 = {'k', '1'};
298     Value value1 = {'v', '1'};
299     delegatePtr1->Put(key1, value1);
300 
301     std::map<std::string, DBStatus> result;
302     DBStatus status = g_tool.SyncTest(delegatePtr1, { DEVICE_B }, SYNC_MODE_PUSH_ONLY, result);
303     EXPECT_TRUE(status == OK);
304     EXPECT_EQ(result[DEVICE_B], OK);
305 
306     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
307 }
308 
309 /**
310  * @tc.name: SandboxDelegateSync002
311  * @tc.desc: Test dlp delegate sync active if callback return true.
312  * @tc.type: FUNC
313  * @tc.require: SR000H0JSC
314  * @tc.author: zhangqiquan
315  */
316 HWTEST_F(DistributedDBSingleVerDLPTest, SandboxDelegateSync002, TestSize.Level1)
317 {
318     KvStoreDelegateManager mgr1(APP_ID, USER_ID, INSTANCE_ID_1);
__anon80cb88940502(const ActivationCheckParam &param) 319     RuntimeConfig::SetSyncActivationCheckCallback([](const ActivationCheckParam &param) {
320         if (param.userId == USER_ID && param.appId == APP_ID && param.storeId == STORE_ID_1 &&
321             param.instanceId == INSTANCE_ID_1) {
322             return true;
323         }
324         return false;
325     });
326 
327     KvStoreNbDelegate *delegatePtr1 = nullptr;
328     EXPECT_EQ(OpenDelegate("/dlp1", delegatePtr1, mgr1, true), OK);
329     ASSERT_NE(delegatePtr1, nullptr);
330 
331     std::map<std::string, DBStatus> result;
332     DBStatus status = g_tool.SyncTest(delegatePtr1, { DEVICE_B }, SYNC_MODE_PUSH_ONLY, result);
333     EXPECT_EQ(status, OK);
334     EXPECT_EQ(result[DEVICE_B], OK);
335 
336     CloseDelegate(delegatePtr1, mgr1, STORE_ID_1);
337 }