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 #include <gtest/gtest.h>
16
17 #include "distributeddb_nb_test_tools.h"
18 #include "process_communicator_test_stub.h"
19
20 using namespace testing;
21 #if defined TESTCASES_USING_GTEST_EXT
22 using namespace testing::ext;
23 #endif
24 using namespace std;
25 using namespace DistributedDB;
26 using namespace DistributedDBDataGenerator;
27
28 namespace DistributedbNbDbDamage {
29 KvStoreDelegateManager *g_manager = nullptr;
30
31 class DistributedbNbDbDamageTest : public testing::Test {
32 public:
33 static void SetUpTestCase(void);
34 static void TearDownTestCase(void);
35 void SetUp();
36 void TearDown();
37 };
38
SetUpTestCase(void)39 void DistributedbNbDbDamageTest::SetUpTestCase(void)
40 {
41 }
42
TearDownTestCase(void)43 void DistributedbNbDbDamageTest::TearDownTestCase(void)
44 {
45 }
46
SetUp(void)47 void DistributedbNbDbDamageTest::SetUp(void)
48 {
49 RemoveDir(DistributedDBConstant::NB_DIRECTOR);
50 UnitTest *test = UnitTest::GetInstance();
51 ASSERT_NE(test, nullptr);
52 const TestInfo *testinfo = test->current_test_info();
53 ASSERT_NE(testinfo, nullptr);
54 string testCaseName = string(testinfo->name());
55 MST_LOG("[SetUp] test case %s is start to run", testCaseName.c_str());
56 }
57
TearDown(void)58 void DistributedbNbDbDamageTest::TearDown(void)
59 {
60 }
61
62 /*
63 * @tc.name: DbDamageRecover 001
64 * @tc.desc: Verify that set isNeedIntegrityCheck and isNeedRmCorruptedDb when open db, if open failed the callback will
65 * be triggered when has register corruption callback.
66 * @tc.type: FUNC
67 * @tc.require: SR000D4878
68 * @tc.author: fengxiaoyun
69 */
70 #ifdef NB_DBDAMAGE
71 HWTEST_F(DistributedbNbDbDamageTest, DbDamageRecover001, TestSize.Level1)
72 {
73 Option option = g_option;
74 KvStoreNbDelegate *delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, option);
75 ASSERT_NE(g_manager, nullptr);
76 ASSERT_NE(delegate, nullptr);
77 EXPECT_EQ(g_manager->CloseKvStore(delegate), OK);
78 delegate = nullptr;
79
80 /**
81 * @tc.steps: step1. device A call SetKvStoreCorruptionHandler and make db file corrupted.
82 * @tc.expected: step1. operate successfully.
83 */
84 KvStoreNbCorruptInfo corruptInfo;
85 bool isCalled = false;
86 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBack, &corruptInfo,
87 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(isCalled));
88 g_manager->SetKvStoreCorruptionHandler(notifier);
89 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
90 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
91
92 /**
93 * @tc.steps: step2. set isNeedIntegrityCheck = true, isNeedRmCorruptedDb = false when open db and check the
94 * corruption callback is whether triggered or not.
95 * @tc.expected: step2. open db failed and the callback is triggered.
96 */
97 option.isNeedIntegrityCheck = true;
98 option.isNeedRmCorruptedDb = false;
99 DBStatus status;
100 KvStoreDelegateManager *manager = nullptr;
101 EXPECT_EQ(DistributedDBNbTestTools::GetNbDelegateStatus(manager, status, g_dbParameter1, option), nullptr);
102 EXPECT_EQ(status, INVALID_PASSWD_OR_CORRUPTED_DB);
103 EXPECT_TRUE(isCalled);
104
105 /**
106 * @tc.steps: step3. set isNeedIntegrityCheck = true, isNeedRmCorruptedDb = true when open db and check the
107 * corruption callback is whether triggered or not.
108 * @tc.expected: step3. open db success and the callback isn't triggered.
109 */
110 option.isNeedRmCorruptedDb = true;
111 isCalled = false;
112 delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, option);
113 ASSERT_TRUE(g_manager != nullptr && delegate != nullptr);
114 EXPECT_FALSE(isCalled);
115 g_manager->SetKvStoreCorruptionHandler(nullptr);
116 EXPECT_TRUE(EndCaseDeleteDB(g_manager, delegate, STORE_ID_1, option.isMemoryDb));
117 }
118
119 /*
120 * @tc.name: DbDamageRecover 002
121 * @tc.desc: Verify that set isNeedIntegrityCheck and isNeedRmCorruptedDb when open db, if open successfully, the data
122 * insert before db damaged is lost and the db can CRUD normally.
123 * @tc.type: FUNC
124 * @tc.require: SR000D4878
125 * @tc.author: fengxiaoyun
126 */
127 HWTEST_F(DistributedbNbDbDamageTest, DbDamageRecover002, TestSize.Level1)
128 {
129 Option option = g_option;
130 /**
131 * @tc.steps: step1. device A put (k1,v1), close db and call SetKvStoreCorruptionHandler and make db file corrupted.
132 * @tc.expected: step1. operate successfully.
133 */
134 KvStoreNbDelegate *delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, option);
135 ASSERT_NE(g_manager, nullptr);
136 ASSERT_NE(delegate, nullptr);
137 EXPECT_EQ(DistributedDBNbTestTools::Put(*delegate, KEY_1, VALUE_1), OK);
138 EXPECT_EQ(g_manager->CloseKvStore(delegate), OK);
139 delegate = nullptr;
140 KvStoreNbCorruptInfo corruptInfo;
141 bool isCalled = false;
142 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBack, &corruptInfo,
143 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(isCalled));
144 g_manager->SetKvStoreCorruptionHandler(notifier);
145 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
146 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
147
148 /**
149 * @tc.steps: step2. set isNeedIntegrityCheck = false, isNeedRmCorruptedDb = true when open db and check the
150 * corruption callback is whether triggered or not.
151 * @tc.expected: step2. open db success and the callback isn't triggered.
152 */
153 option.isNeedIntegrityCheck = false;
154 option.isNeedRmCorruptedDb = true;
155 delegate = DistributedDBNbTestTools::GetNbDelegateSuccess(g_manager, g_dbParameter1, option);
156 ASSERT_TRUE(g_manager != nullptr && delegate != nullptr);
157 EXPECT_FALSE(isCalled);
158
159 /**
160 * @tc.steps: step4. Get(k1), put(k1,v1)(k2,v2), delete(k1), put(k2,v3), Get(k1)(k2).
161 * @tc.expected: step4. Get(k1)=null, put and delete successfully, Get(k1)=v1, Get(k2)=v3.
162 */
163 EXPECT_TRUE(DistributedDBNbTestTools::CheckNbRecord(delegate, KEY_1, VALUE_EMPTY));
164 EXPECT_EQ(DistributedDBNbTestTools::Put(*delegate, KEY_1, VALUE_1), OK);
165 EXPECT_EQ(DistributedDBNbTestTools::Put(*delegate, KEY_2, VALUE_2), OK);
166 EXPECT_EQ(DistributedDBNbTestTools::Delete(*delegate, KEY_2), OK);
167 EXPECT_EQ(DistributedDBNbTestTools::Put(*delegate, KEY_1, VALUE_2), OK);
168 EXPECT_TRUE(DistributedDBNbTestTools::CheckNbRecord(delegate, KEY_1, VALUE_2));
169 EXPECT_TRUE(DistributedDBNbTestTools::CheckNbRecord(delegate, KEY_2, VALUE_EMPTY));
170 g_manager->SetKvStoreCorruptionHandler(nullptr);
171 EXPECT_TRUE(EndCaseDeleteDB(g_manager, delegate, STORE_ID_1, option.isMemoryDb));
172 }
173 #endif
174 /*
175 * @tc.name: DbDamageRecover 003
176 * @tc.desc: Verify that the db is damaged after db is opened, open db again won't trigger damage recover even set
177 * isNeedIntegrityCheck and isNeedRmCorruptedDb.
178 * @tc.type: FUNC
179 * @tc.require: SR000D4878
180 * @tc.author: fengxiaoyun
181 */
182 HWTEST_F(DistributedbNbDbDamageTest, DbDamageRecover003, TestSize.Level1)
183 {
184 Option option = g_option;
185 /**
186 * @tc.steps: step1. device A open delegate1 and don't close, call SetKvStoreCorruptionHandler and make db file
187 * corrupted.
188 * @tc.expected: step1. operate successfully.
189 */
190 KvStoreDelegateManager *manager1 = nullptr;
191 KvStoreNbDelegate *delegate1 = DistributedDBNbTestTools::GetNbDelegateSuccess(manager1, g_dbParameter1, option);
192 ASSERT_NE(manager1, nullptr);
193 ASSERT_NE(delegate1, nullptr);
194
195 KvStoreNbCorruptInfo corruptInfo;
196 bool isCalled = false;
197 auto notifier = bind(&KvStoreNbCorruptInfo::CorruptCallBack, &corruptInfo,
198 placeholders::_1, placeholders::_2, placeholders::_3, std::ref(isCalled));
199 g_manager->SetKvStoreCorruptionHandler(notifier);
200 std::string dbFliePath = DistributedDBNbTestTools::GetKvNbStoreDirectory(g_dbParameter1);
201 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath));
202 EXPECT_TRUE(DistributedDBNbTestTools::ModifyDatabaseFile(dbFliePath + "-wal"));
203
204 /**
205 * @tc.steps: step2. set isNeedIntegrityCheck = true, isNeedRmCorruptedDb = false when open db and check the
206 * corruption callback is whether triggered or not.
207 * @tc.expected: step2. open db successfully and the callback isn't triggered.
208 */
209 option.isNeedIntegrityCheck = true;
210 option.isNeedRmCorruptedDb = false;
211 KvStoreDelegateManager *manager2 = nullptr;
212 KvStoreNbDelegate *delegate2 = DistributedDBNbTestTools::GetNbDelegateSuccess(manager2, g_dbParameter1, option);
213 ASSERT_NE(manager2, nullptr);
214 ASSERT_NE(delegate2, nullptr);
215 EXPECT_FALSE(isCalled);
216
217 /**
218 * @tc.steps: step3. close delegate1 and do step 2 again.
219 * @tc.expected: step3. open db success and the callback isn't triggered.
220 */
221 EXPECT_TRUE(DistributedTestTools::CloseAndRelease(manager1, delegate1));
222 delegate1 = DistributedDBNbTestTools::GetNbDelegateSuccess(manager1, g_dbParameter1, option);
223 ASSERT_NE(manager1, nullptr);
224 ASSERT_NE(delegate1, nullptr);
225 EXPECT_FALSE(isCalled);
226
227 /**
228 * @tc.steps: step4. device A put(k1,v1) and check the corruption callback.
229 * @tc.expected: step4. put failed and return INVALID_PASSWD_OR_CORRUPTED_DB, the callback is triggered.
230 */
231 EXPECT_EQ(DistributedDBNbTestTools::Put(*delegate1, KEY_1, VALUE_1), INVALID_PASSWD_OR_CORRUPTED_DB);
232 std::this_thread::sleep_for(std::chrono::seconds(UNIQUE_SECOND)); // wait for callback complete for 1 second.
233 EXPECT_TRUE(isCalled);
234
235 /**
236 * @tc.steps: step5. close delegate1,delegate2, then open db with isNeedIntegrityCheck = true,
237 * isNeedRmCorruptedDb = false, and check the corruption callback.
238 * @tc.expected: step5. open failed and return INVALID_PASSWD_OR_CORRUPTED_DB, the callback is triggered.
239 */
240 EXPECT_TRUE(DistributedTestTools::CloseAndRelease(manager1, delegate1));
241 EXPECT_TRUE(DistributedTestTools::CloseAndRelease(manager2, delegate2));
242 DBStatus status;
243 isCalled = false;
244 EXPECT_EQ(DistributedDBNbTestTools::GetNbDelegateStatus(manager1, status, g_dbParameter1, option), nullptr);
245 EXPECT_EQ(status, INVALID_PASSWD_OR_CORRUPTED_DB);
246 EXPECT_TRUE(isCalled);
247 KvStoreDelegateManager Manager(APP_ID_1, USER_ID_1);
248 Manager.SetKvStoreCorruptionHandler(nullptr);
249 RemoveDir(DistributedDBConstant::NB_DIRECTOR);
250 }
251 } // end of namespace DistributedbNbDbDamageTest