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 }