13f4cbf05Sopenharmony_ci/* 23f4cbf05Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 33f4cbf05Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43f4cbf05Sopenharmony_ci * you may not use this file except in compliance with the License. 53f4cbf05Sopenharmony_ci * You may obtain a copy of the License at 63f4cbf05Sopenharmony_ci * 73f4cbf05Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83f4cbf05Sopenharmony_ci * 93f4cbf05Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103f4cbf05Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113f4cbf05Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123f4cbf05Sopenharmony_ci * See the License for the specific language governing permissions and 133f4cbf05Sopenharmony_ci * limitations under the License. 143f4cbf05Sopenharmony_ci */ 153f4cbf05Sopenharmony_ci#include <gtest/gtest.h> 163f4cbf05Sopenharmony_ci#include <thread> 173f4cbf05Sopenharmony_ci#include <string> 183f4cbf05Sopenharmony_ci 193f4cbf05Sopenharmony_ci#include "rwlock.h" 203f4cbf05Sopenharmony_ci 213f4cbf05Sopenharmony_ciusing namespace testing::ext; 223f4cbf05Sopenharmony_ciusing namespace std; 233f4cbf05Sopenharmony_ci 243f4cbf05Sopenharmony_cinamespace OHOS { 253f4cbf05Sopenharmony_cinamespace { 263f4cbf05Sopenharmony_ci 273f4cbf05Sopenharmony_ciclass UtilsRWLockTest : public testing::Test {}; 283f4cbf05Sopenharmony_ci 293f4cbf05Sopenharmony_ci// This class is designed for test RWLock. "buf" is protected by "rwLock". 303f4cbf05Sopenharmony_ciclass TestRWLock { 313f4cbf05Sopenharmony_cipublic: 323f4cbf05Sopenharmony_ci TestRWLock():rwLock(), buf() {} 333f4cbf05Sopenharmony_ci 343f4cbf05Sopenharmony_ci explicit TestRWLock(bool writeFirst):rwLock(writeFirst), buf() {} 353f4cbf05Sopenharmony_ci 363f4cbf05Sopenharmony_ci void WriteStr(const string& str) 373f4cbf05Sopenharmony_ci { 383f4cbf05Sopenharmony_ci rwLock.LockWrite(); 393f4cbf05Sopenharmony_ci for (auto it = str.begin(); it != str.end(); it++) { 403f4cbf05Sopenharmony_ci buf.push_back(*it); 413f4cbf05Sopenharmony_ci this_thread::sleep_for(std::chrono::milliseconds(10)); // 10: Extend time of holding the lock 423f4cbf05Sopenharmony_ci } 433f4cbf05Sopenharmony_ci rwLock.UnLockWrite(); 443f4cbf05Sopenharmony_ci return; 453f4cbf05Sopenharmony_ci } 463f4cbf05Sopenharmony_ci 473f4cbf05Sopenharmony_ci void ReadStr(string& str) 483f4cbf05Sopenharmony_ci { 493f4cbf05Sopenharmony_ci rwLock.LockRead(); 503f4cbf05Sopenharmony_ci for (auto it = buf.begin(); it != buf.end(); it++) { 513f4cbf05Sopenharmony_ci str.push_back(*it); 523f4cbf05Sopenharmony_ci this_thread::sleep_for(std::chrono::milliseconds(10)); // 10: Extend time of holding the lock 533f4cbf05Sopenharmony_ci } 543f4cbf05Sopenharmony_ci rwLock.UnLockRead(); 553f4cbf05Sopenharmony_ci return; 563f4cbf05Sopenharmony_ci } 573f4cbf05Sopenharmony_ciprivate: 583f4cbf05Sopenharmony_ci Utils::RWLock rwLock; 593f4cbf05Sopenharmony_ci string buf; 603f4cbf05Sopenharmony_ci}; 613f4cbf05Sopenharmony_ci 623f4cbf05Sopenharmony_ciconst string WRITE_IN_1("write1"); 633f4cbf05Sopenharmony_ciconst string WRITE_IN_2("write2"); 643f4cbf05Sopenharmony_ci 653f4cbf05Sopenharmony_ci/* 663f4cbf05Sopenharmony_ci * @tc.name: testRWLock001 673f4cbf05Sopenharmony_ci * @tc.desc: RWLock here is under write-first mode. If there are some writing operation waiting, 683f4cbf05Sopenharmony_ci * reading will never happen. Reading operations are likely to run at the same time, when all writing operations 693f4cbf05Sopenharmony_ci * have finished. 703f4cbf05Sopenharmony_ci */ 713f4cbf05Sopenharmony_ciHWTEST_F(UtilsRWLockTest, testRWLock001, TestSize.Level1) 723f4cbf05Sopenharmony_ci{ 733f4cbf05Sopenharmony_ci TestRWLock test; 743f4cbf05Sopenharmony_ci 753f4cbf05Sopenharmony_ci thread first(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_1))); 763f4cbf05Sopenharmony_ci this_thread::sleep_for(std::chrono::milliseconds(4)); // Try our best to make `first` get the lock 773f4cbf05Sopenharmony_ci 783f4cbf05Sopenharmony_ci string readOut1(""); 793f4cbf05Sopenharmony_ci thread second(bind(&TestRWLock::ReadStr, ref(test), ref(readOut1))); 803f4cbf05Sopenharmony_ci thread third(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_2))); 813f4cbf05Sopenharmony_ci string readOut2(""); 823f4cbf05Sopenharmony_ci thread fourth(bind(&TestRWLock::ReadStr, ref(test), ref(readOut2))); 833f4cbf05Sopenharmony_ci 843f4cbf05Sopenharmony_ci 853f4cbf05Sopenharmony_ci first.join(); 863f4cbf05Sopenharmony_ci second.join(); 873f4cbf05Sopenharmony_ci third.join(); 883f4cbf05Sopenharmony_ci fourth.join(); 893f4cbf05Sopenharmony_ci 903f4cbf05Sopenharmony_ci EXPECT_EQ(readOut1, WRITE_IN_1 + WRITE_IN_2); 913f4cbf05Sopenharmony_ci EXPECT_EQ(readOut2, WRITE_IN_1 + WRITE_IN_2); 923f4cbf05Sopenharmony_ci} 933f4cbf05Sopenharmony_ci 943f4cbf05Sopenharmony_ci/* 953f4cbf05Sopenharmony_ci * @tc.name: testRWLock002 963f4cbf05Sopenharmony_ci * @tc.desc: RWLock here is not under write-first mode. So if there are writing and reading operations in queue 973f4cbf05Sopenharmony_ci * with a writing mission running, they will compete when the writing mission completing, but reading operations are 983f4cbf05Sopenharmony_ci * likely to run at the same time. 993f4cbf05Sopenharmony_ci */ 1003f4cbf05Sopenharmony_ciHWTEST_F(UtilsRWLockTest, testRWLock002, TestSize.Level1) 1013f4cbf05Sopenharmony_ci{ 1023f4cbf05Sopenharmony_ci TestRWLock test(false); 1033f4cbf05Sopenharmony_ci 1043f4cbf05Sopenharmony_ci thread first(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_1))); 1053f4cbf05Sopenharmony_ci this_thread::sleep_for(chrono::milliseconds(4)); 1063f4cbf05Sopenharmony_ci 1073f4cbf05Sopenharmony_ci string readOut1(""); 1083f4cbf05Sopenharmony_ci thread second(bind(&TestRWLock::ReadStr, ref(test), ref(readOut1))); 1093f4cbf05Sopenharmony_ci thread third(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_2))); 1103f4cbf05Sopenharmony_ci string readOut2(""); 1113f4cbf05Sopenharmony_ci thread fourth(bind(&TestRWLock::ReadStr, ref(test), ref(readOut2))); 1123f4cbf05Sopenharmony_ci 1133f4cbf05Sopenharmony_ci first.join(); 1143f4cbf05Sopenharmony_ci second.join(); 1153f4cbf05Sopenharmony_ci third.join(); 1163f4cbf05Sopenharmony_ci fourth.join(); 1173f4cbf05Sopenharmony_ci 1183f4cbf05Sopenharmony_ci EXPECT_EQ(readOut1, readOut2); 1193f4cbf05Sopenharmony_ci} 1203f4cbf05Sopenharmony_ci} // namespace 1213f4cbf05Sopenharmony_ci} // namespace OHOS