• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
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 
21 #include "common/state_machine.h"
22 
23 using bluetooth::common::StateMachine;
24 
25 namespace {
26 static constexpr uint32_t kInvalidEvent = 0xffffffff;
27 static constexpr uint32_t kEventZero = 0;
28 static constexpr uint32_t kEventOne = 1;
29 static constexpr uint32_t kEventTwo = 2;
30 
31 static char dataZero = 0;
32 static char dataOne = 1;
33 static char dataTwo = 2;
34 }  // namespace
35 
36 class StateMachineImpl : public StateMachine {
37  public:
38   enum {
39     kStateZero,
40     kStateOne,
41     kStateTwo,
42   };
43 
44   class StateZero : public State {
45    public:
StateZero(StateMachine & sm)46     StateZero(StateMachine& sm)
47         : State(sm, kStateZero),
48           on_enter_(false),
49           on_exit_(false),
50           event_(kInvalidEvent),
51           data_(nullptr) {}
OnEnter()52     void OnEnter() override {
53       on_enter_ = true;
54       on_exit_ = false;
55     }
OnExit()56     void OnExit() override {
57       on_exit_ = true;
58       on_enter_ = false;
59     }
ProcessEvent(uint32_t event,void * p_data)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:
StateOne(StateMachine & sm)75     StateOne(StateMachine& sm)
76         : State(sm, kStateOne),
77           on_enter_(false),
78           on_exit_(false),
79           event_(kInvalidEvent),
80           data_(nullptr) {}
OnEnter()81     void OnEnter() override {
82       on_enter_ = true;
83       on_exit_ = false;
84     }
OnExit()85     void OnExit() override {
86       on_exit_ = true;
87       on_enter_ = false;
88     }
ProcessEvent(uint32_t event,void * p_data)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:
StateTwo(StateMachine & sm)104     StateTwo(StateMachine& sm)
105         : State(sm, kStateTwo),
106           on_enter_(false),
107           on_exit_(false),
108           event_(kInvalidEvent),
109           data_(nullptr) {}
OnEnter()110     void OnEnter() override {
111       on_enter_ = true;
112       on_exit_ = false;
113     }
OnExit()114     void OnExit() override {
115       on_exit_ = true;
116       on_enter_ = false;
117     }
ProcessEvent(uint32_t event,void * p_data)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 
StateMachineImpl()131   StateMachineImpl() {
132     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 
147 class StateMachineTest : public ::testing::Test {
148  protected:
StateMachineTest()149   StateMachineTest() {}
150 
SetUp()151   void SetUp() override { sm_.Start(); }
152 
TearDown()153   void TearDown() override { sm_.Quit(); }
154 
155   StateMachineImpl sm_;
156 };
157 
TEST_F(StateMachineTest,test_initial_state)158 TEST_F(StateMachineTest, test_initial_state) {
159   ASSERT_EQ(sm_.kStateZero, sm_.StateId());
160   ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
161 }
162 
TEST_F(StateMachineTest,test_invalid_state)163 TEST_F(StateMachineTest, test_invalid_state) {
164   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 
TEST_F(StateMachineTest,test_transition_to)172 TEST_F(StateMachineTest, test_transition_to) {
173   // 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 
TEST_F(StateMachineTest,test_process_event)200 TEST_F(StateMachineTest, test_process_event) {
201   // 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 }
264