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 "btif/include/btif_state_machine.h" 22 23 namespace { 24 static constexpr uint32_t kInvalidEvent = 0xffffffff; 25 static constexpr uint32_t kEventZero = 0; 26 static constexpr uint32_t kEventOne = 1; 27 static constexpr uint32_t kEventTwo = 2; 28 29 static char dataZero = 0; 30 static char dataOne = 1; 31 static char dataTwo = 2; 32 } // namespace 33 34 class BtifStateMachineImpl : public BtifStateMachine { 35 public: 36 enum { 37 kStateZero, 38 kStateOne, 39 kStateTwo, 40 }; 41 42 class StateZero : public State { 43 public: 44 StateZero(BtifStateMachine& sm) 45 : State(sm, kStateZero), 46 on_enter_(false), 47 on_exit_(false), 48 event_(kInvalidEvent), 49 data_(nullptr) {} 50 void OnEnter() override { 51 on_enter_ = true; 52 on_exit_ = false; 53 } 54 void OnExit() override { 55 on_exit_ = true; 56 on_enter_ = false; 57 } 58 bool ProcessEvent(uint32_t event, void* p_data) override { 59 event_ = event; 60 data_ = p_data; 61 TransitionTo(kStateOne); 62 return true; 63 } 64 65 bool on_enter_; 66 bool on_exit_; 67 uint32_t event_; 68 void* data_; 69 }; 70 71 class StateOne : public State { 72 public: 73 StateOne(BtifStateMachine& sm) 74 : State(sm, kStateOne), 75 on_enter_(false), 76 on_exit_(false), 77 event_(kInvalidEvent), 78 data_(nullptr) {} 79 void OnEnter() override { 80 on_enter_ = true; 81 on_exit_ = false; 82 } 83 void OnExit() override { 84 on_exit_ = true; 85 on_enter_ = false; 86 } 87 bool ProcessEvent(uint32_t event, void* p_data) override { 88 event_ = event; 89 data_ = p_data; 90 TransitionTo(kStateTwo); 91 return true; 92 } 93 94 bool on_enter_; 95 bool on_exit_; 96 uint32_t event_; 97 void* data_; 98 }; 99 100 class StateTwo : public State { 101 public: 102 StateTwo(BtifStateMachine& sm) 103 : State(sm, kStateTwo), 104 on_enter_(false), 105 on_exit_(false), 106 event_(kInvalidEvent), 107 data_(nullptr) {} 108 void OnEnter() override { 109 on_enter_ = true; 110 on_exit_ = false; 111 } 112 void OnExit() override { 113 on_exit_ = true; 114 on_enter_ = false; 115 } 116 bool ProcessEvent(uint32_t event, void* p_data) override { 117 event_ = event; 118 data_ = p_data; 119 TransitionTo(kStateZero); 120 return true; 121 } 122 123 bool on_enter_; 124 bool on_exit_; 125 uint32_t event_; 126 void* data_; 127 }; 128 129 BtifStateMachineImpl() { 130 state_zero_ = new StateZero(*this); 131 state_one_ = new StateOne(*this); 132 state_two_ = new StateTwo(*this); 133 134 AddState(state_zero_); 135 AddState(state_one_); 136 AddState(state_two_); 137 SetInitialState(state_zero_); 138 } 139 140 StateZero* state_zero_; 141 StateOne* state_one_; 142 StateTwo* state_two_; 143 }; 144 145 class BtifStateMachineTest : public ::testing::Test { 146 protected: 147 BtifStateMachineTest() {} 148 149 void SetUp() override { sm_.Start(); } 150 151 void TearDown() override { sm_.Quit(); } 152 153 BtifStateMachineImpl sm_; 154 }; 155 156 TEST_F(BtifStateMachineTest, test_initial_state) { 157 ASSERT_EQ(sm_.kStateZero, sm_.StateId()); 158 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId()); 159 } 160 161 TEST_F(BtifStateMachineTest, test_invalid_state) { 162 sm_.Quit(); 163 ASSERT_EQ(sm_.kStateInvalid, sm_.StateId()); 164 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId()); 165 sm_.Start(); 166 ASSERT_EQ(sm_.kStateZero, sm_.StateId()); 167 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId()); 168 } 169 170 TEST_F(BtifStateMachineTest, test_transition_to) { 171 // Initial state: StateZero 172 ASSERT_EQ(sm_.kStateZero, sm_.StateId()); 173 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId()); 174 ASSERT_TRUE(sm_.state_zero_->on_enter_); 175 ASSERT_FALSE(sm_.state_zero_->on_exit_); 176 177 // Transition to StateOne 178 ASSERT_FALSE(sm_.state_one_->on_enter_); 179 ASSERT_FALSE(sm_.state_one_->on_exit_); 180 sm_.TransitionTo(sm_.kStateOne); 181 ASSERT_EQ(sm_.kStateOne, sm_.StateId()); 182 ASSERT_EQ(sm_.kStateZero, sm_.PreviousStateId()); 183 ASSERT_TRUE(sm_.state_zero_->on_exit_); 184 ASSERT_TRUE(sm_.state_one_->on_enter_); 185 ASSERT_FALSE(sm_.state_one_->on_exit_); 186 187 // Transition to StateTwo 188 ASSERT_FALSE(sm_.state_two_->on_enter_); 189 ASSERT_FALSE(sm_.state_two_->on_exit_); 190 sm_.TransitionTo(sm_.kStateTwo); 191 ASSERT_EQ(sm_.kStateTwo, sm_.StateId()); 192 ASSERT_EQ(sm_.kStateOne, sm_.PreviousStateId()); 193 ASSERT_TRUE(sm_.state_one_->on_exit_); 194 ASSERT_TRUE(sm_.state_two_->on_enter_); 195 ASSERT_FALSE(sm_.state_two_->on_exit_); 196 } 197 198 TEST_F(BtifStateMachineTest, test_process_event) { 199 // Initial state: StateZero 200 ASSERT_EQ(sm_.kStateZero, sm_.StateId()); 201 ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId()); 202 ASSERT_TRUE(sm_.state_zero_->on_enter_); 203 ASSERT_FALSE(sm_.state_zero_->on_exit_); 204 ASSERT_EQ(sm_.state_zero_->event_, kInvalidEvent); 205 ASSERT_EQ(sm_.state_zero_->data_, nullptr); 206 207 // Process an event and transition to StateOne 208 ASSERT_FALSE(sm_.state_one_->on_enter_); 209 ASSERT_FALSE(sm_.state_one_->on_exit_); 210 ASSERT_EQ(sm_.state_one_->event_, kInvalidEvent); 211 ASSERT_EQ(sm_.state_one_->data_, nullptr); 212 ASSERT_TRUE(sm_.ProcessEvent(kEventZero, &dataZero)); 213 ASSERT_EQ(sm_.kStateOne, sm_.StateId()); 214 ASSERT_EQ(sm_.kStateZero, sm_.PreviousStateId()); 215 // Check StateZero 216 ASSERT_EQ(sm_.state_zero_->event_, kEventZero); 217 ASSERT_EQ(sm_.state_zero_->data_, &dataZero); 218 ASSERT_TRUE(sm_.state_zero_->on_exit_); 219 // Check StateOne 220 ASSERT_TRUE(sm_.state_one_->on_enter_); 221 ASSERT_FALSE(sm_.state_one_->on_exit_); 222 ASSERT_EQ(sm_.state_one_->event_, kInvalidEvent); 223 ASSERT_EQ(sm_.state_one_->data_, nullptr); 224 225 // Process an event and transition to StateTwo 226 ASSERT_FALSE(sm_.state_two_->on_enter_); 227 ASSERT_FALSE(sm_.state_two_->on_exit_); 228 ASSERT_EQ(sm_.state_two_->event_, kInvalidEvent); 229 ASSERT_EQ(sm_.state_two_->data_, nullptr); 230 ASSERT_TRUE(sm_.ProcessEvent(kEventOne, &dataOne)); 231 ASSERT_EQ(sm_.kStateTwo, sm_.StateId()); 232 ASSERT_EQ(sm_.kStateOne, sm_.PreviousStateId()); 233 // Check StateOne 234 ASSERT_EQ(sm_.state_one_->event_, kEventOne); 235 ASSERT_EQ(sm_.state_one_->data_, &dataOne); 236 ASSERT_TRUE(sm_.state_one_->on_exit_); 237 // Check StateTwo 238 ASSERT_TRUE(sm_.state_two_->on_enter_); 239 ASSERT_FALSE(sm_.state_two_->on_exit_); 240 ASSERT_EQ(sm_.state_two_->event_, kInvalidEvent); 241 ASSERT_EQ(sm_.state_two_->data_, nullptr); 242 243 // Process an event and transition to StateZero 244 // NOTE: StateZero was exited before and has local state 245 ASSERT_FALSE(sm_.state_zero_->on_enter_); 246 ASSERT_TRUE(sm_.state_zero_->on_exit_); // NOTE: already exited before 247 ASSERT_EQ(sm_.state_zero_->event_, kEventZero); // NOTE: state from before 248 ASSERT_EQ(sm_.state_zero_->data_, &dataZero); // NOTE: state from before 249 ASSERT_TRUE(sm_.ProcessEvent(kEventTwo, &dataTwo)); 250 ASSERT_EQ(sm_.kStateZero, sm_.StateId()); 251 ASSERT_EQ(sm_.kStateTwo, sm_.PreviousStateId()); 252 // Check StateTwo 253 ASSERT_EQ(sm_.state_two_->event_, kEventTwo); 254 ASSERT_EQ(sm_.state_two_->data_, &dataTwo); 255 ASSERT_TRUE(sm_.state_two_->on_exit_); 256 // Check StateZero 257 ASSERT_TRUE(sm_.state_zero_->on_enter_); 258 ASSERT_FALSE(sm_.state_zero_->on_exit_); 259 ASSERT_EQ(sm_.state_zero_->event_, kEventZero); // NOTE: state from before 260 ASSERT_EQ(sm_.state_zero_->data_, &dataZero); // NOTE: state from before 261 } 262