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 <gtest/gtest.h> 16#include <thread> 17#include <string> 18 19#include "rwlock.h" 20 21using namespace testing::ext; 22using namespace std; 23 24namespace OHOS { 25namespace { 26 27class UtilsRWLockTest : public testing::Test {}; 28 29// This class is designed for test RWLock. "buf" is protected by "rwLock". 30class TestRWLock { 31public: 32 TestRWLock():rwLock(), buf() {} 33 34 explicit TestRWLock(bool writeFirst):rwLock(writeFirst), buf() {} 35 36 void WriteStr(const string& str) 37 { 38 rwLock.LockWrite(); 39 for (auto it = str.begin(); it != str.end(); it++) { 40 buf.push_back(*it); 41 this_thread::sleep_for(std::chrono::milliseconds(10)); // 10: Extend time of holding the lock 42 } 43 rwLock.UnLockWrite(); 44 return; 45 } 46 47 void ReadStr(string& str) 48 { 49 rwLock.LockRead(); 50 for (auto it = buf.begin(); it != buf.end(); it++) { 51 str.push_back(*it); 52 this_thread::sleep_for(std::chrono::milliseconds(10)); // 10: Extend time of holding the lock 53 } 54 rwLock.UnLockRead(); 55 return; 56 } 57private: 58 Utils::RWLock rwLock; 59 string buf; 60}; 61 62const string WRITE_IN_1("write1"); 63const string WRITE_IN_2("write2"); 64 65/* 66 * @tc.name: testRWLock001 67 * @tc.desc: RWLock here is under write-first mode. If there are some writing operation waiting, 68 * reading will never happen. Reading operations are likely to run at the same time, when all writing operations 69 * have finished. 70 */ 71HWTEST_F(UtilsRWLockTest, testRWLock001, TestSize.Level1) 72{ 73 TestRWLock test; 74 75 thread first(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_1))); 76 this_thread::sleep_for(std::chrono::milliseconds(4)); // Try our best to make `first` get the lock 77 78 string readOut1(""); 79 thread second(bind(&TestRWLock::ReadStr, ref(test), ref(readOut1))); 80 thread third(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_2))); 81 string readOut2(""); 82 thread fourth(bind(&TestRWLock::ReadStr, ref(test), ref(readOut2))); 83 84 85 first.join(); 86 second.join(); 87 third.join(); 88 fourth.join(); 89 90 EXPECT_EQ(readOut1, WRITE_IN_1 + WRITE_IN_2); 91 EXPECT_EQ(readOut2, WRITE_IN_1 + WRITE_IN_2); 92} 93 94/* 95 * @tc.name: testRWLock002 96 * @tc.desc: RWLock here is not under write-first mode. So if there are writing and reading operations in queue 97 * with a writing mission running, they will compete when the writing mission completing, but reading operations are 98 * likely to run at the same time. 99 */ 100HWTEST_F(UtilsRWLockTest, testRWLock002, TestSize.Level1) 101{ 102 TestRWLock test(false); 103 104 thread first(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_1))); 105 this_thread::sleep_for(chrono::milliseconds(4)); 106 107 string readOut1(""); 108 thread second(bind(&TestRWLock::ReadStr, ref(test), ref(readOut1))); 109 thread third(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_2))); 110 string readOut2(""); 111 thread fourth(bind(&TestRWLock::ReadStr, ref(test), ref(readOut2))); 112 113 first.join(); 114 second.join(); 115 third.join(); 116 fourth.join(); 117 118 EXPECT_EQ(readOut1, readOut2); 119} 120} // namespace 121} // namespace OHOS