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 "auto_sync_timer.h"
17
18 #include <gtest/gtest.h>
19
20 #include "block_data.h"
21 #include "kvdb_service_client.h"
22 #include "store_manager.h"
23
24 using namespace OHOS;
25 using namespace testing::ext;
26 using namespace OHOS::DistributedKv;
27 using namespace std::chrono;
28 namespace OHOS::Test {
29 class AutoSyncTimerTest : public testing::Test {
30 public:
31 class KVDBServiceMock : public KVDBServiceClient {
32 private:
33 static KVDBServiceMock *instance_;
34
35 public:
GetInstance()36 static KVDBServiceMock *GetInstance()
37 {
38 KVDBServiceClient::GetInstance();
39 return instance_;
40 }
KVDBServiceMock(const sptr<IRemoteObject> & object)41 explicit KVDBServiceMock(const sptr<IRemoteObject> &object) : KVDBServiceClient(object)
42 {
43 instance_ = this;
44 }
~KVDBServiceMock()45 virtual ~KVDBServiceMock()
46 {
47 instance_ = nullptr;
48 }
49
Sync(const AppId & appId,const StoreId & storeId,const SyncInfo & syncInfo)50 Status Sync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) override
51 {
52 endTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
53 values_[appId.appId].insert(storeId.storeId);
54 {
55 std::lock_guard<decltype(mutex_)> guard(mutex_);
56 ++callCount;
57 value_.SetValue(callCount);
58 }
59 return KVDBServiceClient::Sync(appId, storeId, syncInfo);
60 }
61
GetCallCount(uint32_t value)62 uint32_t GetCallCount(uint32_t value)
63 {
64 uint32_t retry = 0;
65 uint32_t callTimes = 0;
66 while (retry < value) {
67 callTimes = value_.GetValue();
68 if (callTimes >= value) {
69 break;
70 }
71 std::lock_guard<decltype(mutex_)> guard(mutex_);
72 callTimes = value_.GetValue();
73 if (callTimes >= value) {
74 break;
75 }
76 value_.Clear(callTimes);
77 retry++;
78 }
79 return callTimes;
80 }
81
ResetToZero()82 void ResetToZero()
83 {
84 std::lock_guard<decltype(mutex_)> guard(mutex_);
85 callCount = 0;
86 value_.Clear(0);
87 }
88
89 uint64_t startTime = 0;
90 uint64_t endTime = 0;
91 uint32_t callCount = 0;
92 std::map<std::string, std::set<std::string>> values_;
93 BlockData<uint32_t> value_{ 1, 0 };
94 std::mutex mutex_;
95 };
96 class TestSyncCallback : public KvStoreSyncCallback {
97 public:
SyncCompleted(const std::map<std::string,Status> & results)98 void SyncCompleted(const std::map<std::string, Status> &results) override
99 {
100 ASSERT_TRUE(true);
101 }
102 };
103 static void SetUpTestCase(void);
104 static void TearDownTestCase(void);
105 void SetUp();
106 void TearDown();
107
108 protected:
109 static BrokerDelegator<KVDBServiceMock> delegator_;
110 static constexpr int SLEEP_TIME = 10;
111 };
112 BrokerDelegator<AutoSyncTimerTest::KVDBServiceMock> AutoSyncTimerTest::delegator_;
113 AutoSyncTimerTest::KVDBServiceMock *AutoSyncTimerTest::KVDBServiceMock::instance_ = nullptr;
SetUpTestCase(void)114 void AutoSyncTimerTest::SetUpTestCase(void)
115 {
116 }
117
TearDownTestCase(void)118 void AutoSyncTimerTest::TearDownTestCase(void)
119 {
120 }
121
SetUp(void)122 void AutoSyncTimerTest::SetUp(void)
123 {
124 }
125
TearDown(void)126 void AutoSyncTimerTest::TearDown(void)
127 {
128 sleep(SLEEP_TIME); // make sure the case has executed completely
129 }
130
131 /**
132 * @tc.name: SingleWrite
133 * @tc.desc: single write
134 * @tc.type: FUNC
135 * @tc.require: I4XVQQ
136 * @tc.author: Yang Qing
137 */
138 HWTEST_F(AutoSyncTimerTest, SingleWrite, TestSize.Level0)
139 {
140 auto *instance = KVDBServiceMock::GetInstance();
141 ASSERT_NE(instance, nullptr);
142 instance->ResetToZero();
143 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
144 instance->endTime = 0;
145 instance->values_.clear();
146 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", { { "ut_test_store" } });
147 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
148 auto it = instance->values_.find("ut_test");
149 ASSERT_NE(it, instance->values_.end());
150 ASSERT_EQ(it->second.count("ut_test_store"), 1);
151 ASSERT_LT(instance->endTime - instance->startTime, 100);
152 }
153
154 /**
155 * @tc.name: MultiWriteBelowDelayTime
156 * @tc.desc: write every 40 milliseconds
157 * @tc.type: FUNC
158 * @tc.require: I4XVQQ
159 * @tc.author: Yang Qing
160 */
161 HWTEST_F(AutoSyncTimerTest, MultiWriteBelowDelayTime, TestSize.Level1)
162 {
163 auto *instance = KVDBServiceMock::GetInstance();
164 ASSERT_NE(instance, nullptr);
165 instance->ResetToZero();
166 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
167 instance->endTime = 0;
168 instance->values_.clear();
169 std::atomic_bool finished = false;
__anon09de766e0102null170 std::thread thread([&finished] {
171 while (!finished.load()) {
172 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", { { "ut_test_store" } });
173 std::this_thread::sleep_for(std::chrono::milliseconds(40));
174 }
175 });
176 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
177 ASSERT_GE(instance->endTime - instance->startTime, 200);
178 ASSERT_LT(instance->endTime - instance->startTime, 250);
179 finished.store(true);
180 thread.join();
181 auto it = instance->values_.find("ut_test");
182 ASSERT_NE(it, instance->values_.end());
183 ASSERT_EQ(it->second.count("ut_test_store"), 1);
184 }
185
186 /**
187 * @tc.name: MultiWriteOverDelayTime
188 * @tc.desc: write every 150 milliseconds
189 * @tc.type: FUNC
190 * @tc.require: I4XVQQ
191 * @tc.author: Yang Qing
192 */
193 HWTEST_F(AutoSyncTimerTest, MultiWriteOverDelayTime, TestSize.Level1)
194 {
195 auto *instance = KVDBServiceMock::GetInstance();
196 ASSERT_NE(instance, nullptr);
197 instance->ResetToZero();
198 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
199 instance->endTime = 0;
200 instance->values_.clear();
201 std::atomic_bool finished = false;
__anon09de766e0202null202 std::thread thread([&finished] {
203 while (!finished.load()) {
204 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", { { "ut_test_store" } });
205 std::this_thread::sleep_for(std::chrono::milliseconds(150));
206 }
207 });
208 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
209 ASSERT_LT(instance->endTime - instance->startTime, 100);
210 finished.store(true);
211 thread.join();
212 auto it = instance->values_.find("ut_test");
213 ASSERT_NE(it, instance->values_.end());
214 ASSERT_EQ(it->second.count("ut_test_store"), 1);
215 }
216
217 /**
218 * @tc.name: MultiWriteOverForceTime
219 * @tc.desc: write every 400 milliseconds
220 * @tc.type: FUNC
221 * @tc.require: I4XVQQ
222 * @tc.author: Yang Qing
223 */
224 HWTEST_F(AutoSyncTimerTest, MultiWriteOverForceTime, TestSize.Level1)
225 {
226 auto *instance = KVDBServiceMock::GetInstance();
227 ASSERT_NE(instance, nullptr);
228 instance->ResetToZero();
229 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
230 instance->endTime = 0;
231 instance->values_.clear();
232 std::atomic_bool finished = false;
__anon09de766e0302null233 std::thread thread([&finished] {
234 while (!finished.load()) {
235 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", { { "ut_test_store" } });
236 std::this_thread::sleep_for(std::chrono::milliseconds(400));
237 }
238 });
239 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
240 ASSERT_LT(instance->endTime - instance->startTime, 100);
241 finished.store(true);
242 thread.join();
243 auto it = instance->values_.find("ut_test");
244 ASSERT_NE(it, instance->values_.end());
245 ASSERT_EQ(it->second.count("ut_test_store"), 1);
246 }
247
248 /**
249 * @tc.name: SingleWriteOvertenKVStores
250 * @tc.desc: single write over ten kv stores
251 * @tc.type: FUNC
252 * @tc.require: I4XVQQ
253 * @tc.author: Yang Qing
254 */
255 HWTEST_F(AutoSyncTimerTest, SingleWriteOvertenKVStores, TestSize.Level1)
256 {
257 auto *instance = KVDBServiceMock::GetInstance();
258 ASSERT_NE(instance, nullptr);
259 instance->ResetToZero();
260 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
261 instance->endTime = 0;
262 instance->values_.clear();
263 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", {
264 { "ut_test_store0" },
265 { "ut_test_store1" },
266 { "ut_test_store2" },
267 { "ut_test_store3" },
268 { "ut_test_store4" },
269 { "ut_test_store5" },
270 { "ut_test_store6" },
271 { "ut_test_store7" },
272 { "ut_test_store8" },
273 { "ut_test_store9" },
274 { "ut_test_store10" },
275 });
276 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
277 ASSERT_LT(instance->endTime - instance->startTime, 100);
278 EXPECT_EQ(static_cast<int>(instance->GetCallCount(11)), 11);
279 auto it = instance->values_.find("ut_test");
280 ASSERT_NE(it, instance->values_.end());
281 ASSERT_EQ(it->second.count("ut_test_store0"), 1);
282 ASSERT_EQ(it->second.count("ut_test_store1"), 1);
283 ASSERT_EQ(it->second.count("ut_test_store2"), 1);
284 ASSERT_EQ(it->second.count("ut_test_store3"), 1);
285 ASSERT_EQ(it->second.count("ut_test_store4"), 1);
286 ASSERT_EQ(it->second.count("ut_test_store5"), 1);
287 ASSERT_EQ(it->second.count("ut_test_store6"), 1);
288 ASSERT_EQ(it->second.count("ut_test_store7"), 1);
289 ASSERT_EQ(it->second.count("ut_test_store8"), 1);
290 ASSERT_EQ(it->second.count("ut_test_store9"), 1);
291 ASSERT_EQ(it->second.count("ut_test_store10"), 1);
292 }
293
294 /**
295 * @tc.name: MultiWriteOvertenKVStores
296 * @tc.desc: mulity wirte
297 * @tc.type: FUNC
298 * @tc.require: I4XVQQ
299 * @tc.author: YangQing
300 */
301 HWTEST_F(AutoSyncTimerTest, MultiWriteOvertenKVStores, TestSize.Level1)
302 {
303 auto *instance = KVDBServiceMock::GetInstance();
304 ASSERT_NE(instance, nullptr);
305 instance->ResetToZero();
306 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
307 instance->endTime = 0;
308 instance->values_.clear();
309 std::atomic_bool finished = false;
__anon09de766e0402null310 std::thread thread([&finished] {
311 while (!finished.load()) {
312 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", {
313 { "ut_test_store0" },
314 { "ut_test_store1" },
315 { "ut_test_store2" },
316 { "ut_test_store3" },
317 { "ut_test_store4" },
318 { "ut_test_store5" },
319 { "ut_test_store6" },
320 { "ut_test_store7" },
321 { "ut_test_store8" },
322 { "ut_test_store9" },
323 { "ut_test_store10" },
324 });
325 usleep(40);
326 }
327 });
328 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
329 ASSERT_GE(instance->endTime - instance->startTime, 200);
330 ASSERT_LT(instance->endTime - instance->startTime, 250);
331 EXPECT_EQ(static_cast<int>(instance->GetCallCount(11)), 11);
332 auto it = instance->values_.find("ut_test");
333 ASSERT_EQ(it->second.count("ut_test_store0"), 1);
334 ASSERT_EQ(it->second.count("ut_test_store1"), 1);
335 ASSERT_EQ(it->second.count("ut_test_store2"), 1);
336 ASSERT_EQ(it->second.count("ut_test_store3"), 1);
337 ASSERT_EQ(it->second.count("ut_test_store4"), 1);
338 ASSERT_EQ(it->second.count("ut_test_store5"), 1);
339 ASSERT_EQ(it->second.count("ut_test_store6"), 1);
340 ASSERT_EQ(it->second.count("ut_test_store7"), 1);
341 ASSERT_EQ(it->second.count("ut_test_store8"), 1);
342 ASSERT_EQ(it->second.count("ut_test_store9"), 1);
343 ASSERT_EQ(it->second.count("ut_test_store10"), 1);
344 finished.store(true);
345 thread.join();
346 }
347
348 /**
349 * @tc.name: DoubleWrite
350 * @tc.desc: double wirte
351 * @tc.type: FUNC
352 * @tc.require: I4XVQQ
353 * @tc.author: YangQing
354 */
355 HWTEST_F(AutoSyncTimerTest, DoubleWrite, TestSize.Level1)
356 {
357 auto *instance = KVDBServiceMock::GetInstance();
358 ASSERT_NE(instance, nullptr);
359 instance->ResetToZero();
360 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
361 instance->endTime = 0;
362 instance->values_.clear();
363 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", {
364 { "ut_test_store0" },
365 { "ut_test_store1" },
366 { "ut_test_store2" },
367 { "ut_test_store3" },
368 { "ut_test_store4" },
369 { "ut_test_store5" },
370 { "ut_test_store6" },
371 { "ut_test_store7" },
372 { "ut_test_store8" },
373 { "ut_test_store9" },
374 { "ut_test_store10" },
375 });
376 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", {
377 { "ut_test_store-0" },
378 { "ut_test_store-1" },
379 { "ut_test_store-2" },
380 { "ut_test_store-3" },
381 { "ut_test_store-4" },
382 { "ut_test_store-5" },
383 { "ut_test_store-6" },
384 { "ut_test_store-7" },
385 { "ut_test_store-8" },
386 });
387 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
388 ASSERT_LT(instance->endTime - instance->startTime, 100);
389 EXPECT_EQ(static_cast<int>(instance->GetCallCount(20)), 20);
390 auto it = instance->values_.find("ut_test");
391 ASSERT_EQ(it->second.count("ut_test_store0"), 1);
392 ASSERT_EQ(it->second.count("ut_test_store1"), 1);
393 ASSERT_EQ(it->second.count("ut_test_store2"), 1);
394 ASSERT_EQ(it->second.count("ut_test_store3"), 1);
395 ASSERT_EQ(it->second.count("ut_test_store4"), 1);
396 ASSERT_EQ(it->second.count("ut_test_store5"), 1);
397 ASSERT_EQ(it->second.count("ut_test_store6"), 1);
398 ASSERT_EQ(it->second.count("ut_test_store7"), 1);
399 ASSERT_EQ(it->second.count("ut_test_store8"), 1);
400 ASSERT_EQ(it->second.count("ut_test_store9"), 1);
401 ASSERT_EQ(it->second.count("ut_test_store10"), 1);
402 ASSERT_EQ(it->second.count("ut_test_store-0"), 1);
403 ASSERT_EQ(it->second.count("ut_test_store-1"), 1);
404 ASSERT_EQ(it->second.count("ut_test_store-2"), 1);
405 ASSERT_EQ(it->second.count("ut_test_store-3"), 1);
406 ASSERT_EQ(it->second.count("ut_test_store-4"), 1);
407 ASSERT_EQ(it->second.count("ut_test_store-5"), 1);
408 ASSERT_EQ(it->second.count("ut_test_store-6"), 1);
409 ASSERT_EQ(it->second.count("ut_test_store-7"), 1);
410 ASSERT_EQ(it->second.count("ut_test_store-8"), 1);
411 }
412 } // namespace OHOS::Test