blob: 896e983357f0a9b1fe1bc1055bb4281c9bdf2f38 [file] [log] [blame]
Pavlin Radoslavovd7522292017-11-24 19:12:11 -08001/******************************************************************************
2 *
3 * Copyright 2017 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19#include <gtest/gtest.h>
20
Hansong Zhangdf14c992018-10-04 15:04:18 -070021#include "common/state_machine.h"
22
23using bluetooth::common::StateMachine;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -080024
25namespace {
26static constexpr uint32_t kInvalidEvent = 0xffffffff;
27static constexpr uint32_t kEventZero = 0;
28static constexpr uint32_t kEventOne = 1;
29static constexpr uint32_t kEventTwo = 2;
30
31static char dataZero = 0;
32static char dataOne = 1;
33static char dataTwo = 2;
34} // namespace
35
Hansong Zhangdf14c992018-10-04 15:04:18 -070036class StateMachineImpl : public StateMachine {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -080037 public:
38 enum {
39 kStateZero,
40 kStateOne,
41 kStateTwo,
42 };
43
44 class StateZero : public State {
45 public:
Hansong Zhangdf14c992018-10-04 15:04:18 -070046 StateZero(StateMachine& sm)
Pavlin Radoslavovd7522292017-11-24 19:12:11 -080047 : State(sm, kStateZero),
48 on_enter_(false),
49 on_exit_(false),
50 event_(kInvalidEvent),
51 data_(nullptr) {}
52 void OnEnter() override {
53 on_enter_ = true;
54 on_exit_ = false;
55 }
56 void OnExit() override {
57 on_exit_ = true;
58 on_enter_ = false;
59 }
60 bool ProcessEvent(uint32_t event, void* p_data) override {
61 event_ = event;
62 data_ = p_data;
63 TransitionTo(kStateOne);
64 return true;
65 }
66
67 bool on_enter_;
68 bool on_exit_;
69 uint32_t event_;
70 void* data_;
71 };
72
73 class StateOne : public State {
74 public:
Hansong Zhangdf14c992018-10-04 15:04:18 -070075 StateOne(StateMachine& sm)
Pavlin Radoslavovd7522292017-11-24 19:12:11 -080076 : State(sm, kStateOne),
77 on_enter_(false),
78 on_exit_(false),
79 event_(kInvalidEvent),
80 data_(nullptr) {}
81 void OnEnter() override {
82 on_enter_ = true;
83 on_exit_ = false;
84 }
85 void OnExit() override {
86 on_exit_ = true;
87 on_enter_ = false;
88 }
89 bool ProcessEvent(uint32_t event, void* p_data) override {
90 event_ = event;
91 data_ = p_data;
92 TransitionTo(kStateTwo);
93 return true;
94 }
95
96 bool on_enter_;
97 bool on_exit_;
98 uint32_t event_;
99 void* data_;
100 };
101
102 class StateTwo : public State {
103 public:
Hansong Zhangdf14c992018-10-04 15:04:18 -0700104 StateTwo(StateMachine& sm)
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800105 : State(sm, kStateTwo),
106 on_enter_(false),
107 on_exit_(false),
108 event_(kInvalidEvent),
109 data_(nullptr) {}
110 void OnEnter() override {
111 on_enter_ = true;
112 on_exit_ = false;
113 }
114 void OnExit() override {
115 on_exit_ = true;
116 on_enter_ = false;
117 }
118 bool ProcessEvent(uint32_t event, void* p_data) override {
119 event_ = event;
120 data_ = p_data;
121 TransitionTo(kStateZero);
122 return true;
123 }
124
125 bool on_enter_;
126 bool on_exit_;
127 uint32_t event_;
128 void* data_;
129 };
130
Hansong Zhangdf14c992018-10-04 15:04:18 -0700131 StateMachineImpl() {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800132 state_zero_ = new StateZero(*this);
133 state_one_ = new StateOne(*this);
134 state_two_ = new StateTwo(*this);
135
136 AddState(state_zero_);
137 AddState(state_one_);
138 AddState(state_two_);
139 SetInitialState(state_zero_);
140 }
141
142 StateZero* state_zero_;
143 StateOne* state_one_;
144 StateTwo* state_two_;
145};
146
Hansong Zhangdf14c992018-10-04 15:04:18 -0700147class StateMachineTest : public ::testing::Test {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800148 protected:
Hansong Zhangdf14c992018-10-04 15:04:18 -0700149 StateMachineTest() {}
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800150
151 void SetUp() override { sm_.Start(); }
152
153 void TearDown() override { sm_.Quit(); }
154
Hansong Zhangdf14c992018-10-04 15:04:18 -0700155 StateMachineImpl sm_;
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800156};
157
Hansong Zhangdf14c992018-10-04 15:04:18 -0700158TEST_F(StateMachineTest, test_initial_state) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800159 ASSERT_EQ(sm_.kStateZero, sm_.StateId());
160 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
161}
162
Hansong Zhangdf14c992018-10-04 15:04:18 -0700163TEST_F(StateMachineTest, test_invalid_state) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800164 sm_.Quit();
165 ASSERT_EQ(sm_.kStateInvalid, sm_.StateId());
166 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
167 sm_.Start();
168 ASSERT_EQ(sm_.kStateZero, sm_.StateId());
169 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
170}
171
Hansong Zhangdf14c992018-10-04 15:04:18 -0700172TEST_F(StateMachineTest, test_transition_to) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800173 // Initial state: StateZero
174 ASSERT_EQ(sm_.kStateZero, sm_.StateId());
175 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
176 ASSERT_TRUE(sm_.state_zero_->on_enter_);
177 ASSERT_FALSE(sm_.state_zero_->on_exit_);
178
179 // Transition to StateOne
180 ASSERT_FALSE(sm_.state_one_->on_enter_);
181 ASSERT_FALSE(sm_.state_one_->on_exit_);
182 sm_.TransitionTo(sm_.kStateOne);
183 ASSERT_EQ(sm_.kStateOne, sm_.StateId());
184 ASSERT_EQ(sm_.kStateZero, sm_.PreviousStateId());
185 ASSERT_TRUE(sm_.state_zero_->on_exit_);
186 ASSERT_TRUE(sm_.state_one_->on_enter_);
187 ASSERT_FALSE(sm_.state_one_->on_exit_);
188
189 // Transition to StateTwo
190 ASSERT_FALSE(sm_.state_two_->on_enter_);
191 ASSERT_FALSE(sm_.state_two_->on_exit_);
192 sm_.TransitionTo(sm_.kStateTwo);
193 ASSERT_EQ(sm_.kStateTwo, sm_.StateId());
194 ASSERT_EQ(sm_.kStateOne, sm_.PreviousStateId());
195 ASSERT_TRUE(sm_.state_one_->on_exit_);
196 ASSERT_TRUE(sm_.state_two_->on_enter_);
197 ASSERT_FALSE(sm_.state_two_->on_exit_);
198}
199
Hansong Zhangdf14c992018-10-04 15:04:18 -0700200TEST_F(StateMachineTest, test_process_event) {
Pavlin Radoslavovd7522292017-11-24 19:12:11 -0800201 // Initial state: StateZero
202 ASSERT_EQ(sm_.kStateZero, sm_.StateId());
203 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
204 ASSERT_TRUE(sm_.state_zero_->on_enter_);
205 ASSERT_FALSE(sm_.state_zero_->on_exit_);
206 ASSERT_EQ(sm_.state_zero_->event_, kInvalidEvent);
207 ASSERT_EQ(sm_.state_zero_->data_, nullptr);
208
209 // Process an event and transition to StateOne
210 ASSERT_FALSE(sm_.state_one_->on_enter_);
211 ASSERT_FALSE(sm_.state_one_->on_exit_);
212 ASSERT_EQ(sm_.state_one_->event_, kInvalidEvent);
213 ASSERT_EQ(sm_.state_one_->data_, nullptr);
214 ASSERT_TRUE(sm_.ProcessEvent(kEventZero, &dataZero));
215 ASSERT_EQ(sm_.kStateOne, sm_.StateId());
216 ASSERT_EQ(sm_.kStateZero, sm_.PreviousStateId());
217 // Check StateZero
218 ASSERT_EQ(sm_.state_zero_->event_, kEventZero);
219 ASSERT_EQ(sm_.state_zero_->data_, &dataZero);
220 ASSERT_TRUE(sm_.state_zero_->on_exit_);
221 // Check StateOne
222 ASSERT_TRUE(sm_.state_one_->on_enter_);
223 ASSERT_FALSE(sm_.state_one_->on_exit_);
224 ASSERT_EQ(sm_.state_one_->event_, kInvalidEvent);
225 ASSERT_EQ(sm_.state_one_->data_, nullptr);
226
227 // Process an event and transition to StateTwo
228 ASSERT_FALSE(sm_.state_two_->on_enter_);
229 ASSERT_FALSE(sm_.state_two_->on_exit_);
230 ASSERT_EQ(sm_.state_two_->event_, kInvalidEvent);
231 ASSERT_EQ(sm_.state_two_->data_, nullptr);
232 ASSERT_TRUE(sm_.ProcessEvent(kEventOne, &dataOne));
233 ASSERT_EQ(sm_.kStateTwo, sm_.StateId());
234 ASSERT_EQ(sm_.kStateOne, sm_.PreviousStateId());
235 // Check StateOne
236 ASSERT_EQ(sm_.state_one_->event_, kEventOne);
237 ASSERT_EQ(sm_.state_one_->data_, &dataOne);
238 ASSERT_TRUE(sm_.state_one_->on_exit_);
239 // Check StateTwo
240 ASSERT_TRUE(sm_.state_two_->on_enter_);
241 ASSERT_FALSE(sm_.state_two_->on_exit_);
242 ASSERT_EQ(sm_.state_two_->event_, kInvalidEvent);
243 ASSERT_EQ(sm_.state_two_->data_, nullptr);
244
245 // Process an event and transition to StateZero
246 // NOTE: StateZero was exited before and has local state
247 ASSERT_FALSE(sm_.state_zero_->on_enter_);
248 ASSERT_TRUE(sm_.state_zero_->on_exit_); // NOTE: already exited before
249 ASSERT_EQ(sm_.state_zero_->event_, kEventZero); // NOTE: state from before
250 ASSERT_EQ(sm_.state_zero_->data_, &dataZero); // NOTE: state from before
251 ASSERT_TRUE(sm_.ProcessEvent(kEventTwo, &dataTwo));
252 ASSERT_EQ(sm_.kStateZero, sm_.StateId());
253 ASSERT_EQ(sm_.kStateTwo, sm_.PreviousStateId());
254 // Check StateTwo
255 ASSERT_EQ(sm_.state_two_->event_, kEventTwo);
256 ASSERT_EQ(sm_.state_two_->data_, &dataTwo);
257 ASSERT_TRUE(sm_.state_two_->on_exit_);
258 // Check StateZero
259 ASSERT_TRUE(sm_.state_zero_->on_enter_);
260 ASSERT_FALSE(sm_.state_zero_->on_exit_);
261 ASSERT_EQ(sm_.state_zero_->event_, kEventZero); // NOTE: state from before
262 ASSERT_EQ(sm_.state_zero_->data_, &dataZero); // NOTE: state from before
263}