• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "safe_map.h"
16 
17 #include <array>
18 #include <future>
19 #include <gtest/gtest.h>
20 #include <iostream>
21 #include <thread>
22 
23 #include <iostream>
24 
25 #include <chrono> // std::chrono::seconds
26 #include <iostream> // std::cout
27 #include <thread> // std::thread, std::this_thread::sleep_for
28 
29 using namespace testing::ext;
30 using namespace OHOS;
31 using namespace std;
32 
33 class UtilsSafeMap : public testing::Test {
34 };
35 
36 /*
37  * @tc.name: testUtilsCopyAndAssign001
38  * @tc.desc: single thread test the normal feature insert and erase and EnsureInsert
39  */
40 HWTEST_F(UtilsSafeMap, testUtilsCopyAndAssign001, TestSize.Level0)
41 {
42     SafeMap<string, int> demoData;
43     // insert new
44     demoData.Insert("A", 1);
45     ASSERT_FALSE(demoData.IsEmpty());
46     ASSERT_EQ(demoData.Size(), 1);
47 
48     SafeMap<string, int> newdemo = demoData;
49     int tar = -1;
50     ASSERT_TRUE(newdemo.Find("A", tar));
51     ASSERT_EQ(1, tar);
52 
53     tar = -1;
54     SafeMap<string, int> newdemo2;
55     newdemo2 = demoData;
56     ASSERT_TRUE(newdemo2.Find("A", tar));
57     ASSERT_EQ(1, tar);
58 }
59 
60 /*
61  * @tc.name: testUtilsoperator001
62  * @tc.desc: SafeMap
63  */
64 HWTEST_F(UtilsSafeMap, testUtilsoperator001, TestSize.Level0)
65 {
66     SafeMap<string, int> demoData;
67     // insert new
68     demoData.Insert("A", 1);
69     ASSERT_FALSE(demoData.IsEmpty());
70     ASSERT_EQ(demoData.Size(), 1);
71     ASSERT_EQ(demoData["A"], 1);
72 
73     SafeMap<string, int> newdemo = demoData;
74     ASSERT_EQ(newdemo["A"], 1);
75 
76     int tar = -1;
77     newdemo["B"] = 6;
78     ASSERT_TRUE(newdemo.Find("B", tar));
79     ASSERT_EQ(6, tar);
80 
81     SafeMap<string, int> newdemo2;
82     newdemo2 = newdemo;
83     ASSERT_EQ(newdemo2["A"], 1);
84 }
85 
86 /*
87  * @tc.name: testUtilsNormalFeatureInsert001
88  * @tc.desc: SafeMap
89  */
90 HWTEST_F(UtilsSafeMap, testUtilsNormalFeatureInsert001, TestSize.Level0)
91 {
92     SafeMap<string, int> demoData;
93     ASSERT_TRUE(demoData.IsEmpty());
94     // insert new
95     demoData.Insert("A", 1);
96     ASSERT_FALSE(demoData.IsEmpty());
97     ASSERT_EQ(demoData.Size(), 1);
98 
99     // insert copy one should fail
100     ASSERT_FALSE(demoData.Insert("A", 2));
101     ASSERT_EQ(demoData.Size(), 1);
102 }
103 
104 /*
105  * @tc.name: testUtilsNormalFeatureEnsureInsert001
106  * @tc.desc: SafeMap
107  */
108 HWTEST_F(UtilsSafeMap, testUtilsNormalFeatureEnsureInsert001, TestSize.Level0)
109 {
110     SafeMap<string, int> demoData;
111     ASSERT_TRUE(demoData.IsEmpty());
112 
113     demoData.Insert("A", 1);
114     demoData.EnsureInsert("B", 2);
115 
116     ASSERT_FALSE(demoData.IsEmpty());
117     ASSERT_EQ(demoData.Size(), 2);
118     // insert copy one and new one
119     demoData.EnsureInsert("B", 5);
120     demoData.EnsureInsert("C", 6);
121 
122     ASSERT_EQ(demoData.Size(), 3);
123 }
124 
125 /*
126  * @tc.name: testUtilsNormalFeatureFind001
127  * @tc.desc: SafeMap
128  */
129 HWTEST_F(UtilsSafeMap, testUtilsNormalFeatureFind001, TestSize.Level0)
130 {
131     SafeMap<string, int> demoData;
132     ASSERT_TRUE(demoData.IsEmpty());
133 
134     demoData.Insert("A", 1);
135     demoData.Insert("B", 10000);
136     demoData.EnsureInsert("B", 2);
137     demoData.EnsureInsert("C", 6);
138 
139     ASSERT_FALSE(demoData.IsEmpty());
140     ASSERT_EQ(demoData.Size(), 3);
141 
142     int i = 0;
143     ASSERT_TRUE(demoData.Find("A", i));
144     ASSERT_EQ(i, 1);
145     ASSERT_TRUE(demoData.Find("B", i));
146     ASSERT_EQ(i, 2);
147 
148     ASSERT_TRUE(demoData.Find("C", i));
149     ASSERT_EQ(i, 6);
150 }
151 
152 /*
153  * @tc.name: testUtilsNormalFeatureFindAndSet001
154  * @tc.desc: SafeMap
155  */
156 HWTEST_F(UtilsSafeMap, testUtilsNormalFeatureFindAndSet001, TestSize.Level0)
157 {
158     SafeMap<string, int> demoData;
159     ASSERT_TRUE(demoData.IsEmpty());
160 
161     demoData.Insert("A", 1);
162     demoData.EnsureInsert("B", 2);
163 
164     int oldvalue = 0;
165     int newvalue = 3;
166     ASSERT_TRUE(demoData.FindOldAndSetNew("A", oldvalue, newvalue));
167     // old value
168     ASSERT_EQ(oldvalue, 1);
169 
170     newvalue = 4;
171     ASSERT_TRUE(demoData.FindOldAndSetNew("B", oldvalue, newvalue));
172     // old value
173     ASSERT_EQ(oldvalue, 2);
174     int i = -1;
175     ASSERT_TRUE(demoData.Find("A", i));
176     // new value
177     ASSERT_EQ(i, 3);
178     ASSERT_TRUE(demoData.Find("B", i));
179     // new value
180     ASSERT_EQ(i, 4);
181 }
182 
183 /*
184  * @tc.name: testUtilsNormalFeatureEraseAndClear001
185  * @tc.desc: SafeMap
186  */
187 HWTEST_F(UtilsSafeMap, testUtilsNormalFeatureEraseAndClear001, TestSize.Level0)
188 {
189     SafeMap<string, int> demoData;
190     ASSERT_TRUE(demoData.IsEmpty());
191 
192     demoData.Insert("A", 1);
193     demoData.EnsureInsert("B", 2);
194 
195     ASSERT_EQ(demoData.Size(), 2);
196     demoData.Erase("A");
197     ASSERT_EQ(demoData.Size(), 1);
198 
199     demoData.Clear();
200     ASSERT_EQ(demoData.Size(), 0);
201 }
202 
203 /*
204  * @tc.name: testUtilsConcurrentWriteAndRead001
205  * @tc.desc: 100 threads test in writein to the same key of the map, while read at same time  and no throw
206  */
207 const int THREAD_NUM = 100;
208 HWTEST_F(UtilsSafeMap, testUtilsConcurrentWriteAndRead001, TestSize.Level0)
209 {
210     SafeMap<string, int> demoData;
211     std::thread threads[THREAD_NUM];
212     std::thread checkThread[THREAD_NUM];
213     ASSERT_NO_THROW({
214         auto lamfuncInsert = [](SafeMap<string, int>& data, const string& key,
__anoncf81f8e00102(SafeMap<string, int>& data, const string& key, const int& value, const std::chrono::system_clock::time_point& absTime) 215             const int& value, const std::chrono::system_clock::time_point& absTime) {
216             std::this_thread::sleep_until(absTime);
217             data.EnsureInsert(key, value);
218         };
219 
220         auto lamfuncCheck = [](SafeMap<string, int>& data, const string& key,
__anoncf81f8e00202(SafeMap<string, int>& data, const string& key, std::chrono::system_clock::time_point absTime) 221             std::chrono::system_clock::time_point absTime) {
222             std::this_thread::sleep_until(absTime);
223             thread_local int i = -1;
224             data.Find(key, i);
225         };
226 
227         using std::chrono::system_clock;
228 
229         std::time_t timeT = system_clock::to_time_t(system_clock::now());
230         timeT += 2;
231         string key("A");
232 
233         for (int i = 0; i < THREAD_NUM; ++i) {
234             threads[i] = std::thread(lamfuncInsert, std::ref(demoData), key, i, system_clock::from_time_t(timeT));
235             checkThread[i] = std::thread(lamfuncCheck, std::ref(demoData), key, system_clock::from_time_t(timeT));
236         }
237 
238         std::this_thread::sleep_for(std::chrono::seconds(3));
239         for (auto& t : threads) {
240             t.join();
241         }
242 
243         for (auto& t : checkThread) {
244             t.join();
245         }
246     });
247 }
248 
249 /*
250  * @tc.name: testUtilsConcurrentWriteAndFind001
251  * @tc.desc: 100 threads test in writein to the corresponding key of the map,
252  * while read at same time  and check the results
253  */
254 HWTEST_F(UtilsSafeMap, testUtilsConcurrentWriteAndFind001, TestSize.Level0)
255 {
256     SafeMap<string, int> demoData;
257     std::thread threads[THREAD_NUM];
258     std::vector<std::future<int>> vcfi;
259 
260     ASSERT_NO_THROW({
261         auto lamfuncInsert = [](SafeMap<string, int>& data, const string& key,
__anoncf81f8e00302(SafeMap<string, int>& data, const string& key, const int& value, const std::chrono::system_clock::time_point& absTime) 262             const int& value, const std::chrono::system_clock::time_point& absTime) {
263             std::this_thread::sleep_until(absTime);
264             data.EnsureInsert(key, value);
265         };
266 
267         auto lamfuncCheckLoop = [](SafeMap<string, int>& data, const string& key,
__anoncf81f8e00402(SafeMap<string, int>& data, const string& key, std::chrono::system_clock::time_point absTime) 268             std::chrono::system_clock::time_point absTime) {
269             std::this_thread::sleep_until(absTime);
270             thread_local int i = -1;
271             while (!data.Find(key, i)) {
272                 std::this_thread::sleep_for(std::chrono::microseconds(10));
273             }
274             return i;
275         };
276 
277         using std::chrono::system_clock;
278 
279         std::time_t timeT = system_clock::to_time_t(system_clock::now());
280         timeT += 2;
281         string key("A");
282 
283         for (int i = 0; i < THREAD_NUM; ++i) {
284             threads[i] = std::thread(lamfuncInsert, std::ref(demoData),
285                 key + std::to_string(i), i, system_clock::from_time_t(timeT));
286             vcfi.push_back(std::async(std::launch::async, lamfuncCheckLoop,
287                 std::ref(demoData), key + std::to_string(i), system_clock::from_time_t(timeT)));
288         }
289 
290         std::this_thread::sleep_for(std::chrono::seconds(4));
291         for (auto& t : threads) {
292             t.join();
293         }
294 
295         vector<int> result;
296 
297         for (auto& t : vcfi) {
298             result.push_back(t.get());
299         }
300 
301         std::sort(result.begin(), result.end());
302 
303         for (int i = 0; i < THREAD_NUM; ++i) {
304             ASSERT_EQ(i, result[i]);
305         }
306     });
307 }
308 
309 /*
310  * @tc.name: testUtilsConcurrentWriteAndFindAndSet001
311  * @tc.desc: 100 threads test in writein to the corresponding key of the map,
312  * while findandfix at same time  and check the results
313  */
314 HWTEST_F(UtilsSafeMap, testUtilsConcurrentWriteAndFindAndSet001, TestSize.Level0)
315 {
316     SafeMap<string, int> demoData;
317     std::thread threads[THREAD_NUM];
318     std::vector<std::future<int>> vcfi;
319 
320     ASSERT_NO_THROW({
321         auto lamfuncInsert = [](SafeMap<string, int>& data, const string& key,
__anoncf81f8e00502(SafeMap<string, int>& data, const string& key, const int& value, const std::chrono::system_clock::time_point& absTime) 322             const int& value, const std::chrono::system_clock::time_point& absTime) {
323             std::this_thread::sleep_until(absTime);
324             data.EnsureInsert(key, value);
325         };
326 
327         auto lamfuncCheckLoop = [](SafeMap<string, int>& data, const string& key,
__anoncf81f8e00602(SafeMap<string, int>& data, const string& key, const int& newvalue, std::chrono::system_clock::time_point absTime) 328             const int& newvalue, std::chrono::system_clock::time_point absTime) {
329             std::this_thread::sleep_until(absTime);
330             thread_local int i = -1;
331             while (!data.FindOldAndSetNew(key, i, newvalue)) {
332                 std::this_thread::sleep_for(std::chrono::microseconds(10));
333             }
334             return i;
335         };
336 
337         using std::chrono::system_clock;
338 
339         std::time_t timeT = system_clock::to_time_t(system_clock::now());
340         timeT += 2;
341         string key("A");
342 
343         for (int i = 0; i < THREAD_NUM; ++i) {
344             threads[i] = std::thread(lamfuncInsert, std::ref(demoData),
345                 key + std::to_string(i), i, system_clock::from_time_t(timeT));
346             vcfi.push_back(std::async(std::launch::async, lamfuncCheckLoop,
347                 std::ref(demoData), key + std::to_string(i), i + 1, system_clock::from_time_t(timeT)));
348         }
349 
350         std::this_thread::sleep_for(std::chrono::seconds(4));
351         for (auto& t : threads) {
352             t.join();
353         }
354 
355         vector<int> result;
356         for (auto& t : vcfi) {
357             result.push_back(t.get());
358         }
359 
360         std::sort(result.begin(), result.end());
361 
362         for (int i = 0; i < THREAD_NUM; ++i) {
363             ASSERT_EQ(i, result[i]);
364         }
365 
366         int t = 0;
367         result.clear();
368         for (int i = 0; i < THREAD_NUM; ++i) {
369             t = -1;
370             ASSERT_TRUE(demoData.Find("A" + std::to_string(i), t));
371             result.push_back(t);
372         }
373 
374         std::sort(result.begin(), result.end());
375 
376         for (int i = 0; i < THREAD_NUM; ++i) {
377             ASSERT_EQ(i + 1, result[i]);
378         }
379     });
380 }