From 9b24d7c33da80b4e0d4f59ebee219d2285d6bc26 Mon Sep 17 00:00:00 2001
From: Stephen Roderick <kiwi.net@mac.com>
Date: Mon, 20 Sep 2010 20:21:43 -0400
Subject: [PATCH 1/2] plugins/rtalloc: Add test case demonstrating failing rtstring construction

---
 plugins/rtalloc/tests/CMakeLists.txt  |   23 ++++
 plugins/rtalloc/tests/state_test.cpp  |  199 +++++++++++++++++++++++++++++++++
 plugins/rtalloc/tests/state_test.hpp  |   46 ++++++++
 plugins/rtalloc/tests/test-runner.cpp |   95 ++++++++++++++++
 4 files changed, 363 insertions(+), 0 deletions(-)
 create mode 100644 plugins/rtalloc/tests/state_test.cpp
 create mode 100644 plugins/rtalloc/tests/state_test.hpp
 create mode 100644 plugins/rtalloc/tests/test-runner.cpp

diff --git a/plugins/rtalloc/tests/CMakeLists.txt b/plugins/rtalloc/tests/CMakeLists.txt
index e331cf8..7152c51 100644
--- a/plugins/rtalloc/tests/CMakeLists.txt
+++ b/plugins/rtalloc/tests/CMakeLists.txt
@@ -1,5 +1,20 @@
 IF (BUILD_TESTS)
 
+  if (NOT RUNTIME_OUTPUT_DIRECTORY)
+    set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+  endif()
+
+  find_package(Boost 1.33 REQUIRED unit_test_framework)
+  IF (OROCOS_TARGET STREQUAL win32)
+    #SET(TEST_LIBRARIES ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
+    LIST(APPEND OROCOS-RTT_DEFINITIONS BOOST_TEST_NO_LIB)
+  ENDIF()
+
+  SET(TEST_LIBRARIES ${Boost_SERIALIZATION_LIBRARY} ${Boost_THREAD_LIBRARY})
+
+  INCLUDE_DIRECTORIES( ${OROCOS-RTT_INCLUDE_DIRS} )
+  INCLUDE_DIRECTORIES( "../" )
+
   ADD_EXECUTABLE(rtalloc-combined combined.cpp send.cpp recv.cpp)
   TARGET_LINK_LIBRARIES(rtalloc-combined
 	orocos-taskbrowser-${OROCOS_TARGET}
@@ -7,4 +22,12 @@ IF (BUILD_TESTS)
 	orocos-rtt-${OROCOS_TARGET}
 	)
 
+  ADD_EXECUTABLE( state-test test-runner.cpp state_test.cpp )
+  TARGET_LINK_LIBRARIES(state-test
+	orocos-rtalloctk-${OROCOS_TARGET}
+	orocos-rtt-${OROCOS_TARGET}
+	${TEST_LIBRARIES}
+	)
+  ADD_TEST( state-test ${RUNTIME_OUTPUT_DIRECTORY}/state-test )
+
 ENDIF (BUILD_TESTS)
diff --git a/plugins/rtalloc/tests/state_test.cpp b/plugins/rtalloc/tests/state_test.cpp
new file mode 100644
index 0000000..5cecbc4
--- /dev/null
+++ b/plugins/rtalloc/tests/state_test.cpp
@@ -0,0 +1,199 @@
+/***************************************************************************
+  tag: Peter Soetens  Mon Jan 10 15:59:51 CET 2005  state_test.cpp
+
+                        state_test.cpp -  description
+                           -------------------
+    begin                : Mon January 10 2005
+    copyright            : (C) 2005 Peter Soetens
+    email                : peter.soetens@mech.kuleuven.ac.be
+
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+
+
+#include <rtt/rtt-config.h>
+#include "state_test.hpp"
+
+#include <iostream>
+#include <sstream>
+#include <rtt/SimulationThread.hpp>
+#include <rtt/CommandFunctor.hpp>
+#include <rtt/Method.hpp>
+#include <rtt/Command.hpp>
+#include <rtt/StateMachine.hpp>
+#include <rtt/TaskObject.hpp>
+#include <rtt/scripting/Parser.hpp>
+#include <rtt/scripting/DumpObject.hpp>
+
+using namespace std;
+using namespace RTT;
+
+#include <boost/test/unit_test.hpp>
+
+StateTest::StateTest()
+    :gtc("root"),
+     gtask( 0.01, gtc.engine() )
+{
+	setUp();
+}
+
+void
+StateTest::setUp()
+{
+    SimulationThread::Instance()->stop();
+}
+
+
+void
+StateTest::tearDown()
+{
+    // if a test failed, we must still stop :
+    gtask.stop();
+}
+
+BOOST_FIXTURE_TEST_SUITE( StateTestSuite, StateTest )
+
+BOOST_AUTO_TEST_CASE( testCreateRtstring )
+{
+    // test creation of rtstring from char*
+    string prog = string("StateMachine X {\n")
+        + " initial state INIT {\n"
+        + " var rtstring s = rtstring(\"hello world\");\n"
+        + " transitions { state FINI };\n"
+        + " }\n"
+        + " final state FINI {\n"
+        + " }\n"
+        + " RootMachine X x\n" // instantiate a non hierarchical SC
+        ;
+     this->doState( prog, &gtc );
+     BOOST_CHECK( gtc.engine()->states()->getStateMachine( "x" )->inState("FINI") );
+     this->finishState( &gtc, "x");
+}
+
+
+BOOST_AUTO_TEST_SUITE_END()
+
+void StateTest::doState( const std::string& prog, TaskContext* tc, bool test )
+{
+    BOOST_CHECK( tc->engine() );
+    BOOST_CHECK( tc->engine()->states());
+
+    // Alternative way: test ScriptingAccess as well.
+    try {
+        tc->scripting()->loadStateMachines( prog, std::string("state_test.cpp"), true );
+    }
+    catch( const file_parse_exception& exc )
+        {
+            BOOST_REQUIRE_MESSAGE( false, exc.what() );
+        }
+    catch( const parse_exception& exc )
+        {
+            BOOST_REQUIRE_MESSAGE( false, exc.what() );
+        }
+    catch( const program_load_exception& e)
+        {
+            BOOST_REQUIRE_MESSAGE( false, e.what() );
+        }
+    catch( const std::exception& e ) {
+            BOOST_CHECK_MESSAGE( false , e.what());
+            BOOST_REQUIRE_MESSAGE( false, "Uncaught Processor load exception" );
+    }
+    BOOST_CHECK( gtask.start() );
+    StateMachinePtr sm = tc->engine()->states()->getStateMachine("x");
+    BOOST_CHECK( sm );
+    CommandInterface* ca = newCommandFunctor(boost::bind(&StateMachine::activate, sm ));
+    CommandInterface* cs = newCommandFunctor(boost::bind(&StateMachine::automatic,sm ));
+//      cerr << "Before activate :"<<endl;
+//      tc->getPeer("states")->getPeer("x")->debug(true);
+    BOOST_CHECK( ca->execute()  );
+    BOOST_CHECK_MESSAGE( sm->isActive(), "Error : Activate Command for '"+sm->getName()+"' did not have effect." );
+//      cerr << "After activate :"<<endl;
+//      tc->getPeer("states")->getPeer("x")->debug(true);
+    BOOST_CHECK( gtc.engine()->commands()->process( cs ) != 0 );
+//     while (1)
+    BOOST_CHECK( SimulationThread::Instance()->run(1000) );
+    delete ca;
+    delete cs;
+//     cerr << "After run :"<<endl;
+//     tc->getPeer("states")->getPeer("x")->debug(true);
+// //     tc->getPeer("__states")->getPeer("X")->debug(false);
+//     if( tc->getPeer("__states")->getPeer("Y"))
+//         tc->getPeer("__states")->getPeer("Y")->debug(false);
+//     cerr << "               x.y1 running : "<< (gprocessor.getStateMachineStatus("x.y1") == Processor::StateMachineStatus::running) << endl;
+//     cerr << "               x running : "<< (gprocessor.getStateMachineStatus("x") == Processor::StateMachineStatus::running) << endl;
+
+    if (test ) {
+        // check error status of parent :
+        BOOST_CHECK_MESSAGE( sm->isActive(), "Error : State Context '"+sm->getName()+"' did not get activated." );
+        stringstream errormsg;
+        int line = sm->getLineNumber();
+        errormsg <<" in StateMachine "+sm->getName()
+                 <<" in state "<< sm->currentState()->getName()
+                 <<" on line " << line <<" of that StateMachine:"<<endl;
+        stringstream sctext( sm->getText() );
+        int cnt = 1;
+        while ( cnt++ <line && sctext ) {
+            string garbage;
+            getline( sctext, garbage, '\n' );
+        }
+        getline( sctext, sline, '\n' );
+        errormsg <<"here  > " << sline << endl;
+        if ( sm->inError() ) {
+            RTT::detail::DumpObject( tc );
+        }
+        BOOST_CHECK_MESSAGE( sm->inError() == false, "Runtime error (inError() == true) encountered" + errormsg.str() );
+        // check error status of all children:
+        StateMachine::ChildList cl = sm->getChildren();
+        StateMachine::ChildList::iterator clit = cl.begin();
+        while( clit != cl.end() ) {
+            stringstream cerrormsg;
+            if ( (*clit)->currentState() )
+                cerrormsg <<" in state "<<(*clit)->currentState()->getName()<< " on line " <<  (*clit)->getLineNumber() <<" of that StateMachine."<<endl <<"here  > " << sline << endl;
+            else
+                cerrormsg <<" (deactivated) on line " <<  (*clit)->getLineNumber() <<" of that StateMachine."<<endl<<"here  > " << sline << endl;
+            BOOST_CHECK_MESSAGE( (*clit)->inError() == false, "Runtime error (inError() == true) encountered in child "+(*clit)->getName() + cerrormsg.str() );
+            ++clit;
+        }
+    }
+}
+
+void StateTest::finishState(TaskContext* tc, std::string prog_name, bool test)
+{
+    StateMachinePtr sm = tc->engine()->states()->getStateMachine(prog_name);
+    BOOST_CHECK( sm );
+    BOOST_CHECK( tc->engine()->states()->getStateMachine( prog_name )->stop() );
+    BOOST_CHECK( SimulationThread::Instance()->run(500) );
+    if (test) {
+        stringstream errormsg;
+        errormsg << " on line " << sm->getLineNumber() <<", status is "<< tc->engine()->states()->getStateMachineStatusStr(prog_name) <<endl <<"here  > " << sline << endl;;
+        BOOST_CHECK_MESSAGE( sm->isStopped(), "StateMachine stalled " + errormsg.str() );
+    }
+    // you can call deactivate even when the proc is not running.
+    // but deactivation may be 'in progress if exit state has commands in it.
+    BOOST_CHECK( tc->engine()->states()->getStateMachine( prog_name )->deactivate() );
+    BOOST_CHECK( SimulationThread::Instance()->run(200) );
+    BOOST_CHECK( tc->engine()->states()->getStateMachine( prog_name )->isActive() == false );
+
+    // only stop now, since deactivate won't work if simtask not running.
+    tc->stop();
+
+    try {
+        tc->engine()->states()->unloadStateMachine( prog_name );
+    }
+    catch( const program_unload_exception& e)
+        {
+            BOOST_CHECK_MESSAGE( false, e.what() );
+        }
+    catch( ... ) {
+            BOOST_CHECK_MESSAGE( false, "Uncaught Processor unload exception" );
+    }
+
+}
+
diff --git a/plugins/rtalloc/tests/state_test.hpp b/plugins/rtalloc/tests/state_test.hpp
new file mode 100644
index 0000000..b4c70d6
--- /dev/null
+++ b/plugins/rtalloc/tests/state_test.hpp
@@ -0,0 +1,46 @@
+/***************************************************************************
+  tag: Peter Soetens  Mon Jan 10 15:59:18 CET 2005  state_test.hpp
+
+                        state_test.hpp -  description
+                           -------------------
+    begin                : Mon January 10 2005
+    copyright            : (C) 2005 Peter Soetens
+    email                : peter.soetens@mech.kuleuven.ac.be
+
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+
+#ifndef STATETEST_H
+#define STATETEST_H
+
+#include <rtt/TaskContext.hpp>
+#include <string>
+#include <rtt/SimulationActivity.hpp>
+
+class StateTest
+{
+public:
+    RTT::TaskContext gtc;
+    RTT::SimulationActivity gtask;
+    void doState( const std::string& prog, RTT::TaskContext*, bool test=true );
+    void finishState( RTT::TaskContext* , std::string, bool test=true );
+
+    std::string sline;
+public:
+    StateTest();
+    ~StateTest(){ tearDown();};
+
+    void setUp();
+    void tearDown();
+
+    void testCreateRtstring();
+};
+
+#endif
diff --git a/plugins/rtalloc/tests/test-runner.cpp b/plugins/rtalloc/tests/test-runner.cpp
new file mode 100644
index 0000000..d432e0f
--- /dev/null
+++ b/plugins/rtalloc/tests/test-runner.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+  tag: Peter Soetens  Mon Jan 10 15:59:50 CET 2005  test-runner.cpp
+
+                        test-runner.cpp -  description
+                           -------------------
+    begin                : Mon January 10 2005
+    copyright            : (C) 2005 Peter Soetens
+    email                : peter.soetens@mech.kuleuven.ac.be
+
+ ***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include <rtt/os/main.h>
+#include <rtt/Logger.hpp>
+#include <iostream>
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/included/unit_test.hpp>
+#include <rtt/os/StartStopManager.hpp>
+
+#include <rtt/Toolkit.hpp>
+#include <RTallocToolkit.hpp>
+
+using boost::unit_test::test_suite;
+
+using namespace RTT;
+using namespace std;
+
+struct InitOrocos {
+public:
+	InitOrocos(){  }
+	~InitOrocos(){ 
+	    // If we call __os_exit() in Xenomai, we get an ABORT
+	    // because the main task is cleaned up too early.
+	    // The work around for now is to stop all threads but
+	    // the main thread. To be fixed if boost::test allows it.
+#ifndef OROCOS_TARGET_XENOMAI
+        __os_exit();
+#else
+        OS::StartStopManager::Instance()->stop();
+        OS::StartStopManager::Release();
+#endif
+}
+
+};
+
+BOOST_GLOBAL_FIXTURE( InitOrocos )
+
+boost::unit_test::test_suite* init_unit_test_suite(int argc, char** const argv)
+{
+    if ( argc > 1 && strncmp(argv[1],"--help",6) == 0 ) {
+        cout << "This unit test executable takes the following options:" <<endl<<endl;
+        cout << "The starred option is the default, available options depend on Boost UTF library version." <<endl<<endl;
+        cout << "  --build_info[=<yes|no*>]          "<<endl;
+        cout << "  --catch_system_errors[=<yes*|no>  "<<endl;
+        cout << "  --detect_memory_leaks[=<yes*|no>  "<<endl;
+        cout << "  --log_format[=<HRF*|XML>          "<<endl;
+        cout << "  --log_level[=<all|success|test_suite|message|warning|error*|cpp_exception|system_error|fatal_error|nothing>"<<endl;
+        cout << "  --result_code[=<yes*|no>          "<<endl;
+        cout << "  --output_format[=<HRF*|XML>       "<<endl;
+        cout << "  --random[=<0*|1|>1>               "<<endl;
+        cout << "  --report_format[=<HRF*|XML>       "<<endl;
+        cout << "  --report level[=<no|confirm*|short|detailed>"<<endl;
+        cout << "  --show_progress[=<yes|no*>        "<<endl<<endl;
+        cout << "  --use_alt_stack[=<yes*|no>        "<<endl<<endl;
+        
+        cout << "Select tests by using the form:"<<endl;
+        cout << "  " << argv[0] << " --run_test=suite/testX"<<endl;
+        cout << "Wildcards are accepted:"<<endl;
+        cout << "  " << argv[0] << " --run_test=*/testX"<<endl;
+        exit(0);
+    }
+
+	__os_init(argc, argv);
+
+    // disable logging of errors or warnings if no ORO_LOGLEVEL was set.
+    if ( log().getLogLevel() == Logger::Warning ) {
+        log(Info) << "Lowering LogLevel to Critical." << endlog();
+        log().setLogLevel(Logger::Critical);
+    } else {
+        log(Info) << "LogLevel unaltered by test-runner." << endlog();
+    }
+
+    // load required plugins
+    RTT::Toolkit::Import(RTT::RTallocToolkit);
+
+    return 0;
+}
+
-- 
1.7.0.2

