1fa7767c5Sopenharmony_ci/*
2fa7767c5Sopenharmony_ci * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
3fa7767c5Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fa7767c5Sopenharmony_ci * you may not use this file except in compliance with the License.
5fa7767c5Sopenharmony_ci * You may obtain a copy of the License at
6fa7767c5Sopenharmony_ci *
7fa7767c5Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8fa7767c5Sopenharmony_ci *
9fa7767c5Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fa7767c5Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fa7767c5Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fa7767c5Sopenharmony_ci * See the License for the specific language governing permissions and
13fa7767c5Sopenharmony_ci * limitations under the License.
14fa7767c5Sopenharmony_ci */
15fa7767c5Sopenharmony_ci
16fa7767c5Sopenharmony_ci#include "gtest/gtest.h"
17fa7767c5Sopenharmony_ci#define private public
18fa7767c5Sopenharmony_ci#define protected public
19fa7767c5Sopenharmony_ci
20fa7767c5Sopenharmony_ci#undef UNIT_TEST
21fa7767c5Sopenharmony_ci
22fa7767c5Sopenharmony_ci#include <atomic>   // NOLINT
23fa7767c5Sopenharmony_ci#include <chrono>   // NOLINT
24fa7767c5Sopenharmony_ci#include <iostream> // NOLINT
25fa7767c5Sopenharmony_ci#include <memory>   // NOLINT
26fa7767c5Sopenharmony_ci#include "foundation/osal/base/synchronizer.h"
27fa7767c5Sopenharmony_ci#include "foundation/osal/thread/task.h"
28fa7767c5Sopenharmony_ci#include "foundation/pre_defines.h"
29fa7767c5Sopenharmony_ci
30fa7767c5Sopenharmony_ciusing namespace testing::ext;
31fa7767c5Sopenharmony_ci
32fa7767c5Sopenharmony_cinamespace OHOS {
33fa7767c5Sopenharmony_cinamespace Media {
34fa7767c5Sopenharmony_cinamespace Test {
35fa7767c5Sopenharmony_ciusing namespace OSAL;
36fa7767c5Sopenharmony_ci
37fa7767c5Sopenharmony_ciclass TestSynchronizer : public ::testing::Test {
38fa7767c5Sopenharmony_cipublic:
39fa7767c5Sopenharmony_ci    void SetUp() override
40fa7767c5Sopenharmony_ci    {
41fa7767c5Sopenharmony_ci        task1 = std::make_shared<Task>("workTask1");
42fa7767c5Sopenharmony_ci        task2 = std::make_shared<Task>("workTask2");
43fa7767c5Sopenharmony_ci        task3 = std::make_shared<Task>("workTask3");
44fa7767c5Sopenharmony_ci        isDataRcved = false;
45fa7767c5Sopenharmony_ci        isStarted = false;
46fa7767c5Sopenharmony_ci    }
47fa7767c5Sopenharmony_ci
48fa7767c5Sopenharmony_ci    void TearDown() override
49fa7767c5Sopenharmony_ci    {
50fa7767c5Sopenharmony_ci    }
51fa7767c5Sopenharmony_ci
52fa7767c5Sopenharmony_ci    std::shared_ptr<Task> task1;
53fa7767c5Sopenharmony_ci    std::shared_ptr<Task> task2;
54fa7767c5Sopenharmony_ci    std::shared_ptr<Task> task3;
55fa7767c5Sopenharmony_ci    std::atomic<bool> isDataRcved;
56fa7767c5Sopenharmony_ci    std::atomic<bool> isStarted;
57fa7767c5Sopenharmony_ci    static Synchronizer<int, int> synchronizer;
58fa7767c5Sopenharmony_ci};
59fa7767c5Sopenharmony_ci
60fa7767c5Sopenharmony_ciSynchronizer<int, int> TestSynchronizer::synchronizer("sync");
61fa7767c5Sopenharmony_ci
62fa7767c5Sopenharmony_ciHWTEST_F(TestSynchronizer, test_waitfor_fail, TestSize.Level1)
63fa7767c5Sopenharmony_ci{
64fa7767c5Sopenharmony_ci    int syncId = 0;
65fa7767c5Sopenharmony_ci    task1->RegisterHandler([this, syncId] {
66fa7767c5Sopenharmony_ci        UNUSED_VARIABLE(this);
67fa7767c5Sopenharmony_ci        synchronizer.Notify(syncId, 1234);
68fa7767c5Sopenharmony_ci    });
69fa7767c5Sopenharmony_ci    int timeoutMs = 100;
70fa7767c5Sopenharmony_ci    auto start = std::chrono::high_resolution_clock::now();
71fa7767c5Sopenharmony_ci    auto rtv = synchronizer.WaitFor(
72fa7767c5Sopenharmony_ci        syncId, [] {}, timeoutMs);
73fa7767c5Sopenharmony_ci    auto end = std::chrono::high_resolution_clock::now();
74fa7767c5Sopenharmony_ci    auto diff = static_cast<std::chrono::duration<double>>(end - start).count() * 1000;
75fa7767c5Sopenharmony_ci    EXPECT_EQ(false, rtv);
76fa7767c5Sopenharmony_ci    EXPECT_TRUE((std::abs(static_cast<int>(diff) - timeoutMs) < 25) || (diff < 5));
77fa7767c5Sopenharmony_ci    std::cout << "TestSynchronizer time diff: " << diff << std::endl;
78fa7767c5Sopenharmony_ci}
79fa7767c5Sopenharmony_ci
80fa7767c5Sopenharmony_ciHWTEST_F(TestSynchronizer, test_waitfor_succ, TestSize.Level1)
81fa7767c5Sopenharmony_ci{
82fa7767c5Sopenharmony_ci    int syncId = 0;
83fa7767c5Sopenharmony_ci    task1->RegisterHandler([this, syncId] {
84fa7767c5Sopenharmony_ci        UNUSED_VARIABLE(this);
85fa7767c5Sopenharmony_ci        synchronizer.Notify(syncId, 1234);
86fa7767c5Sopenharmony_ci    });
87fa7767c5Sopenharmony_ci    task1->Start();
88fa7767c5Sopenharmony_ci    int timeoutMs = 1000;
89fa7767c5Sopenharmony_ci    auto rtv = synchronizer.WaitFor(
90fa7767c5Sopenharmony_ci        syncId, [] {}, timeoutMs);
91fa7767c5Sopenharmony_ci    EXPECT_EQ(true, rtv);
92fa7767c5Sopenharmony_ci}
93fa7767c5Sopenharmony_ci
94fa7767c5Sopenharmony_ciHWTEST_F(TestSynchronizer, test_waitfor_with_result_succ, TestSize.Level1)
95fa7767c5Sopenharmony_ci{
96fa7767c5Sopenharmony_ci    int syncId = 0;
97fa7767c5Sopenharmony_ci    int expect = 1234;
98fa7767c5Sopenharmony_ci    task1->RegisterHandler([this, syncId, expect] {
99fa7767c5Sopenharmony_ci        UNUSED_VARIABLE(this);
100fa7767c5Sopenharmony_ci        synchronizer.Notify(syncId, expect);
101fa7767c5Sopenharmony_ci    });
102fa7767c5Sopenharmony_ci    task1->Start();
103fa7767c5Sopenharmony_ci    int timeoutMs = 1000;
104fa7767c5Sopenharmony_ci    int result = 0;
105fa7767c5Sopenharmony_ci    auto rtv = synchronizer.WaitFor(
106fa7767c5Sopenharmony_ci        syncId, [] { return true; }, timeoutMs, result);
107fa7767c5Sopenharmony_ci    EXPECT_EQ(true, rtv);
108fa7767c5Sopenharmony_ci    EXPECT_EQ(expect, result);
109fa7767c5Sopenharmony_ci}
110fa7767c5Sopenharmony_ci
111fa7767c5Sopenharmony_ciHWTEST_F(TestSynchronizer, test_wait_succ, TestSize.Level1)
112fa7767c5Sopenharmony_ci{
113fa7767c5Sopenharmony_ci    int syncId = 0;
114fa7767c5Sopenharmony_ci    int result = 0;
115fa7767c5Sopenharmony_ci    int expect = 1234;
116fa7767c5Sopenharmony_ci    task1->RegisterHandler([this, syncId, &result] {
117fa7767c5Sopenharmony_ci        UNUSED_VARIABLE(this);
118fa7767c5Sopenharmony_ci        if (!isDataRcved.load()) {
119fa7767c5Sopenharmony_ci            synchronizer.Wait(
120fa7767c5Sopenharmony_ci                syncId, [] {}, result);
121fa7767c5Sopenharmony_ci            isDataRcved = true;
122fa7767c5Sopenharmony_ci        }
123fa7767c5Sopenharmony_ci    });
124fa7767c5Sopenharmony_ci    task1->Start();
125fa7767c5Sopenharmony_ci    task2->RegisterHandler([this, syncId, expect] {
126fa7767c5Sopenharmony_ci        UNUSED_VARIABLE(this);
127fa7767c5Sopenharmony_ci        synchronizer.Notify(syncId, expect);
128fa7767c5Sopenharmony_ci    });
129fa7767c5Sopenharmony_ci    task2->Start();
130fa7767c5Sopenharmony_ci    while (!isDataRcved.load()) {}
131fa7767c5Sopenharmony_ci    EXPECT_EQ(expect, result);
132fa7767c5Sopenharmony_ci}
133fa7767c5Sopenharmony_ci} // namespace Test
134fa7767c5Sopenharmony_ci} // namespace Media
135fa7767c5Sopenharmony_ci} // namespace OHOS