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
16#include <cinttypes>
17#include <thread>
18#include <mutex>
19#include <vector>
20#include <gtest/gtest.h>
21#include "hookmgr.h"
22using namespace testing::ext;
23using namespace std;
24
25namespace initModuleTest {
26#define STAGE_TEST_ONE 0
27int g_publicData = 0;
28mutex g_mutex;
29HOOK_MGR *g_hookMgr = nullptr;
30class HookMgrModuleTest : public testing::Test {
31public:
32    static void SetUpTestCase(void) {};
33    static void TearDownTestCase(void) {};
34    void SetUp() {};
35    void TearDown() {};
36};
37
38struct HookExecCtx {
39    int result;
40    int retErr;
41};
42
43void HookExecFunc(int n)
44{
45    for (int i = 0; i < n; ++i) {
46        HookMgrExecute(g_hookMgr, STAGE_TEST_ONE, nullptr, nullptr);
47    }
48}
49
50static int OhosTestHookMultiThread(const HOOK_INFO *hookInfo, void *executionContext)
51{
52    lock_guard<std::mutex> lg(g_mutex);
53    g_publicData++;
54    return 0;
55}
56
57static int OhosTestHookMultiThreadAnother(const HOOK_INFO *hookInfo, void *executionContext)
58{
59    lock_guard<std::mutex> lg(g_mutex);
60    g_publicData++;
61    return -1;
62}
63
64static void OhosHookPrint(const HOOK_INFO *hookInfo, void *traversalCookie)
65{
66    printf("\tstage[%02d] prio[%02d].\n", hookInfo->stage, hookInfo->prio);
67}
68
69static void DumpAllHooks(HOOK_MGR *hookMgr)
70{
71    printf("----------All Hooks---------------\n");
72    HookMgrTraversal(hookMgr, NULL, OhosHookPrint);
73    printf("----------------------------------\n\n");
74}
75
76HWTEST_F(HookMgrModuleTest, HookMgrModuleTest, TestSize.Level1)
77{
78    int ret;
79    int cnt;
80    g_hookMgr = HookMgrCreate("moduleTestHook");
81    ASSERT_NE(g_hookMgr, nullptr);
82
83    ret = HookMgrAdd(g_hookMgr, STAGE_TEST_ONE, 0, OhosTestHookMultiThread);
84    EXPECT_EQ(ret, 0);
85    cnt = HookMgrGetHooksCnt(g_hookMgr, STAGE_TEST_ONE);
86    EXPECT_EQ(cnt, 1);
87
88    HOOK_INFO info;
89    info.stage = STAGE_TEST_ONE;
90    info.prio = 1;
91    info.hook = OhosTestHookMultiThreadAnother;
92    info.hookCookie = nullptr;
93    HookMgrAddEx(g_hookMgr, &info);
94    cnt = HookMgrGetHooksCnt(g_hookMgr, STAGE_TEST_ONE);
95    EXPECT_EQ(cnt, 2);
96    cnt = HookMgrGetStagesCnt(g_hookMgr);
97    EXPECT_EQ(cnt, 1);
98    DumpAllHooks(g_hookMgr);
99
100    // test multiThread HookMgrExecute
101    std::vector<std::thread> threads;
102    for (int i = 1; i <= 10; ++i) {
103        threads.push_back(std::thread(HookExecFunc, 10));
104    }
105    for (auto & th : threads) {
106        th.join();
107    }
108    EXPECT_EQ(g_publicData, 200);
109
110    HookMgrAdd(g_hookMgr, STAGE_TEST_ONE, 1, OhosTestHookMultiThreadAnother);
111    cnt = HookMgrGetHooksCnt(g_hookMgr, STAGE_TEST_ONE);
112    EXPECT_EQ(cnt, 2);
113
114    HookMgrDel(g_hookMgr, STAGE_TEST_ONE, OhosTestHookMultiThreadAnother);
115    cnt = HookMgrGetHooksCnt(g_hookMgr, STAGE_TEST_ONE);
116    EXPECT_EQ(cnt, 1);
117    HookMgrDestroy(g_hookMgr);
118}
119
120} // namespace init_ut
121