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