1/*
2 * Copyright (c) 2021-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
16#include "gtest/gtest.h"
17#define private public
18#define protected public
19
20#undef UNIT_TEST
21
22#include <atomic>   // NOLINT
23#include <chrono>   // NOLINT
24#include <iostream> // NOLINT
25#include <memory>   // NOLINT
26#include "foundation/osal/base/synchronizer.h"
27#include "foundation/osal/thread/task.h"
28#include "foundation/pre_defines.h"
29
30using namespace testing::ext;
31
32namespace OHOS {
33namespace Media {
34namespace Test {
35using namespace OSAL;
36
37class TestSynchronizer : public ::testing::Test {
38public:
39    void SetUp() override
40    {
41        task1 = std::make_shared<Task>("workTask1");
42        task2 = std::make_shared<Task>("workTask2");
43        task3 = std::make_shared<Task>("workTask3");
44        isDataRcved = false;
45        isStarted = false;
46    }
47
48    void TearDown() override
49    {
50    }
51
52    std::shared_ptr<Task> task1;
53    std::shared_ptr<Task> task2;
54    std::shared_ptr<Task> task3;
55    std::atomic<bool> isDataRcved;
56    std::atomic<bool> isStarted;
57    static Synchronizer<int, int> synchronizer;
58};
59
60Synchronizer<int, int> TestSynchronizer::synchronizer("sync");
61
62HWTEST_F(TestSynchronizer, test_waitfor_fail, TestSize.Level1)
63{
64    int syncId = 0;
65    task1->RegisterHandler([this, syncId] {
66        UNUSED_VARIABLE(this);
67        synchronizer.Notify(syncId, 1234);
68    });
69    int timeoutMs = 100;
70    auto start = std::chrono::high_resolution_clock::now();
71    auto rtv = synchronizer.WaitFor(
72        syncId, [] {}, timeoutMs);
73    auto end = std::chrono::high_resolution_clock::now();
74    auto diff = static_cast<std::chrono::duration<double>>(end - start).count() * 1000;
75    EXPECT_EQ(false, rtv);
76    EXPECT_TRUE((std::abs(static_cast<int>(diff) - timeoutMs) < 25) || (diff < 5));
77    std::cout << "TestSynchronizer time diff: " << diff << std::endl;
78}
79
80HWTEST_F(TestSynchronizer, test_waitfor_succ, TestSize.Level1)
81{
82    int syncId = 0;
83    task1->RegisterHandler([this, syncId] {
84        UNUSED_VARIABLE(this);
85        synchronizer.Notify(syncId, 1234);
86    });
87    task1->Start();
88    int timeoutMs = 1000;
89    auto rtv = synchronizer.WaitFor(
90        syncId, [] {}, timeoutMs);
91    EXPECT_EQ(true, rtv);
92}
93
94HWTEST_F(TestSynchronizer, test_waitfor_with_result_succ, TestSize.Level1)
95{
96    int syncId = 0;
97    int expect = 1234;
98    task1->RegisterHandler([this, syncId, expect] {
99        UNUSED_VARIABLE(this);
100        synchronizer.Notify(syncId, expect);
101    });
102    task1->Start();
103    int timeoutMs = 1000;
104    int result = 0;
105    auto rtv = synchronizer.WaitFor(
106        syncId, [] { return true; }, timeoutMs, result);
107    EXPECT_EQ(true, rtv);
108    EXPECT_EQ(expect, result);
109}
110
111HWTEST_F(TestSynchronizer, test_wait_succ, TestSize.Level1)
112{
113    int syncId = 0;
114    int result = 0;
115    int expect = 1234;
116    task1->RegisterHandler([this, syncId, &result] {
117        UNUSED_VARIABLE(this);
118        if (!isDataRcved.load()) {
119            synchronizer.Wait(
120                syncId, [] {}, result);
121            isDataRcved = true;
122        }
123    });
124    task1->Start();
125    task2->RegisterHandler([this, syncId, expect] {
126        UNUSED_VARIABLE(this);
127        synchronizer.Notify(syncId, expect);
128    });
129    task2->Start();
130    while (!isDataRcved.load()) {}
131    EXPECT_EQ(expect, result);
132}
133} // namespace Test
134} // namespace Media
135} // namespace OHOS