00001
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef StateMachine_cpp
00047 #define StateMachine_cpp
00048
00049 #include <cppunit/ui/text/TestRunner.h>
00050 #include <cppunit/TextOutputter.h>
00051 #include <cppunit/extensions/TestFactoryRegistry.h>
00052 #include <cppunit/extensions/HelperMacros.h>
00053 #include <cppunit/TestAssert.h>
00054
00055 #include <coil/TimeValue.h>
00056 #include <rtm/StateMachine.h>
00057
00062 namespace StateMachineTests
00063 {
00064 class StateMachineContext1
00065 {
00066 public:
00067 static const int STATE_1 = 0;
00068 static const int STATE_2 = 1;
00069 static const int STATE_3 = 2;
00070 static const int STATE_4 = 3;
00071 static const int STATE_5 = 4;
00072 static const int STATE_6 = 5;
00073 static const int SIZEOF_STATE = 6;
00074
00075 static const int ENTRY = 0;
00076 static const int PREDO = 1;
00077 static const int DO = 2;
00078 static const int POSTDO = 3;
00079 static const int EXIT = 4;
00080 static const int SIZEOF_ACTION = 5;
00081
00082 StateMachineContext1() : m_fsm(SIZEOF_STATE)
00083 {
00084 m_fsm.setListener(this);
00085
00086 m_fsm.setEntryAction(STATE_1, &StateMachineContext1::onEntry_STATE_1);
00087 m_fsm.setPreDoAction(STATE_1, &StateMachineContext1::onPreDo_STATE_1);
00088 m_fsm.setDoAction(STATE_1, &StateMachineContext1::onDo_STATE_1);
00089 m_fsm.setPostDoAction(STATE_1, &StateMachineContext1::onPostDo_STATE_1);
00090 m_fsm.setExitAction(STATE_1, &StateMachineContext1::onExit_STATE_1);
00091
00092 m_fsm.setEntryAction(STATE_2, &StateMachineContext1::onEntry_STATE_2);
00093 m_fsm.setPreDoAction(STATE_2, &StateMachineContext1::onPreDo_STATE_2);
00094 m_fsm.setDoAction(STATE_2, &StateMachineContext1::onDo_STATE_2);
00095 m_fsm.setPostDoAction(STATE_2, &StateMachineContext1::onPostDo_STATE_2);
00096 m_fsm.setExitAction(STATE_2, &StateMachineContext1::onExit_STATE_2);
00097
00098 m_fsm.setEntryAction(STATE_3, &StateMachineContext1::onEntry_STATE_3);
00099 m_fsm.setPreDoAction(STATE_3, &StateMachineContext1::onPreDo_STATE_3);
00100 m_fsm.setDoAction(STATE_3, &StateMachineContext1::onDo_STATE_3);
00101 m_fsm.setPostDoAction(STATE_3, &StateMachineContext1::onPostDo_STATE_3);
00102 m_fsm.setExitAction(STATE_3, &StateMachineContext1::onExit_STATE_3);
00103
00104 m_fsm.setEntryAction(STATE_4, &StateMachineContext1::onEntry_STATE_4);
00105 m_fsm.setPreDoAction(STATE_4, &StateMachineContext1::onPreDo_STATE_4);
00106 m_fsm.setDoAction(STATE_4, &StateMachineContext1::onDo_STATE_4);
00107 m_fsm.setPostDoAction(STATE_4, &StateMachineContext1::onPostDo_STATE_4);
00108 m_fsm.setExitAction(STATE_4, &StateMachineContext1::onExit_STATE_4);
00109
00110 m_fsm.setEntryAction(STATE_5, &StateMachineContext1::onEntry_STATE_5);
00111 m_fsm.setPreDoAction(STATE_5, &StateMachineContext1::onPreDo_STATE_5);
00112 m_fsm.setDoAction(STATE_5, &StateMachineContext1::onDo_STATE_5);
00113 m_fsm.setPostDoAction(STATE_5, &StateMachineContext1::onPostDo_STATE_5);
00114 m_fsm.setExitAction(STATE_5, &StateMachineContext1::onExit_STATE_5);
00115
00116 m_fsm.setEntryAction(STATE_6, &StateMachineContext1::onEntry_STATE_6);
00117 m_fsm.setPreDoAction(STATE_6, &StateMachineContext1::onPreDo_STATE_6);
00118 m_fsm.setDoAction(STATE_6, &StateMachineContext1::onDo_STATE_6);
00119 m_fsm.setPostDoAction(STATE_6, &StateMachineContext1::onPostDo_STATE_6);
00120 m_fsm.setExitAction(STATE_6, &StateMachineContext1::onExit_STATE_6);
00121
00122 RTC_Utils::StateHolder<int> initialStates;
00123 initialStates.prev = STATE_1;
00124 initialStates.curr = STATE_1;
00125 initialStates.next = STATE_1;
00126 m_fsm.setStartState(initialStates);
00127 }
00128
00129 void work()
00130 {
00131 for (int i = 0; i < 50; ++i)
00132 {
00133 m_fsm.worker();
00134 }
00135 }
00136
00137 void onEntry_STATE_1(const RTC_Utils::StateHolder<int>& states)
00138 {
00139 logCallback(STATE_1, ENTRY);
00140 }
00141 void onPreDo_STATE_1(const RTC_Utils::StateHolder<int>& states)
00142 {
00143 logCallback(STATE_1, PREDO);
00144 m_fsm.goTo(STATE_2);
00145 }
00146 void onDo_STATE_1(const RTC_Utils::StateHolder<int>& states)
00147 {
00148 logCallback(STATE_1, DO);
00149 }
00150 void onPostDo_STATE_1(const RTC_Utils::StateHolder<int>& states)
00151 {
00152 logCallback(STATE_1, POSTDO);
00153 }
00154 void onExit_STATE_1(const RTC_Utils::StateHolder<int>& states)
00155 {
00156 logCallback(STATE_1, EXIT);
00157 }
00158
00159 void onEntry_STATE_2(const RTC_Utils::StateHolder<int>& states)
00160 {
00161 logCallback(STATE_2, ENTRY);
00162 }
00163 void onPreDo_STATE_2(const RTC_Utils::StateHolder<int>& states)
00164 {
00165 logCallback(STATE_2, PREDO);
00166 }
00167
00168 void onDo_STATE_2(const RTC_Utils::StateHolder<int>& states)
00169 {
00170 logCallback(STATE_2, DO);
00171 m_fsm.goTo(STATE_3);
00172 }
00173 void onPostDo_STATE_2(const RTC_Utils::StateHolder<int>& states)
00174 {
00175 logCallback(STATE_2, POSTDO);
00176 }
00177 void onExit_STATE_2(const RTC_Utils::StateHolder<int>& states)
00178 {
00179 logCallback(STATE_2, EXIT);
00180 }
00181
00182 void onEntry_STATE_3(const RTC_Utils::StateHolder<int>& states)
00183 {
00184 logCallback(STATE_3, ENTRY);
00185 }
00186 void onPreDo_STATE_3(const RTC_Utils::StateHolder<int>& states)
00187 {
00188 logCallback(STATE_3, PREDO);
00189 }
00190 void onDo_STATE_3(const RTC_Utils::StateHolder<int>& states)
00191 {
00192 logCallback(STATE_3, DO);
00193 }
00194 void onPostDo_STATE_3(const RTC_Utils::StateHolder<int>& states)
00195 {
00196 logCallback(STATE_3, POSTDO);
00197 m_fsm.goTo(STATE_4);
00198 }
00199 void onExit_STATE_3(const RTC_Utils::StateHolder<int>& states)
00200 {
00201 logCallback(STATE_3, EXIT);
00202 }
00203
00204 void onEntry_STATE_4(const RTC_Utils::StateHolder<int>& states)
00205 {
00206 logCallback(STATE_4, ENTRY);
00207 m_fsm.goTo(STATE_5);
00208 }
00209 void onPreDo_STATE_4(const RTC_Utils::StateHolder<int>& states)
00210 {
00211 logCallback(STATE_4, PREDO);
00212 }
00213 void onDo_STATE_4(const RTC_Utils::StateHolder<int>& states)
00214 {
00215 logCallback(STATE_4, DO);
00216 }
00217 void onPostDo_STATE_4(const RTC_Utils::StateHolder<int>& states)
00218 {
00219 logCallback(STATE_4, POSTDO);
00220 }
00221 void onExit_STATE_4(const RTC_Utils::StateHolder<int>& states)
00222 {
00223 logCallback(STATE_4, EXIT);
00224 }
00225
00226 void onEntry_STATE_5(const RTC_Utils::StateHolder<int>& states)
00227 {
00228 logCallback(STATE_5, ENTRY);
00229 }
00230 void onPreDo_STATE_5(const RTC_Utils::StateHolder<int>& states)
00231 {
00232 logCallback(STATE_5, PREDO);
00233 }
00234 void onDo_STATE_5(const RTC_Utils::StateHolder<int>& states)
00235 {
00236 logCallback(STATE_5, DO);
00237 }
00238 void onPostDo_STATE_5(const RTC_Utils::StateHolder<int>& states)
00239 {
00240 logCallback(STATE_5, POSTDO);
00241 }
00242 void onExit_STATE_5(const RTC_Utils::StateHolder<int>& states)
00243 {
00244 logCallback(STATE_5, EXIT);
00245 m_fsm.goTo(STATE_6);
00246 }
00247
00248 void onEntry_STATE_6(const RTC_Utils::StateHolder<int>& states)
00249 {
00250 logCallback(STATE_6, ENTRY);
00251 }
00252 void onPreDo_STATE_6(const RTC_Utils::StateHolder<int>& states)
00253 {
00254 logCallback(STATE_6, PREDO);
00255 }
00256 void onDo_STATE_6(const RTC_Utils::StateHolder<int>& states)
00257 {
00258 logCallback(STATE_6, DO);
00259 }
00260 void onPostDo_STATE_6(const RTC_Utils::StateHolder<int>& states)
00261 {
00262 logCallback(STATE_6, POSTDO);
00263 }
00264 void onExit_STATE_6(const RTC_Utils::StateHolder<int>& states)
00265 {
00266 logCallback(STATE_6, EXIT);
00267 }
00268
00269 public:
00270 struct StateAndAction
00271 {
00272 int state;
00273 int action;
00274 };
00275
00276 const std::vector<StateAndAction>& getCallbackLog() const
00277 {
00278 return m_callbackLog;
00279 }
00280
00281 private:
00282 RTC_Utils::StateMachine<int, StateMachineContext1> m_fsm;
00283 std::vector<StateAndAction> m_callbackLog;
00284
00285 private:
00286 void logCallback(int state, int action)
00287 {
00288 StateAndAction sa;
00289 sa.state = state;
00290 sa.action = action;
00291 m_callbackLog.push_back(sa);
00292 }
00293 };
00294
00295 class StateMachineTests
00296 : public CppUnit::TestFixture
00297 {
00298 CPPUNIT_TEST_SUITE(StateMachineTests);
00299 CPPUNIT_TEST(test_transition_story1);
00300 CPPUNIT_TEST_SUITE_END();
00301
00302 private:
00303
00304 public:
00308 StateMachineTests()
00309 {
00310 }
00311
00315 ~StateMachineTests()
00316 {
00317 }
00318
00322 virtual void setUp()
00323 {
00324 }
00325
00329 virtual void tearDown()
00330 {
00331 }
00332
00344 void test_transition_story1()
00345 {
00346 typedef StateMachineContext1 SMC;
00347
00348 SMC::StateAndAction expected[] =
00349 {
00350 { SMC::STATE_1, SMC::PREDO },
00351 { SMC::STATE_1, SMC::EXIT },
00352 { SMC::STATE_2, SMC::ENTRY },
00353 { SMC::STATE_2, SMC::PREDO },
00354 { SMC::STATE_2, SMC::DO },
00355 { SMC::STATE_2, SMC::EXIT },
00356 { SMC::STATE_3, SMC::ENTRY },
00357 { SMC::STATE_3, SMC::PREDO },
00358 { SMC::STATE_3, SMC::DO },
00359 { SMC::STATE_3, SMC::POSTDO },
00360 { SMC::STATE_3, SMC::EXIT },
00361 { SMC::STATE_4, SMC::ENTRY },
00362 { SMC::STATE_4, SMC::EXIT },
00363 { SMC::STATE_5, SMC::ENTRY },
00364 { SMC::STATE_5, SMC::PREDO },
00365 { SMC::STATE_5, SMC::DO },
00366 { SMC::STATE_5, SMC::POSTDO },
00367 { SMC::STATE_5, SMC::PREDO }
00368 };
00369
00370 SMC context;
00371 context.work();
00372
00373 const std::vector<SMC::StateAndAction> log = context.getCallbackLog();
00374 for (int i = 0; i < sizeof(expected) / sizeof(SMC::StateAndAction); ++i)
00375 {
00376 CPPUNIT_ASSERT_EQUAL(expected[i].state, log[i].state);
00377 CPPUNIT_ASSERT_EQUAL(expected[i].action, log[i].action);
00378 }
00379 }
00380
00381 };
00382 };
00383
00384
00385
00386
00387 CPPUNIT_TEST_SUITE_REGISTRATION(StateMachineTests::StateMachineTests);
00388
00389 #ifdef LOCAL_MAIN
00390 int main(int argc, char* argv[])
00391 {
00392
00393 FORMAT format = TEXT_OUT;
00394 int target = 0;
00395 std::string xsl;
00396 std::string ns;
00397 std::string fname;
00398 std::ofstream ofs;
00399
00400 int i(1);
00401 while (i < argc)
00402 {
00403 std::string arg(argv[i]);
00404 std::string next_arg;
00405 if (i + 1 < argc) next_arg = argv[i + 1];
00406 else next_arg = "";
00407
00408 if (arg == "--text") { format = TEXT_OUT; break; }
00409 if (arg == "--xml")
00410 {
00411 if (next_arg == "")
00412 {
00413 fname = argv[0];
00414 fname += ".xml";
00415 }
00416 else
00417 {
00418 fname = next_arg;
00419 }
00420 format = XML_OUT;
00421 ofs.open(fname.c_str());
00422 }
00423 if ( arg == "--compiler" ) { format = COMPILER_OUT; break; }
00424 if ( arg == "--cerr" ) { target = 1; break; }
00425 if ( arg == "--xsl" )
00426 {
00427 if (next_arg == "") xsl = "default.xsl";
00428 else xsl = next_arg;
00429 }
00430 if ( arg == "--namespace" )
00431 {
00432 if (next_arg == "")
00433 {
00434 std::cerr << "no namespace specified" << std::endl;
00435 exit(1);
00436 }
00437 else
00438 {
00439 xsl = next_arg;
00440 }
00441 }
00442 ++i;
00443 }
00444 CppUnit::TextUi::TestRunner runner;
00445 if ( ns.empty() )
00446 runner.addTest(CppUnit::TestFactoryRegistry::getRegistry().makeTest());
00447 else
00448 runner.addTest(CppUnit::TestFactoryRegistry::getRegistry(ns).makeTest());
00449 CppUnit::Outputter* outputter = 0;
00450 std::ostream* stream = target ? &std::cerr : &std::cout;
00451 switch ( format )
00452 {
00453 case TEXT_OUT :
00454 outputter = new CppUnit::TextOutputter(&runner.result(),*stream);
00455 break;
00456 case XML_OUT :
00457 std::cout << "XML_OUT" << std::endl;
00458 outputter = new CppUnit::XmlOutputter(&runner.result(),
00459 ofs, "shift_jis");
00460 static_cast<CppUnit::XmlOutputter*>(outputter)->setStyleSheet(xsl);
00461 break;
00462 case COMPILER_OUT :
00463 outputter = new CppUnit::CompilerOutputter(&runner.result(),*stream);
00464 break;
00465 }
00466 runner.setOutputter(outputter);
00467 runner.run();
00468 return 0;
00469 }
00470 #endif // MAIN
00471 #endif // StateMachine_cpp