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" 20using namespace testing::ext; 21using namespace std; 22 23namespace init_ut { 24class HookMgrUnitTest : public testing::Test { 25public: 26 static void SetUpTestCase(void) {}; 27 static void TearDownTestCase(void) {}; 28 void SetUp() {}; 29 void TearDown() {}; 30}; 31 32struct HookExecCtx { 33 int result; 34 int retErr; 35}; 36 37static 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 53static int OhosTestHookRetOK(const HOOK_INFO *hookInfo, void *executionContext) 54{ 55 return OhosHookTestCommon(executionContext, 1); 56} 57 58static int OhosTestHookRetOKEx(const HOOK_INFO *hookInfo, void *executionContext) 59{ 60 return OhosHookTestCommon(executionContext, 2); 61} 62 63static int OhosTestHookRetOKEx2(const HOOK_INFO *hookInfo, void *executionContext) 64{ 65 return OhosHookTestCommon(executionContext, 3); 66} 67 68static void OhosHookPrint(const HOOK_INFO *hookInfo, void *traversalCookie) 69{ 70 printf("\tstage[%02d] prio[%02d].\n", hookInfo->stage, hookInfo->prio); 71} 72 73static 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 82HWTEST_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 184HWTEST_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 251HWTEST_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 304HWTEST_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