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 <gtest/gtest.h>
18 #include "hookmgr.h"
19 #include "bootstage.h"
20 using namespace testing::ext;
21 using namespace std;
22
23 namespace init_ut {
24 class HookMgrUnitTest : public testing::Test {
25 public:
SetUpTestCase(void)26 static void SetUpTestCase(void) {};
TearDownTestCase(void)27 static void TearDownTestCase(void) {};
SetUp()28 void SetUp() {};
TearDown()29 void TearDown() {};
30 };
31
32 struct HookExecCtx {
33 int result;
34 int retErr;
35 };
36
OhosHookTestCommon(void * executionContext,int result)37 static int OhosHookTestCommon(void *executionContext, int result)
38 {
39 struct HookExecCtx *ctx;
40
41 if (executionContext == nullptr) {
42 return 0;
43 }
44
45 ctx = (struct HookExecCtx *)executionContext;
46 ctx->result = result;
47 if (ctx->retErr) {
48 return -1;
49 }
50 return 0;
51 }
52
OhosTestHookRetOK(const HOOK_INFO * hookInfo,void * executionContext)53 static int OhosTestHookRetOK(const HOOK_INFO *hookInfo, void *executionContext)
54 {
55 return OhosHookTestCommon(executionContext, 1);
56 }
57
OhosTestHookRetOKEx(const HOOK_INFO * hookInfo,void * executionContext)58 static int OhosTestHookRetOKEx(const HOOK_INFO *hookInfo, void *executionContext)
59 {
60 return OhosHookTestCommon(executionContext, 2);
61 }
62
OhosTestHookRetOKEx2(const HOOK_INFO * hookInfo,void * executionContext)63 static int OhosTestHookRetOKEx2(const HOOK_INFO *hookInfo, void *executionContext)
64 {
65 return OhosHookTestCommon(executionContext, 3);
66 }
67
OhosHookPrint(const HOOK_INFO * hookInfo,void * traversalCookie)68 static void OhosHookPrint(const HOOK_INFO *hookInfo, void *traversalCookie)
69 {
70 printf("\tstage[%02d] prio[%02d].\n", hookInfo->stage, hookInfo->prio);
71 }
72
dumpAllHooks(HOOK_MGR * hookMgr)73 static void dumpAllHooks(HOOK_MGR *hookMgr)
74 {
75 printf("----------All Hooks---------------\n");
76 HookMgrTraversal(hookMgr, nullptr, OhosHookPrint);
77 printf("----------------------------------\n\n");
78 }
79
80 #define STAGE_TEST_ONE 0
81
82 HWTEST_F(HookMgrUnitTest, HookMgrAdd_one_stage_unitest, TestSize.Level1)
83 {
84 int ret;
85 int cnt;
86
87 cnt = HookMgrGetStagesCnt(nullptr);
88 EXPECT_EQ(cnt, 0);
89
90 // Add the first hook
91 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOK);
92 EXPECT_EQ(ret, 0);
93 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
94 EXPECT_EQ(cnt, 1);
95 cnt = HookMgrGetStagesCnt(nullptr);
96 EXPECT_EQ(cnt, 1);
97 dumpAllHooks(nullptr);
98
99 // Add the same hook with the same priority again
100 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOK);
101 EXPECT_EQ(ret, 0);
102 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
103 EXPECT_EQ(cnt, 1);
104 dumpAllHooks(nullptr);
105
106 // Add the same hook with different priority
107 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 10, OhosTestHookRetOK);
108 EXPECT_EQ(ret, 0);
109 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
110 EXPECT_EQ(cnt, 2);
111 dumpAllHooks(nullptr);
112
113 // Add the another hook
114 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 10, OhosTestHookRetOKEx);
115 EXPECT_EQ(ret, 0);
116 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
117 EXPECT_EQ(cnt, 3);
118 dumpAllHooks(nullptr);
119
120 // Add the same hook with the same priority again
121 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOK);
122 EXPECT_EQ(ret, 0);
123 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
124 EXPECT_EQ(cnt, 3);
125 dumpAllHooks(nullptr);
126
127 // Add the same hook with the same priority again
128 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 10, OhosTestHookRetOK);
129 EXPECT_EQ(ret, 0);
130 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
131 EXPECT_EQ(cnt, 3);
132 dumpAllHooks(nullptr);
133
134 // Add the another hook
135 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 10, OhosTestHookRetOKEx);
136 EXPECT_EQ(ret, 0);
137 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
138 EXPECT_EQ(cnt, 3);
139 dumpAllHooks(nullptr);
140
141 // Insert to the end of already exist prio
142 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx);
143 EXPECT_EQ(ret, 0);
144 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
145 EXPECT_EQ(cnt, 4);
146 dumpAllHooks(nullptr);
147
148 // Insert to the end of already exist prio
149 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx2);
150 EXPECT_EQ(ret, 0);
151 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
152 EXPECT_EQ(cnt, 5);
153 dumpAllHooks(nullptr);
154
155 // Insert a new prio hook
156 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 5, OhosTestHookRetOK);
157 EXPECT_EQ(ret, 0);
158 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
159 EXPECT_EQ(cnt, 6);
160 dumpAllHooks(nullptr);
161
162 // Insert a new prio hook to the beginning
163 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, -5, OhosTestHookRetOK);
164 EXPECT_EQ(ret, 0);
165 cnt = HookMgrGetHooksCnt(nullptr, STAGE_TEST_ONE);
166 EXPECT_EQ(cnt, 7);
167 dumpAllHooks(nullptr);
168
169 // All hooks are in the same stage
170 cnt = HookMgrGetStagesCnt(nullptr);
171 EXPECT_EQ(cnt, 1);
172
173 // Delete all hooks in stage 0
174 HookMgrDel(nullptr, STAGE_TEST_ONE, nullptr);
175 cnt = HookMgrGetHooksCnt(nullptr, 0);
176 EXPECT_EQ(cnt, 0);
177 cnt = HookMgrGetStagesCnt(nullptr);
178 EXPECT_EQ(cnt, 0);
179
180 dumpAllHooks(nullptr);
181 HookMgrDestroy(nullptr);
182 }
183
184 HWTEST_F(HookMgrUnitTest, HookMgrDel_unitest, TestSize.Level1)
185 {
186 int ret;
187 int cnt;
188
189 HOOK_MGR *hookMgr = HookMgrCreate("test");
190 ASSERT_NE(hookMgr, nullptr);
191
192 // Add one, delete one
193 ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOK);
194 EXPECT_EQ(ret, 0);
195 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
196 EXPECT_EQ(cnt, 1);
197
198 HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOK);
199 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
200 EXPECT_EQ(cnt, 0);
201
202 // Add three same hook with different prio, delete together
203 ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOK);
204 EXPECT_EQ(ret, 0);
205 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
206 EXPECT_EQ(cnt, 1);
207 ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 5, OhosTestHookRetOK);
208 EXPECT_EQ(ret, 0);
209 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
210 EXPECT_EQ(cnt, 2);
211 ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 10, OhosTestHookRetOK);
212 EXPECT_EQ(ret, 0);
213 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
214 EXPECT_EQ(cnt, 3);
215 dumpAllHooks(hookMgr);
216
217 HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOK);
218 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
219 EXPECT_EQ(cnt, 0);
220
221 // Add three different hook with same prio, delete one by one
222 ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOK);
223 EXPECT_EQ(ret, 0);
224 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
225 EXPECT_EQ(cnt, 1);
226 ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx);
227 EXPECT_EQ(ret, 0);
228 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
229 EXPECT_EQ(cnt, 2);
230 ret = HookMgrAdd(hookMgr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx2);
231 EXPECT_EQ(ret, 0);
232 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
233 EXPECT_EQ(cnt, 3);
234 dumpAllHooks(hookMgr);
235
236 HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOK);
237 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
238 EXPECT_EQ(cnt, 2);
239 dumpAllHooks(hookMgr);
240 HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOKEx2);
241 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
242 EXPECT_EQ(cnt, 1);
243 dumpAllHooks(hookMgr);
244 HookMgrDel(hookMgr, STAGE_TEST_ONE, OhosTestHookRetOKEx);
245 cnt = HookMgrGetHooksCnt(hookMgr, STAGE_TEST_ONE);
246 EXPECT_EQ(cnt, 0);
247
248 HookMgrDestroy(hookMgr);
249 }
250
251 HWTEST_F(HookMgrUnitTest, HookMgrExecute_unitest, TestSize.Level1)
252 {
253 int ret;
254 struct HookExecCtx ctx;
255 HOOK_EXEC_OPTIONS options;
256
257 ctx.result = 0;
258 ctx.retErr = 0;
259
260 options.flags = 0;
261 options.preHook = nullptr;
262 options.postHook = nullptr;
263
264 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOK);
265 EXPECT_EQ(ret, 0);
266 ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr);
267 EXPECT_EQ(ret, 0);
268 EXPECT_EQ(ctx.result, 1);
269
270 // Check ignore error
271 ctx.retErr = 1;
272 ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr);
273 EXPECT_EQ(ret, 0);
274 EXPECT_EQ(ctx.result, 1);
275
276 // Do not ignore return errors
277 ctx.retErr = 1;
278 options.flags = HOOK_EXEC_EXIT_WHEN_ERROR;
279 ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, &options);
280 ASSERT_NE(ret, 0);
281 EXPECT_EQ(ctx.result, 1);
282 options.flags = 0;
283
284 // Add another hook with same priority
285 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, 0, OhosTestHookRetOKEx);
286 EXPECT_EQ(ret, 0);
287 ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr);
288 EXPECT_EQ(ret, 0);
289 EXPECT_EQ(ctx.result, 2);
290
291 // Add another hook with higher priority
292 ret = HookMgrAdd(nullptr, STAGE_TEST_ONE, -1, OhosTestHookRetOKEx);
293 EXPECT_EQ(ret, 0);
294 ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr);
295 EXPECT_EQ(ret, 0);
296 EXPECT_EQ(ctx.result, 2);
297
298 HookMgrDel(nullptr, STAGE_TEST_ONE, OhosTestHookRetOKEx);
299 ret = HookMgrExecute(nullptr, STAGE_TEST_ONE, (void *)&ctx, nullptr);
300 EXPECT_EQ(ret, 0);
301 EXPECT_EQ(ctx.result, 1);
302 }
303
304 HWTEST_F(HookMgrUnitTest, HookMgrExecuteInit_unitest, TestSize.Level1)
305 {
306 HookMgrExecute(GetBootStageHookMgr(), INIT_GLOBAL_INIT, nullptr, nullptr);
307 HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, nullptr, nullptr);
308 }
309 } // namespace init_ut
310