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 class AutoSyncTimerTest : public testing::Test {
29 public:
30 class KVDBServiceMock : public KVDBServiceClient {
31 private:
32 static KVDBServiceMock *instance_;
33
34 public:
GetInstance()35 static KVDBServiceMock *GetInstance()
36 {
37 KVDBServiceClient::GetInstance();
38 return instance_;
39 }
KVDBServiceMock(const sptr<IRemoteObject> & object)40 explicit KVDBServiceMock(const sptr<IRemoteObject> &object) : KVDBServiceClient(object)
41 {
42 startTime = 0;
43 endTime = 0;
44 instance_ = this;
45 }
~KVDBServiceMock()46 virtual ~KVDBServiceMock()
47 {
48 instance_ = nullptr;
49 }
50
Sync(const AppId & appId,const StoreId & storeId,const SyncInfo & syncInfo)51 Status Sync(const AppId &appId, const StoreId &storeId, const SyncInfo &syncInfo) override
52 {
53 endTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
54 values_[appId.appId].insert(storeId.storeId);
55 {
56 std::lock_guard<decltype(mutex_)> guard(mutex_);
57 ++callCount;
58 value_.SetValue(callCount);
59 }
60 return KVDBServiceClient::Sync(appId, storeId, syncInfo);
61 }
62
GetCallCount(uint32_t value)63 uint32_t GetCallCount(uint32_t value)
64 {
65 int retry = 0;
66 uint32_t callTimes = 0;
67 while (retry < value) {
68 callTimes = value_.GetValue();
69 if (callTimes >= value) {
70 break;
71 }
72 std::lock_guard<decltype(mutex_)> guard(mutex_);
73 callTimes = value_.GetValue();
74 if (callTimes >= value) {
75 break;
76 }
77 value_.Clear(callTimes);
78 retry++;
79 }
80 return callTimes;
81 }
82
ResetToZero()83 void ResetToZero()
84 {
85 std::lock_guard<decltype(mutex_)> guard(mutex_);
86 callCount = 0;
87 value_.Clear(0);
88 }
89
90 uint64_t startTime = 0;
91 uint64_t endTime = 0;
92 uint32_t callCount = 0;
93 std::map<std::string, std::set<std::string>> values_;
94 BlockData<uint32_t> value_{ 1, 0 };
95 std::mutex mutex_;
96 };
97 class TestSyncCallback : public KvStoreSyncCallback {
98 public:
SyncCompleted(const std::map<std::string,Status> & results)99 void SyncCompleted(const std::map<std::string, Status> &results) override
100 {
101 ASSERT_TRUE(true);
102 }
103 };
104 static void SetUpTestCase(void);
105 static void TearDownTestCase(void);
106 void SetUp();
107 void TearDown();
108
109 protected:
110 static std::shared_ptr<SingleKvStore> kvStore_;
111 static BrokerDelegator<KVDBServiceMock> delegator_;
112 };
113 BrokerDelegator<AutoSyncTimerTest::KVDBServiceMock> AutoSyncTimerTest::delegator_;
114 AutoSyncTimerTest::KVDBServiceMock *AutoSyncTimerTest::KVDBServiceMock::instance_ = nullptr;
SetUpTestCase(void)115 void AutoSyncTimerTest::SetUpTestCase(void)
116 {
117 }
118
TearDownTestCase(void)119 void AutoSyncTimerTest::TearDownTestCase(void)
120 {
121 }
122
SetUp(void)123 void AutoSyncTimerTest::SetUp(void)
124 {
125 }
126
TearDown(void)127 void AutoSyncTimerTest::TearDown(void)
128 {
129 sleep(10);
130 }
131
132 /**
133 * @tc.name: SingleWrite
134 * @tc.desc: get the store id of the kv store
135 * @tc.type: FUNC
136 * @tc.require: I4XVQQ
137 * @tc.author: Yang Qing
138 */
139 HWTEST_F(AutoSyncTimerTest, SingleWrite, TestSize.Level0)
140 {
141 auto *instance = KVDBServiceMock::GetInstance();
142 ASSERT_NE(instance, nullptr);
143 instance->ResetToZero();
144 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
145 instance->endTime = 0;
146 instance->values_.clear();
147 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", { { "ut_test_store" } });
148 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
149 auto it = instance->values_.find("ut_test");
150 ASSERT_NE(it, instance->values_.end());
151 ASSERT_EQ(it->second.count("ut_test_store"), 1);
152 ASSERT_LT(instance->endTime - instance->startTime, 100);
153 }
154
155 /**
156 * @tc.name: MultiWrite
157 * @tc.desc: get the store id of the kv store
158 * @tc.type: FUNC
159 * @tc.require: I4XVQQ
160 * @tc.author: Yang Qing
161 */
162 HWTEST_F(AutoSyncTimerTest, MultiWrite, TestSize.Level1)
163 {
164 auto *instance = KVDBServiceMock::GetInstance();
165 ASSERT_NE(instance, nullptr);
166 instance->ResetToZero();
167 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
168 instance->endTime = 0;
169 instance->values_.clear();
170 std::atomic_bool finished = false;
__anonc3743fd00102null171 std::thread thread([&finished] {
172 while (!finished.load()) {
173 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", { { "ut_test_store" } });
174 usleep(40);
175 }
176 });
177 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
178 ASSERT_GE(instance->endTime - instance->startTime, 200);
179 ASSERT_LT(instance->endTime - instance->startTime, 250);
180 finished.store(true);
181 thread.join();
182 auto it = instance->values_.find("ut_test");
183 ASSERT_NE(it, instance->values_.end());
184 ASSERT_EQ(it->second.count("ut_test_store"), 1);
185 }
186
187 /**
188 * @tc.name: SingleWriteOvertenKVStores
189 * @tc.desc: single write over ten kv stores
190 * @tc.type: FUNC
191 * @tc.require: I4XVQQ
192 * @tc.author: Yang Qing
193 */
194 HWTEST_F(AutoSyncTimerTest, SingleWriteOvertenKVStores, TestSize.Level1)
195 {
196 auto *instance = KVDBServiceMock::GetInstance();
197 ASSERT_NE(instance, nullptr);
198 instance->ResetToZero();
199 instance->startTime = time_point_cast<milliseconds>(system_clock::now()).time_since_epoch().count();
200 instance->endTime = 0;
201 instance->values_.clear();
202 AutoSyncTimer::GetInstance().DoAutoSync("ut_test", {
203 { "ut_test_store0" },
204 { "ut_test_store1" },
205 { "ut_test_store2" },
206 { "ut_test_store3" },
207 { "ut_test_store4" },
208 { "ut_test_store5" },
209 { "ut_test_store6" },
210 { "ut_test_store7" },
211 { "ut_test_store8" },
212 { "ut_test_store9" },
213 { "ut_test_store10" },
214 });
215 EXPECT_EQ(static_cast<int>(instance->GetCallCount(1)), 1);
216 ASSERT_LT(instance->endTime - instance->startTime, 100);
217 EXPECT_EQ(static_cast<int>(instance->GetCallCount(11)), 11);
218 auto it = instance->values_.find("ut_test");
219 ASSERT_NE(it, instance->values_.end());
220 ASSERT_EQ(it->second.count("ut_test_store0"), 1);
221 ASSERT_EQ(it->second.count("ut_test_store1"), 1);
222 ASSERT_EQ(it->second.count("ut_test_store2"), 1);
223 ASSERT_EQ(it->second.count("ut_test_store3"), 1);
224 ASSERT_EQ(it->second.count("ut_test_store4"), 1);
225 ASSERT_EQ(it->second.count("ut_test_store5"), 1);
226 ASSERT_EQ(it->second.count("ut_test_store6"), 1);
227 ASSERT_EQ(it->second.count("ut_test_store7"), 1);
228 ASSERT_EQ(it->second.count("ut_test_store8"), 1);
229 ASSERT_EQ(it->second.count("ut_test_store9"), 1);
230 ASSERT_EQ(it->second.count("ut_test_store10"), 1);
231 }