blob: 302aa879b694f368b4bf03edb32711ebbb876742 [file] [log] [blame]
Wink Savillefc5b4802009-12-08 21:22:24 -08001/**
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Wink Saville6b888d92010-11-15 12:16:52 -080017package com.android.internal.util;
18
Wink Savilleefcc3d32013-01-30 11:21:22 -080019import java.util.Collection;
20import java.util.Iterator;
21
Wink Saville6b888d92010-11-15 12:16:52 -080022import android.os.Debug;
23import android.os.HandlerThread;
24import android.os.Looper;
25import android.os.Message;
26import android.os.SystemClock;
Wink Savillefc5b4802009-12-08 21:22:24 -080027
Abodunrinwa Tokif9017762015-07-31 18:13:30 -070028import android.test.suitebuilder.annotation.Suppress;
Wink Saville64c42ca2011-04-18 14:55:10 -070029import com.android.internal.util.State;
30import com.android.internal.util.StateMachine;
Wink Savillebbf30dfd2012-05-29 12:40:46 -070031import com.android.internal.util.StateMachine.LogRec;
Wink Savillefc5b4802009-12-08 21:22:24 -080032
Brett Chabotf76c56b2010-07-26 17:28:17 -070033import android.test.suitebuilder.annotation.MediumTest;
34import android.test.suitebuilder.annotation.SmallTest;
35import android.util.Log;
36
37import junit.framework.TestCase;
Wink Savillefc5b4802009-12-08 21:22:24 -080038
39/**
Wink Saville64c42ca2011-04-18 14:55:10 -070040 * Test for StateMachine.
Wink Savillefc5b4802009-12-08 21:22:24 -080041 */
Abodunrinwa Tokif9017762015-07-31 18:13:30 -070042@Suppress // Failing
Wink Saville64c42ca2011-04-18 14:55:10 -070043public class StateMachineTest extends TestCase {
Wink Savillebbf30dfd2012-05-29 12:40:46 -070044 private static final String ENTER = "enter";
45 private static final String EXIT = "exit";
46 private static final String ON_QUITTING = "ON_QUITTING";
47
Wink Savillefc5b4802009-12-08 21:22:24 -080048 private static final int TEST_CMD_1 = 1;
49 private static final int TEST_CMD_2 = 2;
50 private static final int TEST_CMD_3 = 3;
51 private static final int TEST_CMD_4 = 4;
52 private static final int TEST_CMD_5 = 5;
53 private static final int TEST_CMD_6 = 6;
54
55 private static final boolean DBG = true;
Wink Saville6b888d92010-11-15 12:16:52 -080056 private static final boolean WAIT_FOR_DEBUGGER = false;
Wink Saville64c42ca2011-04-18 14:55:10 -070057 private static final String TAG = "StateMachineTest";
Wink Savillefc5b4802009-12-08 21:22:24 -080058
Wink Savillebbf30dfd2012-05-29 12:40:46 -070059 private void sleep(int millis) {
60 try {
61 Thread.sleep(millis);
62 } catch(InterruptedException e) {
63 }
64 }
65
Wink Savilleefcc3d32013-01-30 11:21:22 -080066 private void dumpLogRecs(StateMachine sm) {
67 int size = sm.getLogRecSize();
68 tlog("size=" + size + " count=" + sm.getLogRecCount());
69 for (int i = 0; i < size; i++) {
70 LogRec lr = sm.getLogRec(i);
71 tlog(lr.toString());
72 }
73 }
74
75 private void dumpLogRecs(Collection<LogRec> clr) {
76 int size = clr.size();
77 tlog("size=" + size);
78 for (LogRec lr : clr) {
79 tlog(lr.toString());
80 }
81 }
82
Wink Savillefc5b4802009-12-08 21:22:24 -080083 /**
Wink Savillebbf30dfd2012-05-29 12:40:46 -070084 * Tests {@link StateMachine#quit()}.
Wink Saville1b8b98b2010-03-11 11:49:54 -080085 */
Wink Saville64c42ca2011-04-18 14:55:10 -070086 class StateMachineQuitTest extends StateMachine {
Wink Savilleefcc3d32013-01-30 11:21:22 -080087 Collection<LogRec> mLogRecs;
Wink Saville1b8b98b2010-03-11 11:49:54 -080088
89 StateMachineQuitTest(String name) {
90 super(name);
91 mThisSm = this;
92 setDbg(DBG);
93
94 // Setup state machine with 1 state
95 addState(mS1);
96
97 // Set the initial state
98 setInitialState(mS1);
99 }
100
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700101 @Override
102 public void onQuitting() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800103 log("onQuitting");
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700104 addLogRec(ON_QUITTING);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800105 mLogRecs = mThisSm.copyLogRecs();
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700106 synchronized (mThisSm) {
107 mThisSm.notifyAll();
108 }
Wink Saville1b8b98b2010-03-11 11:49:54 -0800109 }
110
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700111 class S1 extends State {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800112 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700113 public void exit() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800114 log("S1.exit");
115 addLogRec(EXIT);
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700116 }
117 @Override
118 public boolean processMessage(Message message) {
119 switch(message.what) {
120 // Sleep and assume the other messages will be queued up.
121 case TEST_CMD_1: {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800122 log("TEST_CMD_1");
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700123 sleep(500);
124 quit();
125 break;
126 }
127 default: {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800128 log("default what=" + message.what);
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700129 break;
130 }
131 }
132 return HANDLED;
Wink Saville1b8b98b2010-03-11 11:49:54 -0800133 }
134 }
135
136 private StateMachineQuitTest mThisSm;
137 private S1 mS1 = new S1();
138 }
139
140 @SmallTest
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700141 public void testStateMachineQuit() throws Exception {
Wink Saville6b888d92010-11-15 12:16:52 -0800142 if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
Wink Saville1b8b98b2010-03-11 11:49:54 -0800143
144 StateMachineQuitTest smQuitTest = new StateMachineQuitTest("smQuitTest");
145 smQuitTest.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -0800146 if (smQuitTest.isDbg()) tlog("testStateMachineQuit E");
Wink Saville1b8b98b2010-03-11 11:49:54 -0800147
148 synchronized (smQuitTest) {
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700149
150 // Send 6 message we'll quit on the first but all 6 should be processed before quitting.
Wink Saville1b8b98b2010-03-11 11:49:54 -0800151 for (int i = 1; i <= 6; i++) {
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700152 smQuitTest.sendMessage(smQuitTest.obtainMessage(i));
Wink Saville1b8b98b2010-03-11 11:49:54 -0800153 }
154
Wink Saville1b8b98b2010-03-11 11:49:54 -0800155 try {
156 // wait for the messages to be handled
157 smQuitTest.wait();
158 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800159 tloge("testStateMachineQuit: exception while waiting " + e.getMessage());
Wink Saville1b8b98b2010-03-11 11:49:54 -0800160 }
161 }
162
Wink Savilleefcc3d32013-01-30 11:21:22 -0800163 dumpLogRecs(smQuitTest.mLogRecs);
164 assertEquals(8, smQuitTest.mLogRecs.size());
Wink Saville1b8b98b2010-03-11 11:49:54 -0800165
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700166 LogRec lr;
Wink Savilleefcc3d32013-01-30 11:21:22 -0800167 Iterator<LogRec> itr = smQuitTest.mLogRecs.iterator();
168 for (int i = 1; i <= 6; i++) {
169 lr = itr.next();
170 assertEquals(i, lr.getWhat());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700171 assertEquals(smQuitTest.mS1, lr.getState());
172 assertEquals(smQuitTest.mS1, lr.getOriginalState());
173 }
Wink Savilleefcc3d32013-01-30 11:21:22 -0800174 lr = itr.next();
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700175 assertEquals(EXIT, lr.getInfo());
176 assertEquals(smQuitTest.mS1, lr.getState());
Wink Saville1b8b98b2010-03-11 11:49:54 -0800177
Wink Savilleefcc3d32013-01-30 11:21:22 -0800178 lr = itr.next();
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700179 assertEquals(ON_QUITTING, lr.getInfo());
Wink Saville1b8b98b2010-03-11 11:49:54 -0800180
Wink Savilleefcc3d32013-01-30 11:21:22 -0800181 if (smQuitTest.isDbg()) tlog("testStateMachineQuit X");
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700182 }
Wink Saville1b8b98b2010-03-11 11:49:54 -0800183
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700184 /**
185 * Tests {@link StateMachine#quitNow()}
186 */
187 class StateMachineQuitNowTest extends StateMachine {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800188 public Collection<LogRec> mLogRecs = null;
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700189
190 StateMachineQuitNowTest(String name) {
191 super(name);
192 mThisSm = this;
193 setDbg(DBG);
194
195 // Setup state machine with 1 state
196 addState(mS1);
197
198 // Set the initial state
199 setInitialState(mS1);
200 }
201
202 @Override
203 public void onQuitting() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800204 log("onQuitting");
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700205 addLogRec(ON_QUITTING);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800206 // Get a copy of the log records since we're quitting and they will disappear
207 mLogRecs = mThisSm.copyLogRecs();
208
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700209 synchronized (mThisSm) {
210 mThisSm.notifyAll();
211 }
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700212 }
213
214 class S1 extends State {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800215 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700216 public void exit() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800217 log("S1.exit");
218 addLogRec(EXIT);
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700219 }
220 @Override
221 public boolean processMessage(Message message) {
222 switch(message.what) {
223 // Sleep and assume the other messages will be queued up.
224 case TEST_CMD_1: {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800225 log("TEST_CMD_1");
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700226 sleep(500);
227 quitNow();
228 break;
229 }
230 default: {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800231 log("default what=" + message.what);
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700232 break;
233 }
234 }
235 return HANDLED;
236 }
237 }
238
239 private StateMachineQuitNowTest mThisSm;
240 private S1 mS1 = new S1();
241 }
242
243 @SmallTest
244 public void testStateMachineQuitNow() throws Exception {
245 if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
246
247 StateMachineQuitNowTest smQuitNowTest = new StateMachineQuitNowTest("smQuitNowTest");
248 smQuitNowTest.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -0800249 if (smQuitNowTest.isDbg()) tlog("testStateMachineQuitNow E");
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700250
251 synchronized (smQuitNowTest) {
252
Wink Savilleefcc3d32013-01-30 11:21:22 -0800253 // Send 6 message we'll QuitNow on the first even though
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700254 // we send 6 only one will be processed.
255 for (int i = 1; i <= 6; i++) {
256 smQuitNowTest.sendMessage(smQuitNowTest.obtainMessage(i));
257 }
258
259 try {
260 // wait for the messages to be handled
261 smQuitNowTest.wait();
262 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800263 tloge("testStateMachineQuitNow: exception while waiting " + e.getMessage());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700264 }
265 }
266
Wink Savilleefcc3d32013-01-30 11:21:22 -0800267 tlog("testStateMachineQuiteNow: logRecs=" + smQuitNowTest.mLogRecs);
268 assertEquals(3, smQuitNowTest.mLogRecs.size());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700269
Wink Savilleefcc3d32013-01-30 11:21:22 -0800270 Iterator<LogRec> itr = smQuitNowTest.mLogRecs.iterator();
271 LogRec lr = itr.next();
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700272 assertEquals(1, lr.getWhat());
273 assertEquals(smQuitNowTest.mS1, lr.getState());
274 assertEquals(smQuitNowTest.mS1, lr.getOriginalState());
275
Wink Savilleefcc3d32013-01-30 11:21:22 -0800276 lr = itr.next();
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700277 assertEquals(EXIT, lr.getInfo());
278 assertEquals(smQuitNowTest.mS1, lr.getState());
279
Wink Savilleefcc3d32013-01-30 11:21:22 -0800280 lr = itr.next();
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700281 assertEquals(ON_QUITTING, lr.getInfo());
282
Wink Savilleefcc3d32013-01-30 11:21:22 -0800283 if (smQuitNowTest.isDbg()) tlog("testStateMachineQuitNow X");
Wink Saville1b8b98b2010-03-11 11:49:54 -0800284 }
285
286 /**
Wink Savillee7be6a82010-03-18 17:03:30 -0700287 * Test enter/exit can use transitionTo
288 */
Wink Saville64c42ca2011-04-18 14:55:10 -0700289 class StateMachineEnterExitTransitionToTest extends StateMachine {
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700290
Wink Savillee7be6a82010-03-18 17:03:30 -0700291 StateMachineEnterExitTransitionToTest(String name) {
292 super(name);
293 mThisSm = this;
294 setDbg(DBG);
295
296 // Setup state machine with 1 state
297 addState(mS1);
298 addState(mS2);
299 addState(mS3);
300 addState(mS4);
301
302 // Set the initial state
303 setInitialState(mS1);
304 }
305
Wink Saville64c42ca2011-04-18 14:55:10 -0700306 class S1 extends State {
307 @Override
308 public void enter() {
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700309 // Test transitions in enter on the initial state work
Wink Savilleefcc3d32013-01-30 11:21:22 -0800310 addLogRec(ENTER);
Wink Savillee7be6a82010-03-18 17:03:30 -0700311 transitionTo(mS2);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800312 log("S1.enter");
Wink Savillee7be6a82010-03-18 17:03:30 -0700313 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700314 @Override
315 public void exit() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800316 addLogRec(EXIT);
317 log("S1.exit");
Wink Savillee7be6a82010-03-18 17:03:30 -0700318 }
319 }
320
Wink Saville64c42ca2011-04-18 14:55:10 -0700321 class S2 extends State {
322 @Override
323 public void enter() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800324 addLogRec(ENTER);
325 log("S2.enter");
Wink Savillee7be6a82010-03-18 17:03:30 -0700326 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700327 @Override
328 public void exit() {
Wink Savillee7be6a82010-03-18 17:03:30 -0700329 // Test transition in exit work
Wink Savillee7be6a82010-03-18 17:03:30 -0700330 transitionTo(mS4);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800331
332 assertEquals(TEST_CMD_1, getCurrentMessage().what);
333 addLogRec(EXIT);
334
335 log("S2.exit");
Wink Savillee7be6a82010-03-18 17:03:30 -0700336 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700337 @Override
338 public boolean processMessage(Message message) {
Wink Savillee7be6a82010-03-18 17:03:30 -0700339 // Start a transition to S3 but it will be
Wink Savillea4f3bec2010-05-19 09:11:38 -0700340 // changed to a transition to S4 in exit
Wink Savillee7be6a82010-03-18 17:03:30 -0700341 transitionTo(mS3);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800342 log("S2.processMessage");
Wink Savillea4f3bec2010-05-19 09:11:38 -0700343 return HANDLED;
Wink Savillee7be6a82010-03-18 17:03:30 -0700344 }
345 }
346
Wink Saville64c42ca2011-04-18 14:55:10 -0700347 class S3 extends State {
348 @Override
349 public void enter() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800350 addLogRec(ENTER);
351 log("S3.enter");
Wink Savillee7be6a82010-03-18 17:03:30 -0700352 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700353 @Override
354 public void exit() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800355 addLogRec(EXIT);
356 log("S3.exit");
Wink Savillee7be6a82010-03-18 17:03:30 -0700357 }
358 }
359
Wink Saville64c42ca2011-04-18 14:55:10 -0700360 class S4 extends State {
361 @Override
362 public void enter() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800363 addLogRec(ENTER);
Wink Savillee7be6a82010-03-18 17:03:30 -0700364 // Test that we can do halting in an enter/exit
365 transitionToHaltingState();
Wink Savilleefcc3d32013-01-30 11:21:22 -0800366 log("S4.enter");
Wink Savillee7be6a82010-03-18 17:03:30 -0700367 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700368 @Override
369 public void exit() {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800370 addLogRec(EXIT);
371 log("S4.exit");
Wink Savillee7be6a82010-03-18 17:03:30 -0700372 }
373 }
374
375 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700376 protected void onHalting() {
Wink Savillee7be6a82010-03-18 17:03:30 -0700377 synchronized (mThisSm) {
378 mThisSm.notifyAll();
379 }
380 }
381
382 private StateMachineEnterExitTransitionToTest mThisSm;
383 private S1 mS1 = new S1();
384 private S2 mS2 = new S2();
385 private S3 mS3 = new S3();
386 private S4 mS4 = new S4();
Wink Savillee7be6a82010-03-18 17:03:30 -0700387 }
388
389 @SmallTest
390 public void testStateMachineEnterExitTransitionToTest() throws Exception {
391 //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
392
393 StateMachineEnterExitTransitionToTest smEnterExitTranstionToTest =
394 new StateMachineEnterExitTransitionToTest("smEnterExitTranstionToTest");
395 smEnterExitTranstionToTest.start();
396 if (smEnterExitTranstionToTest.isDbg()) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800397 tlog("testStateMachineEnterExitTransitionToTest E");
Wink Savillee7be6a82010-03-18 17:03:30 -0700398 }
399
400 synchronized (smEnterExitTranstionToTest) {
Wink Savillea4f3bec2010-05-19 09:11:38 -0700401 smEnterExitTranstionToTest.sendMessage(TEST_CMD_1);
Wink Savillee7be6a82010-03-18 17:03:30 -0700402
403 try {
404 // wait for the messages to be handled
405 smEnterExitTranstionToTest.wait();
406 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800407 tloge("testStateMachineEnterExitTransitionToTest: exception while waiting "
Wink Savillee7be6a82010-03-18 17:03:30 -0700408 + e.getMessage());
409 }
410 }
411
Wink Savilleefcc3d32013-01-30 11:21:22 -0800412 dumpLogRecs(smEnterExitTranstionToTest);
Wink Savillee7be6a82010-03-18 17:03:30 -0700413
Wink Savilleefcc3d32013-01-30 11:21:22 -0800414 assertEquals(9, smEnterExitTranstionToTest.getLogRecCount());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700415 LogRec lr;
Wink Savillee7be6a82010-03-18 17:03:30 -0700416
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700417 lr = smEnterExitTranstionToTest.getLogRec(0);
418 assertEquals(ENTER, lr.getInfo());
419 assertEquals(smEnterExitTranstionToTest.mS1, lr.getState());
Wink Savillee7be6a82010-03-18 17:03:30 -0700420
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700421 lr = smEnterExitTranstionToTest.getLogRec(1);
422 assertEquals(EXIT, lr.getInfo());
423 assertEquals(smEnterExitTranstionToTest.mS1, lr.getState());
424
425 lr = smEnterExitTranstionToTest.getLogRec(2);
426 assertEquals(ENTER, lr.getInfo());
427 assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
428
429 lr = smEnterExitTranstionToTest.getLogRec(3);
430 assertEquals(TEST_CMD_1, lr.getWhat());
431 assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
432 assertEquals(smEnterExitTranstionToTest.mS2, lr.getOriginalState());
Wink Savilleefcc3d32013-01-30 11:21:22 -0800433 assertEquals(smEnterExitTranstionToTest.mS3, lr.getDestState());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700434
435 lr = smEnterExitTranstionToTest.getLogRec(4);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800436 assertEquals(TEST_CMD_1, lr.getWhat());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700437 assertEquals(smEnterExitTranstionToTest.mS2, lr.getState());
Wink Savilleefcc3d32013-01-30 11:21:22 -0800438 assertEquals(smEnterExitTranstionToTest.mS2, lr.getOriginalState());
439 assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
440 assertEquals(EXIT, lr.getInfo());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700441
442 lr = smEnterExitTranstionToTest.getLogRec(5);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800443 assertEquals(TEST_CMD_1, lr.getWhat());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700444 assertEquals(ENTER, lr.getInfo());
445 assertEquals(smEnterExitTranstionToTest.mS3, lr.getState());
Wink Savilleefcc3d32013-01-30 11:21:22 -0800446 assertEquals(smEnterExitTranstionToTest.mS3, lr.getOriginalState());
447 assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700448
449 lr = smEnterExitTranstionToTest.getLogRec(6);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800450 assertEquals(TEST_CMD_1, lr.getWhat());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700451 assertEquals(EXIT, lr.getInfo());
452 assertEquals(smEnterExitTranstionToTest.mS3, lr.getState());
Wink Savilleefcc3d32013-01-30 11:21:22 -0800453 assertEquals(smEnterExitTranstionToTest.mS3, lr.getOriginalState());
454 assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700455
456 lr = smEnterExitTranstionToTest.getLogRec(7);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800457 assertEquals(TEST_CMD_1, lr.getWhat());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700458 assertEquals(ENTER, lr.getInfo());
459 assertEquals(smEnterExitTranstionToTest.mS4, lr.getState());
Wink Savilleefcc3d32013-01-30 11:21:22 -0800460 assertEquals(smEnterExitTranstionToTest.mS4, lr.getOriginalState());
461 assertEquals(smEnterExitTranstionToTest.mS4, lr.getDestState());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700462
463 lr = smEnterExitTranstionToTest.getLogRec(8);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800464 assertEquals(TEST_CMD_1, lr.getWhat());
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700465 assertEquals(EXIT, lr.getInfo());
466 assertEquals(smEnterExitTranstionToTest.mS4, lr.getState());
Wink Savilleefcc3d32013-01-30 11:21:22 -0800467 assertEquals(smEnterExitTranstionToTest.mS4, lr.getOriginalState());
Wink Savillee7be6a82010-03-18 17:03:30 -0700468
469 if (smEnterExitTranstionToTest.isDbg()) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800470 tlog("testStateMachineEnterExitTransitionToTest X");
Wink Savillee7be6a82010-03-18 17:03:30 -0700471 }
472 }
473
474 /**
Wink Savillefc5b4802009-12-08 21:22:24 -0800475 * Tests that ProcessedMessage works as a circular buffer.
476 */
Wink Saville64c42ca2011-04-18 14:55:10 -0700477 class StateMachine0 extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -0800478 StateMachine0(String name) {
479 super(name);
480 mThisSm = this;
481 setDbg(DBG);
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700482 setLogRecSize(3);
Wink Savillefc5b4802009-12-08 21:22:24 -0800483
484 // Setup state machine with 1 state
485 addState(mS1);
486
487 // Set the initial state
488 setInitialState(mS1);
489 }
490
Wink Saville64c42ca2011-04-18 14:55:10 -0700491 class S1 extends State {
492 @Override
493 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -0800494 if (message.what == TEST_CMD_6) {
495 transitionToHaltingState();
496 }
Wink Savillea4f3bec2010-05-19 09:11:38 -0700497 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800498 }
499 }
500
501 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700502 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800503 synchronized (mThisSm) {
504 mThisSm.notifyAll();
505 }
506 }
507
508 private StateMachine0 mThisSm;
509 private S1 mS1 = new S1();
510 }
511
512 @SmallTest
513 public void testStateMachine0() throws Exception {
Wink Saville1b8b98b2010-03-11 11:49:54 -0800514 //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
Wink Savillefc5b4802009-12-08 21:22:24 -0800515
516 StateMachine0 sm0 = new StateMachine0("sm0");
517 sm0.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -0800518 if (sm0.isDbg()) tlog("testStateMachine0 E");
Wink Savillefc5b4802009-12-08 21:22:24 -0800519
520 synchronized (sm0) {
521 // Send 6 messages
522 for (int i = 1; i <= 6; i++) {
523 sm0.sendMessage(sm0.obtainMessage(i));
524 }
525
526 try {
527 // wait for the messages to be handled
528 sm0.wait();
529 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800530 tloge("testStateMachine0: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -0800531 }
532 }
533
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700534 assertEquals(6, sm0.getLogRecCount());
535 assertEquals(3, sm0.getLogRecSize());
Wink Savillefc5b4802009-12-08 21:22:24 -0800536
Wink Savilleefcc3d32013-01-30 11:21:22 -0800537 dumpLogRecs(sm0);
538
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700539 LogRec lr;
540 lr = sm0.getLogRec(0);
541 assertEquals(TEST_CMD_4, lr.getWhat());
542 assertEquals(sm0.mS1, lr.getState());
543 assertEquals(sm0.mS1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800544
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700545 lr = sm0.getLogRec(1);
546 assertEquals(TEST_CMD_5, lr.getWhat());
547 assertEquals(sm0.mS1, lr.getState());
548 assertEquals(sm0.mS1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800549
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700550 lr = sm0.getLogRec(2);
551 assertEquals(TEST_CMD_6, lr.getWhat());
552 assertEquals(sm0.mS1, lr.getState());
553 assertEquals(sm0.mS1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800554
Wink Savilleefcc3d32013-01-30 11:21:22 -0800555 if (sm0.isDbg()) tlog("testStateMachine0 X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800556 }
557
558 /**
559 * This tests enter/exit and transitions to the same state.
560 * The state machine has one state, it receives two messages
561 * in state mS1. With the first message it transitions to
562 * itself which causes it to be exited and reentered.
563 */
Wink Saville64c42ca2011-04-18 14:55:10 -0700564 class StateMachine1 extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -0800565 StateMachine1(String name) {
566 super(name);
567 mThisSm = this;
568 setDbg(DBG);
569
570 // Setup state machine with 1 state
571 addState(mS1);
572
573 // Set the initial state
574 setInitialState(mS1);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800575 if (DBG) log("StateMachine1: ctor X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800576 }
577
Wink Saville64c42ca2011-04-18 14:55:10 -0700578 class S1 extends State {
579 @Override
580 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800581 mEnterCount++;
582 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700583 @Override
584 public void exit() {
585 mExitCount++;
586 }
587 @Override
588 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -0800589 if (message.what == TEST_CMD_1) {
590 assertEquals(1, mEnterCount);
591 assertEquals(0, mExitCount);
592 transitionTo(mS1);
593 } else if (message.what == TEST_CMD_2) {
594 assertEquals(2, mEnterCount);
595 assertEquals(1, mExitCount);
596 transitionToHaltingState();
597 }
Wink Savillea4f3bec2010-05-19 09:11:38 -0700598 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800599 }
Wink Savillefc5b4802009-12-08 21:22:24 -0800600 }
601
602 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700603 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800604 synchronized (mThisSm) {
605 mThisSm.notifyAll();
606 }
607 }
608
609 private StateMachine1 mThisSm;
610 private S1 mS1 = new S1();
611
612 private int mEnterCount;
613 private int mExitCount;
614 }
615
Brett Chabotf76c56b2010-07-26 17:28:17 -0700616 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -0800617 public void testStateMachine1() throws Exception {
618 StateMachine1 sm1 = new StateMachine1("sm1");
619 sm1.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -0800620 if (sm1.isDbg()) tlog("testStateMachine1 E");
Wink Savillefc5b4802009-12-08 21:22:24 -0800621
622 synchronized (sm1) {
623 // Send two messages
Wink Saville91fbd562010-03-17 17:12:43 -0700624 sm1.sendMessage(TEST_CMD_1);
625 sm1.sendMessage(TEST_CMD_2);
Wink Savillefc5b4802009-12-08 21:22:24 -0800626
627 try {
628 // wait for the messages to be handled
629 sm1.wait();
630 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800631 tloge("testStateMachine1: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -0800632 }
633 }
634
635 assertEquals(2, sm1.mEnterCount);
636 assertEquals(2, sm1.mExitCount);
637
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700638 assertEquals(2, sm1.getLogRecSize());
Wink Savillefc5b4802009-12-08 21:22:24 -0800639
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700640 LogRec lr;
641 lr = sm1.getLogRec(0);
642 assertEquals(TEST_CMD_1, lr.getWhat());
643 assertEquals(sm1.mS1, lr.getState());
644 assertEquals(sm1.mS1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800645
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700646 lr = sm1.getLogRec(1);
647 assertEquals(TEST_CMD_2, lr.getWhat());
648 assertEquals(sm1.mS1, lr.getState());
649 assertEquals(sm1.mS1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800650
651 assertEquals(2, sm1.mEnterCount);
652 assertEquals(2, sm1.mExitCount);
653
Wink Savilleefcc3d32013-01-30 11:21:22 -0800654 if (sm1.isDbg()) tlog("testStateMachine1 X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800655 }
656
657 /**
658 * Test deferring messages and states with no parents. The state machine
659 * has two states, it receives two messages in state mS1 deferring them
660 * until what == TEST_CMD_2 and then transitions to state mS2. State
661 * mS2 then receives both of the deferred messages first TEST_CMD_1 and
662 * then TEST_CMD_2.
663 */
Wink Saville64c42ca2011-04-18 14:55:10 -0700664 class StateMachine2 extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -0800665 StateMachine2(String name) {
666 super(name);
667 mThisSm = this;
668 setDbg(DBG);
669
670 // Setup the hierarchy
671 addState(mS1);
672 addState(mS2);
673
674 // Set the initial state
675 setInitialState(mS1);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800676 if (DBG) log("StateMachine2: ctor X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800677 }
678
Wink Saville64c42ca2011-04-18 14:55:10 -0700679 class S1 extends State {
680 @Override
681 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800682 mDidEnter = true;
683 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700684 @Override
685 public void exit() {
686 mDidExit = true;
687 }
688 @Override
689 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -0800690 deferMessage(message);
691 if (message.what == TEST_CMD_2) {
692 transitionTo(mS2);
693 }
Wink Savillea4f3bec2010-05-19 09:11:38 -0700694 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800695 }
Wink Savillefc5b4802009-12-08 21:22:24 -0800696 }
697
Wink Saville64c42ca2011-04-18 14:55:10 -0700698 class S2 extends State {
699 @Override
700 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -0800701 if (message.what == TEST_CMD_2) {
702 transitionToHaltingState();
703 }
Wink Savillea4f3bec2010-05-19 09:11:38 -0700704 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800705 }
706 }
707
708 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700709 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800710 synchronized (mThisSm) {
711 mThisSm.notifyAll();
712 }
713 }
714
715 private StateMachine2 mThisSm;
716 private S1 mS1 = new S1();
717 private S2 mS2 = new S2();
718
719 private boolean mDidEnter = false;
720 private boolean mDidExit = false;
721 }
722
Brett Chabotf76c56b2010-07-26 17:28:17 -0700723 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -0800724 public void testStateMachine2() throws Exception {
725 StateMachine2 sm2 = new StateMachine2("sm2");
726 sm2.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -0800727 if (sm2.isDbg()) tlog("testStateMachine2 E");
Wink Savillefc5b4802009-12-08 21:22:24 -0800728
729 synchronized (sm2) {
730 // Send two messages
Wink Saville91fbd562010-03-17 17:12:43 -0700731 sm2.sendMessage(TEST_CMD_1);
732 sm2.sendMessage(TEST_CMD_2);
Wink Savillefc5b4802009-12-08 21:22:24 -0800733
734 try {
735 // wait for the messages to be handled
736 sm2.wait();
737 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800738 tloge("testStateMachine2: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -0800739 }
740 }
741
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700742 assertEquals(4, sm2.getLogRecSize());
Wink Savillefc5b4802009-12-08 21:22:24 -0800743
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700744 LogRec lr;
745 lr = sm2.getLogRec(0);
746 assertEquals(TEST_CMD_1, lr.getWhat());
747 assertEquals(sm2.mS1, lr.getState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800748
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700749 lr = sm2.getLogRec(1);
750 assertEquals(TEST_CMD_2, lr.getWhat());
751 assertEquals(sm2.mS1, lr.getState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800752
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700753 lr = sm2.getLogRec(2);
754 assertEquals(TEST_CMD_1, lr.getWhat());
755 assertEquals(sm2.mS2, lr.getState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800756
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700757 lr = sm2.getLogRec(3);
758 assertEquals(TEST_CMD_2, lr.getWhat());
759 assertEquals(sm2.mS2, lr.getState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800760
761 assertTrue(sm2.mDidEnter);
762 assertTrue(sm2.mDidExit);
763
Wink Savilleefcc3d32013-01-30 11:21:22 -0800764 if (sm2.isDbg()) tlog("testStateMachine2 X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800765 }
766
767 /**
768 * Test that unhandled messages in a child are handled by the parent.
769 * When TEST_CMD_2 is received.
770 */
Wink Saville64c42ca2011-04-18 14:55:10 -0700771 class StateMachine3 extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -0800772 StateMachine3(String name) {
773 super(name);
774 mThisSm = this;
775 setDbg(DBG);
776
777 // Setup the simplest hierarchy of two states
778 // mParentState and mChildState.
779 // (Use indentation to help visualize hierarchy)
780 addState(mParentState);
781 addState(mChildState, mParentState);
782
783 // Set the initial state will be the child
784 setInitialState(mChildState);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800785 if (DBG) log("StateMachine3: ctor X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800786 }
787
Wink Saville64c42ca2011-04-18 14:55:10 -0700788 class ParentState extends State {
789 @Override
790 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -0800791 if (message.what == TEST_CMD_2) {
792 transitionToHaltingState();
793 }
Wink Savillea4f3bec2010-05-19 09:11:38 -0700794 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800795 }
796 }
797
Wink Saville64c42ca2011-04-18 14:55:10 -0700798 class ChildState extends State {
799 @Override
800 public boolean processMessage(Message message) {
Wink Savillea4f3bec2010-05-19 09:11:38 -0700801 return NOT_HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800802 }
803 }
804
805 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700806 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800807 synchronized (mThisSm) {
808 mThisSm.notifyAll();
809 }
810 }
811
812 private StateMachine3 mThisSm;
813 private ParentState mParentState = new ParentState();
814 private ChildState mChildState = new ChildState();
815 }
816
Brett Chabotf76c56b2010-07-26 17:28:17 -0700817 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -0800818 public void testStateMachine3() throws Exception {
819 StateMachine3 sm3 = new StateMachine3("sm3");
820 sm3.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -0800821 if (sm3.isDbg()) tlog("testStateMachine3 E");
Wink Savillefc5b4802009-12-08 21:22:24 -0800822
823 synchronized (sm3) {
824 // Send two messages
Wink Saville91fbd562010-03-17 17:12:43 -0700825 sm3.sendMessage(TEST_CMD_1);
826 sm3.sendMessage(TEST_CMD_2);
Wink Savillefc5b4802009-12-08 21:22:24 -0800827
828 try {
829 // wait for the messages to be handled
830 sm3.wait();
831 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800832 tloge("testStateMachine3: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -0800833 }
834 }
835
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700836 assertEquals(2, sm3.getLogRecSize());
Wink Savillefc5b4802009-12-08 21:22:24 -0800837
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700838 LogRec lr;
839 lr = sm3.getLogRec(0);
840 assertEquals(TEST_CMD_1, lr.getWhat());
841 assertEquals(sm3.mParentState, lr.getState());
842 assertEquals(sm3.mChildState, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800843
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700844 lr = sm3.getLogRec(1);
845 assertEquals(TEST_CMD_2, lr.getWhat());
846 assertEquals(sm3.mParentState, lr.getState());
847 assertEquals(sm3.mChildState, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800848
Wink Savilleefcc3d32013-01-30 11:21:22 -0800849 if (sm3.isDbg()) tlog("testStateMachine3 X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800850 }
851
852 /**
853 * Test a hierarchy of 3 states a parent and two children
854 * with transition from child 1 to child 2 and child 2
855 * lets the parent handle the messages.
856 */
Wink Saville64c42ca2011-04-18 14:55:10 -0700857 class StateMachine4 extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -0800858 StateMachine4(String name) {
859 super(name);
860 mThisSm = this;
861 setDbg(DBG);
862
863 // Setup a hierarchy of three states
864 // mParentState, mChildState1 & mChildState2
865 // (Use indentation to help visualize hierarchy)
866 addState(mParentState);
867 addState(mChildState1, mParentState);
868 addState(mChildState2, mParentState);
869
870 // Set the initial state will be child 1
871 setInitialState(mChildState1);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800872 if (DBG) log("StateMachine4: ctor X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800873 }
874
Wink Saville64c42ca2011-04-18 14:55:10 -0700875 class ParentState extends State {
876 @Override
877 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -0800878 if (message.what == TEST_CMD_2) {
879 transitionToHaltingState();
880 }
Wink Savillea4f3bec2010-05-19 09:11:38 -0700881 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800882 }
883 }
884
Wink Saville64c42ca2011-04-18 14:55:10 -0700885 class ChildState1 extends State {
886 @Override
887 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -0800888 transitionTo(mChildState2);
Wink Savillea4f3bec2010-05-19 09:11:38 -0700889 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800890 }
891 }
892
Wink Saville64c42ca2011-04-18 14:55:10 -0700893 class ChildState2 extends State {
894 @Override
895 public boolean processMessage(Message message) {
Wink Savillea4f3bec2010-05-19 09:11:38 -0700896 return NOT_HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -0800897 }
898 }
899
900 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700901 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800902 synchronized (mThisSm) {
903 mThisSm.notifyAll();
904 }
905 }
906
907 private StateMachine4 mThisSm;
908 private ParentState mParentState = new ParentState();
909 private ChildState1 mChildState1 = new ChildState1();
910 private ChildState2 mChildState2 = new ChildState2();
911 }
912
Brett Chabotf76c56b2010-07-26 17:28:17 -0700913 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -0800914 public void testStateMachine4() throws Exception {
915 StateMachine4 sm4 = new StateMachine4("sm4");
916 sm4.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -0800917 if (sm4.isDbg()) tlog("testStateMachine4 E");
Wink Savillefc5b4802009-12-08 21:22:24 -0800918
919 synchronized (sm4) {
920 // Send two messages
Wink Saville91fbd562010-03-17 17:12:43 -0700921 sm4.sendMessage(TEST_CMD_1);
922 sm4.sendMessage(TEST_CMD_2);
Wink Savillefc5b4802009-12-08 21:22:24 -0800923
924 try {
925 // wait for the messages to be handled
926 sm4.wait();
927 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -0800928 tloge("testStateMachine4: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -0800929 }
930 }
931
932
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700933 assertEquals(2, sm4.getLogRecSize());
Wink Savillefc5b4802009-12-08 21:22:24 -0800934
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700935 LogRec lr;
936 lr = sm4.getLogRec(0);
937 assertEquals(TEST_CMD_1, lr.getWhat());
938 assertEquals(sm4.mChildState1, lr.getState());
939 assertEquals(sm4.mChildState1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800940
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700941 lr = sm4.getLogRec(1);
942 assertEquals(TEST_CMD_2, lr.getWhat());
943 assertEquals(sm4.mParentState, lr.getState());
944 assertEquals(sm4.mChildState2, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -0800945
Wink Savilleefcc3d32013-01-30 11:21:22 -0800946 if (sm4.isDbg()) tlog("testStateMachine4 X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800947 }
948
949 /**
950 * Test transition from one child to another of a "complex"
951 * hierarchy with two parents and multiple children.
952 */
Wink Saville64c42ca2011-04-18 14:55:10 -0700953 class StateMachine5 extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -0800954 StateMachine5(String name) {
955 super(name);
956 mThisSm = this;
957 setDbg(DBG);
958
959 // Setup a hierarchy with two parents and some children.
960 // (Use indentation to help visualize hierarchy)
961 addState(mParentState1);
962 addState(mChildState1, mParentState1);
963 addState(mChildState2, mParentState1);
964
965 addState(mParentState2);
966 addState(mChildState3, mParentState2);
967 addState(mChildState4, mParentState2);
968 addState(mChildState5, mChildState4);
969
970 // Set the initial state will be the child
971 setInitialState(mChildState1);
Wink Savilleefcc3d32013-01-30 11:21:22 -0800972 if (DBG) log("StateMachine5: ctor X");
Wink Savillefc5b4802009-12-08 21:22:24 -0800973 }
974
Wink Saville64c42ca2011-04-18 14:55:10 -0700975 class ParentState1 extends State {
976 @Override
977 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800978 mParentState1EnterCount += 1;
979 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700980 @Override
981 public void exit() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800982 mParentState1ExitCount += 1;
983 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700984 @Override
985 public boolean processMessage(Message message) {
986 return HANDLED;
987 }
Wink Savillefc5b4802009-12-08 21:22:24 -0800988 }
989
Wink Saville64c42ca2011-04-18 14:55:10 -0700990 class ChildState1 extends State {
991 @Override
992 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -0800993 mChildState1EnterCount += 1;
994 }
Wink Saville64c42ca2011-04-18 14:55:10 -0700995 @Override
996 public void exit() {
997 mChildState1ExitCount += 1;
998 }
999 @Override
1000 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001001 assertEquals(1, mParentState1EnterCount);
1002 assertEquals(0, mParentState1ExitCount);
1003 assertEquals(1, mChildState1EnterCount);
1004 assertEquals(0, mChildState1ExitCount);
1005 assertEquals(0, mChildState2EnterCount);
1006 assertEquals(0, mChildState2ExitCount);
1007 assertEquals(0, mParentState2EnterCount);
1008 assertEquals(0, mParentState2ExitCount);
1009 assertEquals(0, mChildState3EnterCount);
1010 assertEquals(0, mChildState3ExitCount);
1011 assertEquals(0, mChildState4EnterCount);
1012 assertEquals(0, mChildState4ExitCount);
1013 assertEquals(0, mChildState5EnterCount);
1014 assertEquals(0, mChildState5ExitCount);
1015
1016 transitionTo(mChildState2);
Wink Savillea4f3bec2010-05-19 09:11:38 -07001017 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001018 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001019 }
1020
Wink Saville64c42ca2011-04-18 14:55:10 -07001021 class ChildState2 extends State {
1022 @Override
1023 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001024 mChildState2EnterCount += 1;
1025 }
Wink Saville64c42ca2011-04-18 14:55:10 -07001026 @Override
1027 public void exit() {
1028 mChildState2ExitCount += 1;
1029 }
1030 @Override
1031 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001032 assertEquals(1, mParentState1EnterCount);
1033 assertEquals(0, mParentState1ExitCount);
1034 assertEquals(1, mChildState1EnterCount);
1035 assertEquals(1, mChildState1ExitCount);
1036 assertEquals(1, mChildState2EnterCount);
1037 assertEquals(0, mChildState2ExitCount);
1038 assertEquals(0, mParentState2EnterCount);
1039 assertEquals(0, mParentState2ExitCount);
1040 assertEquals(0, mChildState3EnterCount);
1041 assertEquals(0, mChildState3ExitCount);
1042 assertEquals(0, mChildState4EnterCount);
1043 assertEquals(0, mChildState4ExitCount);
1044 assertEquals(0, mChildState5EnterCount);
1045 assertEquals(0, mChildState5ExitCount);
1046
1047 transitionTo(mChildState5);
Wink Savillea4f3bec2010-05-19 09:11:38 -07001048 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001049 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001050 }
1051
Wink Saville64c42ca2011-04-18 14:55:10 -07001052 class ParentState2 extends State {
1053 @Override
1054 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001055 mParentState2EnterCount += 1;
1056 }
Wink Saville64c42ca2011-04-18 14:55:10 -07001057 @Override
1058 public void exit() {
1059 mParentState2ExitCount += 1;
1060 }
1061 @Override
1062 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001063 assertEquals(1, mParentState1EnterCount);
1064 assertEquals(1, mParentState1ExitCount);
1065 assertEquals(1, mChildState1EnterCount);
1066 assertEquals(1, mChildState1ExitCount);
1067 assertEquals(1, mChildState2EnterCount);
1068 assertEquals(1, mChildState2ExitCount);
1069 assertEquals(2, mParentState2EnterCount);
1070 assertEquals(1, mParentState2ExitCount);
1071 assertEquals(1, mChildState3EnterCount);
1072 assertEquals(1, mChildState3ExitCount);
1073 assertEquals(2, mChildState4EnterCount);
1074 assertEquals(2, mChildState4ExitCount);
1075 assertEquals(1, mChildState5EnterCount);
1076 assertEquals(1, mChildState5ExitCount);
1077
1078 transitionToHaltingState();
Wink Savillea4f3bec2010-05-19 09:11:38 -07001079 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001080 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001081 }
1082
Wink Saville64c42ca2011-04-18 14:55:10 -07001083 class ChildState3 extends State {
1084 @Override
1085 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001086 mChildState3EnterCount += 1;
1087 }
Wink Saville64c42ca2011-04-18 14:55:10 -07001088 @Override
1089 public void exit() {
1090 mChildState3ExitCount += 1;
1091 }
1092 @Override
1093 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001094 assertEquals(1, mParentState1EnterCount);
1095 assertEquals(1, mParentState1ExitCount);
1096 assertEquals(1, mChildState1EnterCount);
1097 assertEquals(1, mChildState1ExitCount);
1098 assertEquals(1, mChildState2EnterCount);
1099 assertEquals(1, mChildState2ExitCount);
1100 assertEquals(1, mParentState2EnterCount);
1101 assertEquals(0, mParentState2ExitCount);
1102 assertEquals(1, mChildState3EnterCount);
1103 assertEquals(0, mChildState3ExitCount);
1104 assertEquals(1, mChildState4EnterCount);
1105 assertEquals(1, mChildState4ExitCount);
1106 assertEquals(1, mChildState5EnterCount);
1107 assertEquals(1, mChildState5ExitCount);
1108
1109 transitionTo(mChildState4);
Wink Savillea4f3bec2010-05-19 09:11:38 -07001110 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001111 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001112 }
1113
Wink Saville64c42ca2011-04-18 14:55:10 -07001114 class ChildState4 extends State {
1115 @Override
1116 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001117 mChildState4EnterCount += 1;
1118 }
Wink Saville64c42ca2011-04-18 14:55:10 -07001119 @Override
1120 public void exit() {
1121 mChildState4ExitCount += 1;
1122 }
1123 @Override
1124 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001125 assertEquals(1, mParentState1EnterCount);
1126 assertEquals(1, mParentState1ExitCount);
1127 assertEquals(1, mChildState1EnterCount);
1128 assertEquals(1, mChildState1ExitCount);
1129 assertEquals(1, mChildState2EnterCount);
1130 assertEquals(1, mChildState2ExitCount);
1131 assertEquals(1, mParentState2EnterCount);
1132 assertEquals(0, mParentState2ExitCount);
1133 assertEquals(1, mChildState3EnterCount);
1134 assertEquals(1, mChildState3ExitCount);
1135 assertEquals(2, mChildState4EnterCount);
1136 assertEquals(1, mChildState4ExitCount);
1137 assertEquals(1, mChildState5EnterCount);
1138 assertEquals(1, mChildState5ExitCount);
1139
1140 transitionTo(mParentState2);
Wink Savillea4f3bec2010-05-19 09:11:38 -07001141 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001142 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001143 }
1144
Wink Saville64c42ca2011-04-18 14:55:10 -07001145 class ChildState5 extends State {
1146 @Override
1147 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001148 mChildState5EnterCount += 1;
1149 }
Wink Saville64c42ca2011-04-18 14:55:10 -07001150 @Override
1151 public void exit() {
1152 mChildState5ExitCount += 1;
1153 }
1154 @Override
1155 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001156 assertEquals(1, mParentState1EnterCount);
1157 assertEquals(1, mParentState1ExitCount);
1158 assertEquals(1, mChildState1EnterCount);
1159 assertEquals(1, mChildState1ExitCount);
1160 assertEquals(1, mChildState2EnterCount);
1161 assertEquals(1, mChildState2ExitCount);
1162 assertEquals(1, mParentState2EnterCount);
1163 assertEquals(0, mParentState2ExitCount);
1164 assertEquals(0, mChildState3EnterCount);
1165 assertEquals(0, mChildState3ExitCount);
1166 assertEquals(1, mChildState4EnterCount);
1167 assertEquals(0, mChildState4ExitCount);
1168 assertEquals(1, mChildState5EnterCount);
1169 assertEquals(0, mChildState5ExitCount);
1170
1171 transitionTo(mChildState3);
Wink Savillea4f3bec2010-05-19 09:11:38 -07001172 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001173 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001174 }
1175
1176 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001177 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001178 synchronized (mThisSm) {
1179 mThisSm.notifyAll();
1180 }
1181 }
1182
1183 private StateMachine5 mThisSm;
1184 private ParentState1 mParentState1 = new ParentState1();
1185 private ChildState1 mChildState1 = new ChildState1();
1186 private ChildState2 mChildState2 = new ChildState2();
1187 private ParentState2 mParentState2 = new ParentState2();
1188 private ChildState3 mChildState3 = new ChildState3();
1189 private ChildState4 mChildState4 = new ChildState4();
1190 private ChildState5 mChildState5 = new ChildState5();
1191
1192 private int mParentState1EnterCount = 0;
1193 private int mParentState1ExitCount = 0;
1194 private int mChildState1EnterCount = 0;
1195 private int mChildState1ExitCount = 0;
1196 private int mChildState2EnterCount = 0;
1197 private int mChildState2ExitCount = 0;
1198 private int mParentState2EnterCount = 0;
1199 private int mParentState2ExitCount = 0;
1200 private int mChildState3EnterCount = 0;
1201 private int mChildState3ExitCount = 0;
1202 private int mChildState4EnterCount = 0;
1203 private int mChildState4ExitCount = 0;
1204 private int mChildState5EnterCount = 0;
1205 private int mChildState5ExitCount = 0;
1206 }
1207
Brett Chabotf76c56b2010-07-26 17:28:17 -07001208 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -08001209 public void testStateMachine5() throws Exception {
1210 StateMachine5 sm5 = new StateMachine5("sm5");
1211 sm5.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -08001212 if (sm5.isDbg()) tlog("testStateMachine5 E");
Wink Savillefc5b4802009-12-08 21:22:24 -08001213
1214 synchronized (sm5) {
1215 // Send 6 messages
Wink Saville91fbd562010-03-17 17:12:43 -07001216 sm5.sendMessage(TEST_CMD_1);
1217 sm5.sendMessage(TEST_CMD_2);
1218 sm5.sendMessage(TEST_CMD_3);
1219 sm5.sendMessage(TEST_CMD_4);
1220 sm5.sendMessage(TEST_CMD_5);
1221 sm5.sendMessage(TEST_CMD_6);
Wink Savillefc5b4802009-12-08 21:22:24 -08001222
1223 try {
1224 // wait for the messages to be handled
1225 sm5.wait();
1226 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001227 tloge("testStateMachine5: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -08001228 }
1229 }
1230
1231
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001232 assertEquals(6, sm5.getLogRecSize());
Wink Savillefc5b4802009-12-08 21:22:24 -08001233
1234 assertEquals(1, sm5.mParentState1EnterCount);
1235 assertEquals(1, sm5.mParentState1ExitCount);
1236 assertEquals(1, sm5.mChildState1EnterCount);
1237 assertEquals(1, sm5.mChildState1ExitCount);
1238 assertEquals(1, sm5.mChildState2EnterCount);
1239 assertEquals(1, sm5.mChildState2ExitCount);
1240 assertEquals(2, sm5.mParentState2EnterCount);
1241 assertEquals(2, sm5.mParentState2ExitCount);
1242 assertEquals(1, sm5.mChildState3EnterCount);
1243 assertEquals(1, sm5.mChildState3ExitCount);
1244 assertEquals(2, sm5.mChildState4EnterCount);
1245 assertEquals(2, sm5.mChildState4ExitCount);
1246 assertEquals(1, sm5.mChildState5EnterCount);
1247 assertEquals(1, sm5.mChildState5ExitCount);
1248
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001249 LogRec lr;
1250 lr = sm5.getLogRec(0);
1251 assertEquals(TEST_CMD_1, lr.getWhat());
1252 assertEquals(sm5.mChildState1, lr.getState());
1253 assertEquals(sm5.mChildState1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001254
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001255 lr = sm5.getLogRec(1);
1256 assertEquals(TEST_CMD_2, lr.getWhat());
1257 assertEquals(sm5.mChildState2, lr.getState());
1258 assertEquals(sm5.mChildState2, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001259
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001260 lr = sm5.getLogRec(2);
1261 assertEquals(TEST_CMD_3, lr.getWhat());
1262 assertEquals(sm5.mChildState5, lr.getState());
1263 assertEquals(sm5.mChildState5, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001264
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001265 lr = sm5.getLogRec(3);
1266 assertEquals(TEST_CMD_4, lr.getWhat());
1267 assertEquals(sm5.mChildState3, lr.getState());
1268 assertEquals(sm5.mChildState3, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001269
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001270 lr = sm5.getLogRec(4);
1271 assertEquals(TEST_CMD_5, lr.getWhat());
1272 assertEquals(sm5.mChildState4, lr.getState());
1273 assertEquals(sm5.mChildState4, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001274
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001275 lr = sm5.getLogRec(5);
1276 assertEquals(TEST_CMD_6, lr.getWhat());
1277 assertEquals(sm5.mParentState2, lr.getState());
1278 assertEquals(sm5.mParentState2, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001279
Wink Savilleefcc3d32013-01-30 11:21:22 -08001280 if (sm5.isDbg()) tlog("testStateMachine5 X");
Wink Savillefc5b4802009-12-08 21:22:24 -08001281 }
1282
1283 /**
1284 * Test that the initial state enter is invoked immediately
1285 * after construction and before any other messages arrive and that
1286 * sendMessageDelayed works.
1287 */
Wink Saville64c42ca2011-04-18 14:55:10 -07001288 class StateMachine6 extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -08001289 StateMachine6(String name) {
1290 super(name);
1291 mThisSm = this;
1292 setDbg(DBG);
1293
1294 // Setup state machine with 1 state
1295 addState(mS1);
1296
1297 // Set the initial state
1298 setInitialState(mS1);
Wink Savilleefcc3d32013-01-30 11:21:22 -08001299 if (DBG) log("StateMachine6: ctor X");
Wink Savillefc5b4802009-12-08 21:22:24 -08001300 }
1301
Wink Saville64c42ca2011-04-18 14:55:10 -07001302 class S1 extends State {
1303 @Override
1304 public void enter() {
Wink Saville91fbd562010-03-17 17:12:43 -07001305 sendMessage(TEST_CMD_1);
Wink Savillefc5b4802009-12-08 21:22:24 -08001306 }
Wink Saville64c42ca2011-04-18 14:55:10 -07001307 @Override
1308 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001309 if (message.what == TEST_CMD_1) {
1310 mArrivalTimeMsg1 = SystemClock.elapsedRealtime();
1311 } else if (message.what == TEST_CMD_2) {
1312 mArrivalTimeMsg2 = SystemClock.elapsedRealtime();
1313 transitionToHaltingState();
1314 }
Wink Savillea4f3bec2010-05-19 09:11:38 -07001315 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001316 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001317 }
1318
1319 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001320 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001321 synchronized (mThisSm) {
1322 mThisSm.notifyAll();
1323 }
1324 }
1325
1326 private StateMachine6 mThisSm;
1327 private S1 mS1 = new S1();
1328
1329 private long mArrivalTimeMsg1;
1330 private long mArrivalTimeMsg2;
1331 }
1332
Brett Chabotf76c56b2010-07-26 17:28:17 -07001333 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -08001334 public void testStateMachine6() throws Exception {
Wink Savillefc5b4802009-12-08 21:22:24 -08001335 final int DELAY_TIME = 250;
1336 final int DELAY_FUDGE = 20;
1337
1338 StateMachine6 sm6 = new StateMachine6("sm6");
1339 sm6.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -08001340 if (sm6.isDbg()) tlog("testStateMachine6 E");
Wink Savillefc5b4802009-12-08 21:22:24 -08001341
1342 synchronized (sm6) {
1343 // Send a message
Wink Saville91fbd562010-03-17 17:12:43 -07001344 sm6.sendMessageDelayed(TEST_CMD_2, DELAY_TIME);
Wink Savillefc5b4802009-12-08 21:22:24 -08001345
1346 try {
1347 // wait for the messages to be handled
1348 sm6.wait();
1349 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001350 tloge("testStateMachine6: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -08001351 }
1352 }
1353
1354 /**
1355 * TEST_CMD_1 was sent in enter and must always have been processed
1356 * immediately after construction and hence the arrival time difference
1357 * should always >= to the DELAY_TIME
1358 */
1359 long arrivalTimeDiff = sm6.mArrivalTimeMsg2 - sm6.mArrivalTimeMsg1;
1360 long expectedDelay = DELAY_TIME - DELAY_FUDGE;
Wink Savilleefcc3d32013-01-30 11:21:22 -08001361 if (sm6.isDbg()) tlog("testStateMachine6: expect " + arrivalTimeDiff
Wink Savillefc5b4802009-12-08 21:22:24 -08001362 + " >= " + expectedDelay);
1363 assertTrue(arrivalTimeDiff >= expectedDelay);
1364
Wink Savilleefcc3d32013-01-30 11:21:22 -08001365 if (sm6.isDbg()) tlog("testStateMachine6 X");
Wink Savillefc5b4802009-12-08 21:22:24 -08001366 }
1367
1368 /**
1369 * Test that enter is invoked immediately after exit. This validates
1370 * that enter can be used to send a watch dog message for its state.
1371 */
Wink Saville64c42ca2011-04-18 14:55:10 -07001372 class StateMachine7 extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -08001373 private final int SM7_DELAY_TIME = 250;
1374
1375 StateMachine7(String name) {
1376 super(name);
1377 mThisSm = this;
1378 setDbg(DBG);
1379
1380 // Setup state machine with 1 state
1381 addState(mS1);
1382 addState(mS2);
1383
1384 // Set the initial state
1385 setInitialState(mS1);
Wink Savilleefcc3d32013-01-30 11:21:22 -08001386 if (DBG) log("StateMachine7: ctor X");
Wink Savillefc5b4802009-12-08 21:22:24 -08001387 }
1388
Wink Saville64c42ca2011-04-18 14:55:10 -07001389 class S1 extends State {
1390 @Override
1391 public void exit() {
1392 sendMessage(TEST_CMD_2);
1393 }
1394 @Override
1395 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001396 transitionTo(mS2);
Wink Savillea4f3bec2010-05-19 09:11:38 -07001397 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001398 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001399 }
1400
Wink Saville64c42ca2011-04-18 14:55:10 -07001401 class S2 extends State {
1402 @Override
1403 public void enter() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001404 // Send a delayed message as a watch dog
Wink Saville91fbd562010-03-17 17:12:43 -07001405 sendMessageDelayed(TEST_CMD_3, SM7_DELAY_TIME);
Wink Savillefc5b4802009-12-08 21:22:24 -08001406 }
Wink Saville64c42ca2011-04-18 14:55:10 -07001407 @Override
1408 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001409 if (message.what == TEST_CMD_2) {
1410 mMsgCount += 1;
1411 mArrivalTimeMsg2 = SystemClock.elapsedRealtime();
1412 } else if (message.what == TEST_CMD_3) {
1413 mMsgCount += 1;
1414 mArrivalTimeMsg3 = SystemClock.elapsedRealtime();
1415 }
1416
1417 if (mMsgCount == 2) {
1418 transitionToHaltingState();
1419 }
Wink Savillea4f3bec2010-05-19 09:11:38 -07001420 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001421 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001422 }
1423
1424 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001425 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001426 synchronized (mThisSm) {
1427 mThisSm.notifyAll();
1428 }
1429 }
1430
1431 private StateMachine7 mThisSm;
1432 private S1 mS1 = new S1();
1433 private S2 mS2 = new S2();
1434
1435 private int mMsgCount = 0;
1436 private long mArrivalTimeMsg2;
1437 private long mArrivalTimeMsg3;
1438 }
1439
Brett Chabotf76c56b2010-07-26 17:28:17 -07001440 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -08001441 public void testStateMachine7() throws Exception {
Wink Savillefc5b4802009-12-08 21:22:24 -08001442 final int SM7_DELAY_FUDGE = 20;
1443
1444 StateMachine7 sm7 = new StateMachine7("sm7");
1445 sm7.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -08001446 if (sm7.isDbg()) tlog("testStateMachine7 E");
Wink Savillefc5b4802009-12-08 21:22:24 -08001447
1448 synchronized (sm7) {
1449 // Send a message
Wink Saville91fbd562010-03-17 17:12:43 -07001450 sm7.sendMessage(TEST_CMD_1);
Wink Savillefc5b4802009-12-08 21:22:24 -08001451
1452 try {
1453 // wait for the messages to be handled
1454 sm7.wait();
1455 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001456 tloge("testStateMachine7: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -08001457 }
1458 }
1459
1460 /**
1461 * TEST_CMD_3 was sent in S2.enter with a delay and must always have been
1462 * processed immediately after S1.exit. Since S1.exit sent TEST_CMD_2
1463 * without a delay the arrival time difference should always >= to SM7_DELAY_TIME.
1464 */
1465 long arrivalTimeDiff = sm7.mArrivalTimeMsg3 - sm7.mArrivalTimeMsg2;
1466 long expectedDelay = sm7.SM7_DELAY_TIME - SM7_DELAY_FUDGE;
Wink Savilleefcc3d32013-01-30 11:21:22 -08001467 if (sm7.isDbg()) tlog("testStateMachine7: expect " + arrivalTimeDiff
Wink Savillefc5b4802009-12-08 21:22:24 -08001468 + " >= " + expectedDelay);
1469 assertTrue(arrivalTimeDiff >= expectedDelay);
1470
Wink Savilleefcc3d32013-01-30 11:21:22 -08001471 if (sm7.isDbg()) tlog("testStateMachine7 X");
Wink Savillefc5b4802009-12-08 21:22:24 -08001472 }
1473
1474 /**
1475 * Test unhandledMessage.
1476 */
Wink Saville64c42ca2011-04-18 14:55:10 -07001477 class StateMachineUnhandledMessage extends StateMachine {
Wink Savillefc5b4802009-12-08 21:22:24 -08001478 StateMachineUnhandledMessage(String name) {
1479 super(name);
1480 mThisSm = this;
1481 setDbg(DBG);
1482
1483 // Setup state machine with 1 state
1484 addState(mS1);
1485
1486 // Set the initial state
1487 setInitialState(mS1);
1488 }
Wink Saville64c42ca2011-04-18 14:55:10 -07001489 @Override
1490 public void unhandledMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001491 mUnhandledMessageCount += 1;
1492 }
1493
Wink Saville64c42ca2011-04-18 14:55:10 -07001494 class S1 extends State {
1495 @Override
1496 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001497 if (message.what == TEST_CMD_2) {
1498 transitionToHaltingState();
1499 }
Wink Savillea4f3bec2010-05-19 09:11:38 -07001500 return NOT_HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001501 }
1502 }
1503
1504 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001505 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001506 synchronized (mThisSm) {
1507 mThisSm.notifyAll();
1508 }
1509 }
1510
1511 private StateMachineUnhandledMessage mThisSm;
1512 private int mUnhandledMessageCount;
1513 private S1 mS1 = new S1();
1514 }
1515
1516 @SmallTest
1517 public void testStateMachineUnhandledMessage() throws Exception {
1518
Wink Savilleefcc3d32013-01-30 11:21:22 -08001519 StateMachineUnhandledMessage sm = new StateMachineUnhandledMessage("smUnhandledMessage");
Wink Savillefc5b4802009-12-08 21:22:24 -08001520 sm.start();
Wink Savilleefcc3d32013-01-30 11:21:22 -08001521 if (sm.isDbg()) tlog("testStateMachineUnhandledMessage E");
Wink Savillefc5b4802009-12-08 21:22:24 -08001522
1523 synchronized (sm) {
1524 // Send 2 messages
1525 for (int i = 1; i <= 2; i++) {
Wink Saville91fbd562010-03-17 17:12:43 -07001526 sm.sendMessage(i);
Wink Savillefc5b4802009-12-08 21:22:24 -08001527 }
1528
1529 try {
1530 // wait for the messages to be handled
1531 sm.wait();
1532 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001533 tloge("testStateMachineUnhandledMessage: exception while waiting "
Wink Savillefc5b4802009-12-08 21:22:24 -08001534 + e.getMessage());
1535 }
1536 }
1537
Wink Savilleefcc3d32013-01-30 11:21:22 -08001538 assertEquals(2, sm.getLogRecSize());
Wink Savillefc5b4802009-12-08 21:22:24 -08001539 assertEquals(2, sm.mUnhandledMessageCount);
1540
Wink Savilleefcc3d32013-01-30 11:21:22 -08001541 if (sm.isDbg()) tlog("testStateMachineUnhandledMessage X");
Wink Savillefc5b4802009-12-08 21:22:24 -08001542 }
1543
1544 /**
1545 * Test state machines sharing the same thread/looper. Multiple instances
1546 * of the same state machine will be created. They will all share the
1547 * same thread and thus each can update <code>sharedCounter</code> which
1548 * will be used to notify testStateMachineSharedThread that the test is
1549 * complete.
1550 */
Wink Saville64c42ca2011-04-18 14:55:10 -07001551 class StateMachineSharedThread extends StateMachine {
Wink Savillef0f566e2010-03-11 14:03:50 -08001552 StateMachineSharedThread(String name, Looper looper, int maxCount) {
1553 super(name, looper);
Wink Savillefc5b4802009-12-08 21:22:24 -08001554 mMaxCount = maxCount;
1555 setDbg(DBG);
1556
1557 // Setup state machine with 1 state
1558 addState(mS1);
1559
1560 // Set the initial state
1561 setInitialState(mS1);
1562 }
1563
Wink Saville64c42ca2011-04-18 14:55:10 -07001564 class S1 extends State {
1565 @Override
1566 public boolean processMessage(Message message) {
Wink Savillefc5b4802009-12-08 21:22:24 -08001567 if (message.what == TEST_CMD_4) {
1568 transitionToHaltingState();
1569 }
Wink Savillea4f3bec2010-05-19 09:11:38 -07001570 return HANDLED;
Wink Savillefc5b4802009-12-08 21:22:24 -08001571 }
1572 }
1573
1574 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001575 protected void onHalting() {
Wink Savillefc5b4802009-12-08 21:22:24 -08001576 // Update the shared counter, which is OK since all state
1577 // machines are using the same thread.
1578 sharedCounter += 1;
1579 if (sharedCounter == mMaxCount) {
1580 synchronized (waitObject) {
1581 waitObject.notifyAll();
1582 }
1583 }
1584 }
1585
1586 private int mMaxCount;
1587 private S1 mS1 = new S1();
1588 }
1589 private static int sharedCounter = 0;
1590 private static Object waitObject = new Object();
1591
Brett Chabotf76c56b2010-07-26 17:28:17 -07001592 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -08001593 public void testStateMachineSharedThread() throws Exception {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001594 if (DBG) tlog("testStateMachineSharedThread E");
Wink Savillefc5b4802009-12-08 21:22:24 -08001595
1596 // Create and start the handler thread
1597 HandlerThread smThread = new HandlerThread("testStateMachineSharedThread");
1598 smThread.start();
1599
1600 // Create the state machines
1601 StateMachineSharedThread sms[] = new StateMachineSharedThread[10];
1602 for (int i = 0; i < sms.length; i++) {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001603 sms[i] = new StateMachineSharedThread("smSharedThread",
1604 smThread.getLooper(), sms.length);
Wink Savillefc5b4802009-12-08 21:22:24 -08001605 sms[i].start();
1606 }
1607
1608 synchronized (waitObject) {
1609 // Send messages to each of the state machines
1610 for (StateMachineSharedThread sm : sms) {
1611 for (int i = 1; i <= 4; i++) {
Wink Saville91fbd562010-03-17 17:12:43 -07001612 sm.sendMessage(i);
Wink Savillefc5b4802009-12-08 21:22:24 -08001613 }
1614 }
1615
1616 // Wait for the last state machine to notify its done
1617 try {
1618 waitObject.wait();
1619 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001620 tloge("testStateMachineSharedThread: exception while waiting "
Wink Savillefc5b4802009-12-08 21:22:24 -08001621 + e.getMessage());
1622 }
1623 }
1624
1625 for (StateMachineSharedThread sm : sms) {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001626 assertEquals(4, sm.getLogRecCount());
1627 for (int i = 0; i < sm.getLogRecSize(); i++) {
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001628 LogRec lr = sm.getLogRec(i);
1629 assertEquals(i+1, lr.getWhat());
1630 assertEquals(sm.mS1, lr.getState());
1631 assertEquals(sm.mS1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001632 }
1633 }
1634
Wink Savilleefcc3d32013-01-30 11:21:22 -08001635 if (DBG) tlog("testStateMachineSharedThread X");
1636 }
1637
1638 static class Hsm1 extends StateMachine {
1639 private static final String HSM1_TAG = "hsm1";
1640
1641 public static final int CMD_1 = 1;
1642 public static final int CMD_2 = 2;
1643 public static final int CMD_3 = 3;
1644 public static final int CMD_4 = 4;
1645 public static final int CMD_5 = 5;
1646
1647 public static Hsm1 makeHsm1() {
1648 Log.d(HSM1_TAG, "makeHsm1 E");
1649 Hsm1 sm = new Hsm1(HSM1_TAG);
1650 sm.start();
1651 Log.d(HSM1_TAG, "makeHsm1 X");
1652 return sm;
1653 }
1654
1655 Hsm1(String name) {
1656 super(name);
1657 log("ctor E");
1658
1659 // Add states, use indentation to show hierarchy
1660 addState(mP1);
1661 addState(mS1, mP1);
1662 addState(mS2, mP1);
1663 addState(mP2);
1664
1665 // Set the initial state
1666 setInitialState(mS1);
1667 log("ctor X");
1668 }
1669
1670 class P1 extends State {
1671 @Override
1672 public void enter() {
1673 log("P1.enter");
1674 }
1675 @Override
1676 public void exit() {
1677 log("P1.exit");
1678 }
1679 @Override
1680 public boolean processMessage(Message message) {
1681 boolean retVal;
1682 log("P1.processMessage what=" + message.what);
1683 switch(message.what) {
1684 case CMD_2:
1685 // CMD_2 will arrive in mS2 before CMD_3
1686 sendMessage(CMD_3);
1687 deferMessage(message);
1688 transitionTo(mS2);
1689 retVal = true;
1690 break;
1691 default:
1692 // Any message we don't understand in this state invokes unhandledMessage
1693 retVal = false;
1694 break;
1695 }
1696 return retVal;
1697 }
1698 }
1699
1700 class S1 extends State {
1701 @Override
1702 public void enter() {
1703 log("S1.enter");
1704 }
1705 @Override
1706 public void exit() {
1707 log("S1.exit");
1708 }
1709 @Override
1710 public boolean processMessage(Message message) {
1711 log("S1.processMessage what=" + message.what);
1712 if (message.what == CMD_1) {
1713 // Transition to ourself to show that enter/exit is called
1714 transitionTo(mS1);
1715 return HANDLED;
1716 } else {
1717 // Let parent process all other messages
1718 return NOT_HANDLED;
1719 }
1720 }
1721 }
1722
1723 class S2 extends State {
1724 @Override
1725 public void enter() {
1726 log("S2.enter");
1727 }
1728 @Override
1729 public void exit() {
1730 log("S2.exit");
1731 }
1732 @Override
1733 public boolean processMessage(Message message) {
1734 boolean retVal;
1735 log("S2.processMessage what=" + message.what);
1736 switch(message.what) {
1737 case(CMD_2):
1738 sendMessage(CMD_4);
1739 retVal = true;
1740 break;
1741 case(CMD_3):
1742 deferMessage(message);
1743 transitionTo(mP2);
1744 retVal = true;
1745 break;
1746 default:
1747 retVal = false;
1748 break;
1749 }
1750 return retVal;
1751 }
1752 }
1753
1754 class P2 extends State {
1755 @Override
1756 public void enter() {
1757 log("P2.enter");
1758 sendMessage(CMD_5);
1759 }
1760 @Override
1761 public void exit() {
1762 log("P2.exit");
1763 }
1764 @Override
1765 public boolean processMessage(Message message) {
1766 log("P2.processMessage what=" + message.what);
1767 switch(message.what) {
1768 case(CMD_3):
1769 break;
1770 case(CMD_4):
1771 break;
1772 case(CMD_5):
1773 transitionToHaltingState();
1774 break;
1775 }
1776 return HANDLED;
1777 }
1778 }
1779
1780 @Override
1781 protected void onHalting() {
1782 log("halting");
1783 synchronized (this) {
1784 this.notifyAll();
1785 }
1786 }
1787
1788 P1 mP1 = new P1();
1789 S1 mS1 = new S1();
1790 S2 mS2 = new S2();
1791 P2 mP2 = new P2();
Wink Savillefc5b4802009-12-08 21:22:24 -08001792 }
1793
Brett Chabotf76c56b2010-07-26 17:28:17 -07001794 @MediumTest
Wink Savillefc5b4802009-12-08 21:22:24 -08001795 public void testHsm1() throws Exception {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001796 if (DBG) tlog("testHsm1 E");
Wink Savillefc5b4802009-12-08 21:22:24 -08001797
1798 Hsm1 sm = Hsm1.makeHsm1();
1799
1800 // Send messages
Wink Saville91fbd562010-03-17 17:12:43 -07001801 sm.sendMessage(Hsm1.CMD_1);
1802 sm.sendMessage(Hsm1.CMD_2);
Wink Savillefc5b4802009-12-08 21:22:24 -08001803
1804 synchronized (sm) {
1805 // Wait for the last state machine to notify its done
1806 try {
1807 sm.wait();
1808 } catch (InterruptedException e) {
Wink Savilleefcc3d32013-01-30 11:21:22 -08001809 tloge("testHsm1: exception while waiting " + e.getMessage());
Wink Savillefc5b4802009-12-08 21:22:24 -08001810 }
1811 }
1812
Wink Savilleefcc3d32013-01-30 11:21:22 -08001813 dumpLogRecs(sm);
1814
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001815 assertEquals(7, sm.getLogRecCount());
Wink Savilleefcc3d32013-01-30 11:21:22 -08001816
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001817 LogRec lr = sm.getLogRec(0);
1818 assertEquals(Hsm1.CMD_1, lr.getWhat());
1819 assertEquals(sm.mS1, lr.getState());
1820 assertEquals(sm.mS1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001821
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001822 lr = sm.getLogRec(1);
1823 assertEquals(Hsm1.CMD_2, lr.getWhat());
1824 assertEquals(sm.mP1, lr.getState());
1825 assertEquals(sm.mS1, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001826
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001827 lr = sm.getLogRec(2);
1828 assertEquals(Hsm1.CMD_2, lr.getWhat());
1829 assertEquals(sm.mS2, lr.getState());
1830 assertEquals(sm.mS2, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001831
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001832 lr = sm.getLogRec(3);
1833 assertEquals(Hsm1.CMD_3, lr.getWhat());
1834 assertEquals(sm.mS2, lr.getState());
1835 assertEquals(sm.mS2, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001836
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001837 lr = sm.getLogRec(4);
1838 assertEquals(Hsm1.CMD_3, lr.getWhat());
1839 assertEquals(sm.mP2, lr.getState());
1840 assertEquals(sm.mP2, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001841
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001842 lr = sm.getLogRec(5);
1843 assertEquals(Hsm1.CMD_4, lr.getWhat());
1844 assertEquals(sm.mP2, lr.getState());
1845 assertEquals(sm.mP2, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001846
Wink Savillebbf30dfd2012-05-29 12:40:46 -07001847 lr = sm.getLogRec(6);
1848 assertEquals(Hsm1.CMD_5, lr.getWhat());
1849 assertEquals(sm.mP2, lr.getState());
1850 assertEquals(sm.mP2, lr.getOriginalState());
Wink Savillefc5b4802009-12-08 21:22:24 -08001851
Wink Savilleefcc3d32013-01-30 11:21:22 -08001852 if (DBG) tlog("testStateMachineSharedThread X");
Wink Savillefc5b4802009-12-08 21:22:24 -08001853 }
1854
Wink Savilleefcc3d32013-01-30 11:21:22 -08001855 private void tlog(String s) {
1856 Log.d(TAG, s);
Wink Savillefc5b4802009-12-08 21:22:24 -08001857 }
1858
Wink Savilleefcc3d32013-01-30 11:21:22 -08001859 private void tloge(String s) {
1860 Log.e(TAG, s);
Wink Savillefc5b4802009-12-08 21:22:24 -08001861 }
Wink Savillefc5b4802009-12-08 21:22:24 -08001862}