1 /*
2 * Copyright (C) 2023 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 <chrono>
17
18 #include "finite_state_machine.h"
19
20 #include "mock_thread_handler.h"
21
22 namespace OHOS {
23 namespace UserIam {
24 namespace FaceAuth {
25 using namespace testing;
26 using namespace testing::ext;
27
28 enum State : uint32_t {
29 STATE_INIT,
30 STATE_VERIFY_STARING,
31 STATE_COLLECT_STARING,
32 STATE_AUTH_PROCESSING,
33 STATE_VERIFY_STOPPING,
34 STATE_COLLECT_STOPPING,
35 STATE_END
36 };
37
38 enum Event : uint32_t {
39 EVENT_START_AUTH,
40 EVENT_VERIFY_STARTED,
41 EVENT_COLLECT_STARTED,
42 EVENT_AUTH_RESULT_GET,
43 EVENT_VERIFY_STOPPED,
44 EVENT_COLLECT_STOP,
45 EVENT_USER_CANCEL,
46 EVENT_TIME_OUT,
47 };
48
49 class StateMachineTest : public testing::Test {
50 public:
51 static void SetUpTestCase();
52
53 static void TearDownTestCase();
54
55 void SetUp() override;
56
57 void TearDown() override;
58 };
59
SetUpTestCase()60 void StateMachineTest::SetUpTestCase()
61 {
62 }
63
TearDownTestCase()64 void StateMachineTest::TearDownTestCase()
65 {
66 }
67
SetUp()68 void StateMachineTest::SetUp()
69 {
70 ThreadHandler::GetSingleThreadInstance()->EnsureTask(nullptr);
71 }
72
TearDown()73 void StateMachineTest::TearDown()
74 {
75 ThreadHandler::GetSingleThreadInstance()->EnsureTask(nullptr);
76 }
77
78 HWTEST_F(StateMachineTest, MachineCreateSelfReturn, TestSize.Level0)
79 {
80 auto handler = ThreadHandler::GetSingleThreadInstance();
81 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine0", STATE_INIT);
82 EXPECT_NE(machineBuilder, nullptr);
83
84 auto ret1 = machineBuilder->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_VERIFY_STARING);
85 EXPECT_NE(ret1, nullptr);
86
87 auto ret2 = ret1->MakeTransition(STATE_VERIFY_STARING, EVENT_VERIFY_STARTED, STATE_COLLECT_STARING);
88 EXPECT_EQ(ret2, ret1);
89 }
90
91 HWTEST_F(StateMachineTest, MachineCreateOnlyBuildOnce, TestSize.Level0)
92 {
93 auto handler = ThreadHandler::GetSingleThreadInstance();
94 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine1", STATE_INIT);
95 EXPECT_NE(machineBuilder, nullptr);
96
97 machineBuilder->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_VERIFY_STARING)
98 ->MakeTransition(STATE_VERIFY_STARING, EVENT_VERIFY_STARTED, STATE_COLLECT_STARING);
99
100 auto first = machineBuilder->Build();
101 EXPECT_NE(first, nullptr);
102
103 auto second = machineBuilder->Build();
104 EXPECT_EQ(second, nullptr);
105 }
106
107 HWTEST_F(StateMachineTest, MachineCreateCheckTransition, TestSize.Level0)
108 {
109 auto handler = ThreadHandler::GetSingleThreadInstance();
110 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine2", STATE_INIT);
111 EXPECT_NE(machineBuilder, nullptr);
112
113 machineBuilder->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_VERIFY_STARING)
114 ->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_COLLECT_STARING);
115
116 auto machine = machineBuilder->Build();
117 EXPECT_EQ(machine, nullptr);
118 }
119
120 HWTEST_F(StateMachineTest, MachineCreateInitialState, TestSize.Level0)
121 {
122 auto handler = ThreadHandler::GetSingleThreadInstance();
123 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine3", STATE_COLLECT_STOPPING);
124 ASSERT_NE(machineBuilder, nullptr);
125
126 machineBuilder->MakeTransition(STATE_COLLECT_STOPPING, EVENT_START_AUTH, STATE_VERIFY_STARING);
127 auto machine = machineBuilder->Build();
128 ASSERT_NE(machine, nullptr);
129 EXPECT_EQ(machine->GetCurrentState(), STATE_COLLECT_STOPPING);
130 }
131
132 HWTEST_F(StateMachineTest, MachineCreateNameCheck, TestSize.Level0)
133 {
134 auto handler = ThreadHandler::GetSingleThreadInstance();
135 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine4", STATE_COLLECT_STOPPING);
136 ASSERT_NE(machineBuilder, nullptr);
137
138 machineBuilder->MakeTransition(STATE_COLLECT_STOPPING, EVENT_START_AUTH, STATE_VERIFY_STARING);
139 auto machine = machineBuilder->Build();
140 ASSERT_NE(machine, nullptr);
141 EXPECT_EQ(machine->GetMachineName(), "testMachine4");
142 }
143
144 HWTEST_F(StateMachineTest, MachineScheduleStepIn, TestSize.Level0)
145 {
146 auto handler = ThreadHandler::GetSingleThreadInstance();
147 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine5", STATE_INIT);
148 ASSERT_NE(machineBuilder, nullptr);
149
150 machineBuilder->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_VERIFY_STARING)
151 ->MakeTransition(STATE_VERIFY_STARING, EVENT_VERIFY_STARTED, STATE_COLLECT_STARING);
152
153 auto machine = machineBuilder->Build();
154 ASSERT_NE(machine, nullptr);
155 EXPECT_EQ(machine->GetCurrentState(), STATE_INIT);
156
157 machine->Schedule(EVENT_START_AUTH);
158 EXPECT_EQ(machine->EnsureCurrentState(), STATE_VERIFY_STARING);
159 machine->Schedule(EVENT_VERIFY_STARTED);
160 EXPECT_EQ(machine->EnsureCurrentState(), STATE_COLLECT_STARING);
161 machine->Schedule(EVENT_VERIFY_STARTED);
162 EXPECT_EQ(machine->EnsureCurrentState(), STATE_COLLECT_STARING);
163 }
164
165 HWTEST_F(StateMachineTest, MachineScheduleWithAction, TestSize.Level0)
166 {
167 auto handler = ThreadHandler::GetSingleThreadInstance();
168 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine6", STATE_INIT);
169 ASSERT_NE(machineBuilder, nullptr);
170
171 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> action1;
172 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> action2;
173 {
__anon8c0447c90102(FiniteStateMachine &machine) 174 auto init = [](FiniteStateMachine &machine) { return machine.GetCurrentState() == STATE_INIT; };
__anon8c0447c90202(FiniteStateMachine &machine) 175 auto verify = [](FiniteStateMachine &machine) { return machine.GetCurrentState() == EVENT_VERIFY_STARTED; };
176 InSequence s;
177 EXPECT_CALL(action1, Call(Truly(init), EVENT_START_AUTH)).Times(Exactly(1));
178 EXPECT_CALL(action2, Call(Truly(verify), EVENT_VERIFY_STARTED)).Times(Exactly(1));
179 }
180
181 machineBuilder
182 ->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_VERIFY_STARING,
__anon8c0447c90302(FiniteStateMachine &machine, uint32_t event) 183 [&action1](FiniteStateMachine &machine, uint32_t event) { action1.Call(machine, event); })
184 ->MakeTransition(STATE_VERIFY_STARING, EVENT_VERIFY_STARTED, STATE_COLLECT_STARING,
__anon8c0447c90402(FiniteStateMachine &machine, uint32_t event) 185 [&action2](FiniteStateMachine &machine, uint32_t event) { action2.Call(machine, event); });
186
187 auto machine = machineBuilder->Build();
188 ASSERT_NE(machine, nullptr);
189 EXPECT_EQ(machine->EnsureCurrentState(), STATE_INIT);
190
191 machine->Schedule(EVENT_START_AUTH);
192 EXPECT_EQ(machine->EnsureCurrentState(), STATE_VERIFY_STARING);
193 machine->Schedule(EVENT_VERIFY_STARTED);
194 EXPECT_EQ(machine->EnsureCurrentState(), STATE_COLLECT_STARING);
195 machine->Schedule(EVENT_VERIFY_STARTED);
196 EXPECT_EQ(machine->EnsureCurrentState(), STATE_COLLECT_STARING);
197 }
198
199 HWTEST_F(StateMachineTest, MachineScheduleWithComplexActionDirectly, TestSize.Level0)
200 {
201 auto handler = MockThreadHandler::InvokeDirectly();
202 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine7", STATE_INIT);
203 ASSERT_NE(machineBuilder, nullptr);
204
205 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> action1;
206 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> action2;
207 {
__anon8c0447c90502(FiniteStateMachine &machine) 208 auto init = [](FiniteStateMachine &machine) { return machine.GetCurrentState() == STATE_INIT; };
__anon8c0447c90602(FiniteStateMachine &machine) 209 auto verify = [](FiniteStateMachine &machine) { return machine.GetCurrentState() == EVENT_VERIFY_STARTED; };
210
211 InSequence s;
212 EXPECT_CALL(action1, Call(Truly(init), EVENT_START_AUTH)).Times(Exactly(1));
213 EXPECT_CALL(action2, Call(Truly(verify), EVENT_VERIFY_STARTED)).Times(Exactly(1));
214 }
215
216 machineBuilder
217 ->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_VERIFY_STARING,
__anon8c0447c90702(FiniteStateMachine &machine, uint32_t event) 218 [&action1](FiniteStateMachine &machine, uint32_t event) {
219 action1.Call(machine, event);
220 machine.Schedule(EVENT_VERIFY_STARTED);
221 })
222 ->MakeTransition(STATE_VERIFY_STARING, EVENT_VERIFY_STARTED, STATE_COLLECT_STARING,
__anon8c0447c90802(FiniteStateMachine &machine, uint32_t event) 223 [&action2](FiniteStateMachine &machine, uint32_t event) {
224 action2.Call(machine, event);
225 machine.Schedule(EVENT_COLLECT_STARTED);
226 })
227 ->MakeTransition(STATE_COLLECT_STARING, EVENT_COLLECT_STARTED, STATE_AUTH_PROCESSING, nullptr);
228
229 auto machine = machineBuilder->Build();
230 ASSERT_NE(machine, nullptr);
231 EXPECT_EQ(machine->EnsureCurrentState(), STATE_INIT);
232
233 machine->Schedule(EVENT_START_AUTH);
234 EXPECT_EQ(machine->EnsureCurrentState(), STATE_AUTH_PROCESSING);
235 }
236
237 HWTEST_F(StateMachineTest, MachineScheduleWithComplexActionBackGround, TestSize.Level0)
238 {
239 auto handler = ThreadHandler::GetSingleThreadInstance();
240 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine8", STATE_INIT);
241 ASSERT_NE(machineBuilder, nullptr);
242
243 machineBuilder
244 ->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_VERIFY_STARING,
__anon8c0447c90902(FiniteStateMachine &machine, uint32_t event) 245 [](FiniteStateMachine &machine, [[maybe_unused]] uint32_t event) {
246 machine.Schedule(EVENT_VERIFY_STARTED);
247 machine.Schedule(EVENT_COLLECT_STARTED);
248 machine.Schedule(EVENT_USER_CANCEL);
249 })
250 ->MakeTransition(STATE_VERIFY_STARING, EVENT_VERIFY_STARTED, STATE_COLLECT_STARING, nullptr)
251 ->MakeTransition(STATE_COLLECT_STARING, EVENT_COLLECT_STARTED, STATE_AUTH_PROCESSING, nullptr)
252 ->MakeTransition(STATE_AUTH_PROCESSING, EVENT_USER_CANCEL, STATE_END, nullptr);
253 auto machine = machineBuilder->Build();
254 ASSERT_NE(machine, nullptr);
255 EXPECT_EQ(machine->EnsureCurrentState(), STATE_INIT);
256
257 machine->Schedule(EVENT_START_AUTH);
258 EXPECT_EQ(machine->EnsureCurrentState(), STATE_END);
259 }
260
261 HWTEST_F(StateMachineTest, MachineScheduleDeadlock, TestSize.Level0)
262 {
263 auto handler = ThreadHandler::GetSingleThreadInstance();
264 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine9", STATE_INIT);
265 ASSERT_NE(machineBuilder, nullptr);
__anon8c0447c90a02(FiniteStateMachine &machine, uint32_t event) 266 machineBuilder->MakeTransition(STATE_INIT, STATE_INIT, STATE_INIT, [](FiniteStateMachine &machine, uint32_t event) {
267 machine.Schedule(STATE_INIT);
268 machine.Schedule(STATE_INIT);
269 machine.Schedule(STATE_INIT);
270 });
271 auto machine = machineBuilder->Build();
272 ASSERT_NE(machine, nullptr);
273 EXPECT_EQ(machine->EnsureCurrentState(), STATE_INIT);
274
275 machine->Schedule(EVENT_START_AUTH);
276 EXPECT_EQ(machine->EnsureCurrentState(), STATE_INIT);
277 }
278
279 HWTEST_F(StateMachineTest, MachineScheduleContinues, TestSize.Level0)
280 {
281 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> action;
282 EXPECT_CALL(action, Call(_, STATE_INIT)).Times(Exactly(3));
283 auto handler = ThreadHandler::GetSingleThreadInstance();
284 {
285 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine10", STATE_INIT);
286 ASSERT_NE(machineBuilder, nullptr);
287 machineBuilder->MakeTransition(STATE_INIT, STATE_INIT, STATE_INIT,
__anon8c0447c90b02(FiniteStateMachine &machine, uint32_t event) 288 [&action](FiniteStateMachine &machine, [[maybe_unused]] uint32_t event) {
289 action.Call(machine, STATE_INIT);
290 });
291 auto machine = machineBuilder->Build();
292 ASSERT_NE(machine, nullptr);
293 machine->Schedule(STATE_INIT);
294 machine->Schedule(STATE_INIT);
295 machine->Schedule(STATE_INIT);
296 handler->EnsureTask(nullptr);
297 }
298 }
299
300 HWTEST_F(StateMachineTest, MachineScheduleExpireNodeTimeout, TestSize.Level0)
301 {
302 auto handler = ThreadHandler::GetSingleThreadInstance();
303
304 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> action;
305 EXPECT_CALL(action, Call(_, STATE_INIT)).Times(Exactly(5));
306 {
307 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine11", STATE_INIT);
308 ASSERT_NE(machineBuilder, nullptr);
309 machineBuilder->MakeTransition(STATE_INIT, STATE_INIT, STATE_INIT,
__anon8c0447c90c02(FiniteStateMachine &machine, uint32_t event) 310 [&action](FiniteStateMachine &machine, [[maybe_unused]] uint32_t event) {
311 std::this_thread::sleep_for(std::chrono::milliseconds(200));
312 action.Call(machine, STATE_INIT);
313 });
314 auto machine = machineBuilder->Build();
315 ASSERT_NE(machine, nullptr);
316
317 machine->SetThreadHandler(handler);
318 handler->EnsureTask(nullptr);
319 machine->Schedule(STATE_INIT);
320 machine->Schedule(STATE_INIT);
321 machine->Schedule(STATE_INIT);
322 machine->Schedule(STATE_INIT);
323 machine->Schedule(STATE_INIT);
324 std::this_thread::sleep_for(std::chrono::milliseconds(100));
325 machine = nullptr;
326 handler->EnsureTask(nullptr);
327 }
328 }
329
330 HWTEST_F(StateMachineTest, MachineScheduleExpireNodeExpire, TestSize.Level0)
331 {
332 auto handler = ThreadHandler::GetSingleThreadInstance();
333 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> action;
334 EXPECT_CALL(action, Call(_, STATE_INIT)).Times(Exactly(0));
335 {
336 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine12", STATE_INIT);
337 ASSERT_NE(machineBuilder, nullptr);
338 machineBuilder->MakeTransition(STATE_INIT, STATE_INIT, STATE_INIT,
__anon8c0447c90d02(FiniteStateMachine &machine, uint32_t event) 339 [&action](FiniteStateMachine &machine, [[maybe_unused]] uint32_t event) {
340 action.Call(machine, STATE_INIT);
341 });
342 auto machine = machineBuilder->Build();
343 ASSERT_NE(machine, nullptr);
__anon8c0447c90e02() 344 handler->PostTask([]() { std::this_thread::sleep_for(std::chrono::milliseconds(1000)); });
345 machine->Schedule(STATE_INIT);
346 machine->Schedule(STATE_INIT);
347 machine->Schedule(STATE_INIT);
348 machine->Schedule(STATE_INIT);
349 machine->Schedule(STATE_INIT);
350 machine = nullptr;
351 }
352 handler->EnsureTask(nullptr);
353 }
354
GetTestMachine(std::shared_ptr<FiniteStateMachine> & machine,MockFunction<void (FiniteStateMachine & machine,uint32_t event)> & action,MockFunction<void (FiniteStateMachine & machine,uint32_t event)> & enter,MockFunction<void (FiniteStateMachine & machine,uint32_t event)> & leave)355 static void GetTestMachine(std::shared_ptr<FiniteStateMachine> &machine,
356 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> &action,
357 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> &enter,
358 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> &leave)
359 {
360 auto machineBuilder = FiniteStateMachine::Builder::New("testMachine13", STATE_INIT);
361 ASSERT_NE(machineBuilder, nullptr);
362
363 machineBuilder
364 ->MakeTransition(STATE_INIT, EVENT_START_AUTH, STATE_VERIFY_STARING,
365 [&action](FiniteStateMachine &machine, uint32_t event) {
366 action.Call(machine, event);
367 machine.Schedule(EVENT_VERIFY_STARTED);
368 machine.Schedule(EVENT_COLLECT_STARTED);
369 })
370 ->MakeTransition(STATE_VERIFY_STARING, EVENT_VERIFY_STARTED, STATE_COLLECT_STARING,
371 [&action](FiniteStateMachine &machine, uint32_t event) { action.Call(machine, event); })
372 ->MakeTransition(STATE_COLLECT_STARING, EVENT_COLLECT_STARTED, STATE_AUTH_PROCESSING,
373 [&action](FiniteStateMachine &machine, uint32_t event) { action.Call(machine, event); })
374 ->MakeTransition(STATE_AUTH_PROCESSING, EVENT_USER_CANCEL, STATE_END,
375 [&action](FiniteStateMachine &machine, uint32_t event) { action.Call(machine, event); });
376
377 machineBuilder->MakeOnStateEnter(STATE_INIT,
378 [&enter](FiniteStateMachine &machine, uint32_t event) { enter.Call(machine, event); });
379 machineBuilder->MakeOnStateLeave(STATE_INIT,
380 [&leave](FiniteStateMachine &machine, uint32_t event) { leave.Call(machine, event); });
381
382 machineBuilder->MakeOnStateEnter(STATE_VERIFY_STARING,
383 [&enter](FiniteStateMachine &machine, uint32_t event) { enter.Call(machine, event); });
384 machineBuilder->MakeOnStateLeave(STATE_VERIFY_STARING,
385 [&leave](FiniteStateMachine &machine, uint32_t event) { leave.Call(machine, event); });
386
387 machineBuilder->MakeOnStateEnter(STATE_COLLECT_STARING,
388 [&enter](FiniteStateMachine &machine, uint32_t event) { enter.Call(machine, event); });
389 machineBuilder->MakeOnStateLeave(STATE_COLLECT_STARING,
390 [&leave](FiniteStateMachine &machine, uint32_t event) { leave.Call(machine, event); });
391
392 machineBuilder->MakeOnStateEnter(STATE_AUTH_PROCESSING,
393 [&enter](FiniteStateMachine &machine, uint32_t event) { enter.Call(machine, event); });
394 machineBuilder->MakeOnStateLeave(STATE_AUTH_PROCESSING,
395 [&leave](FiniteStateMachine &machine, uint32_t event) { leave.Call(machine, event); });
396
397 machineBuilder->MakeOnStateEnter(STATE_END,
398 [&enter](FiniteStateMachine &machine, uint32_t event) { enter.Call(machine, event); });
399
400 machine = machineBuilder->Build();
401 }
402
403 HWTEST_F(StateMachineTest, MachineScheduleEnterAndLeave, TestSize.Level0)
404 {
405 auto handler = ThreadHandler::GetSingleThreadInstance();
406 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> action;
407 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> enter;
408 MockFunction<void(FiniteStateMachine & machine, uint32_t event)> leave;
409
410 InSequence s;
411 EXPECT_CALL(action, Call(_, EVENT_START_AUTH));
412 EXPECT_CALL(leave, Call(_, STATE_INIT));
413 EXPECT_CALL(enter, Call(_, STATE_VERIFY_STARING));
414
415 EXPECT_CALL(action, Call(_, EVENT_VERIFY_STARTED));
416 EXPECT_CALL(leave, Call(_, STATE_VERIFY_STARING));
417 EXPECT_CALL(enter, Call(_, STATE_COLLECT_STARING));
418
419 EXPECT_CALL(action, Call(_, EVENT_COLLECT_STARTED));
420 EXPECT_CALL(leave, Call(_, STATE_COLLECT_STARING));
421 EXPECT_CALL(enter, Call(_, STATE_AUTH_PROCESSING));
422
423 EXPECT_CALL(action, Call(_, EVENT_USER_CANCEL));
424 EXPECT_CALL(leave, Call(_, STATE_AUTH_PROCESSING));
425 EXPECT_CALL(enter, Call(_, STATE_END));
426
427 std::shared_ptr<FiniteStateMachine> machine;
428 GetTestMachine(machine, action, enter, leave);
429 ASSERT_NE(machine, nullptr);
430
431 machine->SetThreadHandler(handler);
432 handler->EnsureTask(nullptr);
433 machine->Schedule(EVENT_START_AUTH);
434 handler->EnsureTask(nullptr);
435 machine->Schedule(EVENT_USER_CANCEL);
436 EXPECT_EQ(STATE_END, machine->EnsureCurrentState());
437
438 handler->EnsureTask(nullptr);
439 }
440 } // namespace FaceAuth
441 } // namespace UserIam
442 } // namespace OHOS