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 21 using namespace testing::ext; 22 using namespace std; 23 24 namespace OHOS { 25 namespace { 26 27 class UtilsRWLockTest : public testing::Test {}; 28 29 // This class is designed for test RWLock. "buf" is protected by "rwLock". 30 class TestRWLock { 31 public: TestRWLock()32 TestRWLock():rwLock(), buf() {} 33 TestRWLock(bool writeFirst)34 explicit TestRWLock(bool writeFirst):rwLock(writeFirst), buf() {} 35 WriteStr(const string & str)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(1)); 42 } 43 rwLock.UnLockWrite(); 44 return; 45 } 46 ReadStr(string & str)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(1)); 53 } 54 rwLock.UnLockRead(); 55 return; 56 } 57 private: 58 Utils::RWLock rwLock; 59 string buf; 60 }; 61 62 const string WRITE_IN_1("write1"); 63 const 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 will happen at the same time, when all writing operations 69 * have finished. 70 */ 71 HWTEST_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(chrono::milliseconds(1)); 77 78 string readOut1(""); 79 thread second(bind(&TestRWLock::ReadStr, ref(test), ref(readOut1))); 80 this_thread::sleep_for(chrono::milliseconds(1)); 81 82 thread third(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_2))); 83 this_thread::sleep_for(chrono::milliseconds(1)); 84 85 string readOut2(""); 86 thread fourth(bind(&TestRWLock::ReadStr, ref(test), ref(readOut2))); 87 88 first.join(); 89 second.join(); 90 third.join(); 91 fourth.join(); 92 93 EXPECT_EQ(readOut1, WRITE_IN_1 + WRITE_IN_2); 94 EXPECT_EQ(readOut2, WRITE_IN_1 + WRITE_IN_2); 95 } 96 97 /* 98 * @tc.name: testRWLock002 99 * @tc.desc: RWLock here is not under write-first mode. So if there are writing and reading operations in queue 100 * with a writing mission running, they will compete when the writing mission completing. But what we can ensure 101 * is that reading operations in queue will happen at the same time. 102 */ 103 HWTEST_F(UtilsRWLockTest, testRWLock002, TestSize.Level1) 104 { 105 TestRWLock test(false); 106 107 thread first(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_1))); 108 this_thread::sleep_for(chrono::milliseconds(1)); 109 110 string readOut1(""); 111 thread second(bind(&TestRWLock::ReadStr, ref(test), ref(readOut1))); 112 this_thread::sleep_for(chrono::milliseconds(1)); 113 114 thread third(bind(&TestRWLock::WriteStr, ref(test), ref(WRITE_IN_2))); 115 this_thread::sleep_for(chrono::milliseconds(1)); 116 117 string readOut2(""); 118 thread fourth(bind(&TestRWLock::ReadStr, ref(test), ref(readOut2))); 119 120 first.join(); 121 second.join(); 122 third.join(); 123 fourth.join(); 124 125 EXPECT_EQ(readOut1, readOut2); 126 } 127 } // namespace 128 } // namespace OHOS