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