1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
// Copyright 2024 Christophe Henry
// henry UNDERSCORE christophe AT hotmail DOT com
// This is an extended version of the state machine available in the boost::mpl library
// Distributed under the same license as the original.
// Copyright for the original version:
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
// under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// back-end
#include "BackCommon.hpp"
//front-end
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/puml/puml.hpp>
#include "PumlCommon.hpp"
#ifndef BOOST_MSM_NONSTANDALONE_TEST
#define BOOST_TEST_MODULE only_string_puml_test
#endif
#include <boost/test/unit_test.hpp>
using namespace std;
namespace msm = boost::msm;
using namespace msm::front;
using namespace msm::front::puml;
namespace
{
// note in the puml tests will be non-specialized types marked with _
// front-end: define the FSM structure
struct player_ : public msm::front::state_machine_def<player_>
{
unsigned int start_playback_counter=0;
unsigned int can_close_drawer_counter=0;
unsigned int test_fct_counter=0;
unsigned int entry_counter = 0;
unsigned int exit_counter = 0;
BOOST_MSM_PUML_DECLARE_TABLE(
R"(
@startuml Player
skinparam linetype polyline
state Player{
[*]-> Empty_
Stopped_ -> Playing_ : play / TestFct,start_playback [DummyGuard]
Stopped_ -> Open_ : open_close_ / open_drawer
Stopped_ -> Stopped_ : stop_
Open_ -> Empty_ : open_close_ / close_drawer [can_close_drawer]
Empty_ --> Open_ : open_close_ / open_drawer
Empty_ ---> Stopped_ : cd_detected / store_cd_info2 [good_disk_format && always_true]
Playing_ --> Stopped_ : stop_ / stop_playback
Playing_ -> Paused_ : pause_ / pause_playback
Playing_ --> Open_ : open_close_ / stop_and_open
Paused_ -> Playing_ : end_pause / resume_playback2
Paused_ --> Stopped_ : stop_ / stop_playback
Paused_ --> Open_ : open_close_ / stop_and_open
Playing_ : flag CDLoaded
Playing_ : entry increment_entry [always_true]
Playing_ : exit increment_exit [always_true]
Paused_ : flag CDLoaded
Stopped_ : flag CDLoaded
}
@enduml
)"
)
// Replaces the default no-transition response.
template <class FSM,class Event>
void no_transition(Event const&, FSM&,int)
{
BOOST_FAIL("no_transition called!");
}
};
// Pick a back-end
typedef get_test_machines<player_> players;
BOOST_AUTO_TEST_CASE_TEMPLATE(only_string_puml_test, player, players)
{
player p;
static_assert(msm::back11::get_number_of_regions<typename player::initial_state>::type::value == 1);
static_assert(::boost::mpl::size<typename player::transition_table>::type::value == 12);
p.start();
p.process_event(Event<by_name("open_close_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 1,"Open should be active"); //Open
BOOST_CHECK_MESSAGE(p.template is_flag_active<Flag<by_name("CDLoaded")>>() == false, "CDLoaded should not be active");
p.process_event(Event<by_name("open_close_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.can_close_drawer_counter == 1,"guard not called correctly");
p.process_event(Event<by_name("cd_detected")>{"louie, louie", DISK_DVD});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 2,"Empty should be active"); //Empty
BOOST_CHECK_MESSAGE(p.entry_counter == 0, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.exit_counter == 0, "Playing exit not called correctly");
p.process_event(Event<by_name("cd_detected")>{"louie, louie", DISK_CD});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.start_playback_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.test_fct_counter == 1,"action not called correctly");
BOOST_CHECK_MESSAGE(p.template is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
BOOST_CHECK_MESSAGE(p.entry_counter == 1, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.exit_counter == 0, "Playing exit not called correctly");
p.process_event(Event<by_name("pause_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.template is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
BOOST_CHECK_MESSAGE(p.entry_counter == 1, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.exit_counter == 1, "Playing exit not called correctly");
// go back to Playing
p.process_event(Event<by_name("end_pause")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 3,"Playing should be active"); //Playing
BOOST_CHECK_MESSAGE(p.entry_counter == 2, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.exit_counter == 1, "Playing exit not called correctly");
p.process_event(Event<by_name("pause_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 4,"Paused should be active"); //Paused
BOOST_CHECK_MESSAGE(p.entry_counter == 2, "Playing entry not called correctly");
BOOST_CHECK_MESSAGE(p.exit_counter == 2, "Playing exit not called correctly");
p.process_event(Event<by_name("stop_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
BOOST_CHECK_MESSAGE(p.template is_flag_active < Flag<by_name("CDLoaded")>>() == true, "CDLoaded should be active");
p.process_event(Event<by_name("stop_")>{});
BOOST_CHECK_MESSAGE(p.current_state()[0] == 0,"Stopped should be active"); //Stopped
}
}
|