Lumiera  0.pre.03
»edit your freedom«
command-use2-test.cpp
Go to the documentation of this file.
1 /*
2  CommandUse2(Test) - usage aspects II
3 
4  Copyright (C) Lumiera.org
5  2009, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 * *****************************************************/
22 
28 #include "lib/test/run.hpp"
29 #include "lib/test/test-helper.hpp"
33 #include "lib/format-string.hpp"
34 #include "lib/format-obj.hpp"
35 #include "lib/util.hpp"
36 
38 
39 extern "C" {
41 }
44 
45 #include <functional>
46 #include <boost/ref.hpp>
47 #include <boost/lexical_cast.hpp>
48 #include <string>
49 
50 
51 namespace steam {
52 namespace control {
53 namespace test {
54 
55  using util::_Fmt;
56  using std::string;
57  using std::function;
58  using std::bind;
59  using std::ref;
60  using boost::lexical_cast;
61  using util::contains;
62 
63  using LERR_(EXTERNAL);
64 
65 
71  template<typename TY>
72  inline bool
73  protocolled (TY val2check)
74  {
75  return contains ( command2::check_.str()
76  , util::toString (val2check)
77  );
78  }
79 
80 
81 
82 
83  /***********************************************************************/
91  class CommandUse2_test : public Test
92  {
93 
94  int randVal_;
95 
96  string randomTxt()
97  {
98  _Fmt fmt ("invoked( %2d )");
99 
100  randVal_ = rand() % 100;
101  return fmt % randVal_;
102  }
103 
104  bool blowUp_;
105 
106 
107  virtual void
108  run (Arg)
109  {
110  command2::check_.seekp(0);
111  uint cnt_defs = Command::definition_count();
112  uint cnt_inst = Command::instance_count();
113 
114  function<string()> randFun = bind (&CommandUse2_test::randomTxt, this);
115 
116  // prepare a command definition (prototype)
117  CommandDef ("test.command2")
118  .operation (command2::operate)
119  .captureUndo (command2::capture)
120  .undoOperation (command2::undoIt)
121  .bind (randFun, &blowUp_);
122 
123  //note : blowUp_ is bound via pointer,
124  // thus we can provoke an exception at will.
125  blowUp_ = false;
126 
127 
128  check_defaultHandlingPattern();
129 // check_ThrowOnError(); //////////////////////////////////////////////////////////////////////TICKET #211
131 
132 
133  Command::remove ("test.command2");
134  Command::remove ("test.command2.1");
135  CHECK (cnt_defs == Command::definition_count());
136  CHECK (cnt_inst == Command::instance_count());
137  }
138 
139 
140 
141  void
142  check_defaultHandlingPattern()
143  {
144  Command com = Command::get("test.command2");
145 
146  CHECK (!protocolled("invoked"));
147 
148  bool success = com();
149 
150  CHECK (success);
151  CHECK (protocolled("invoked"));
152  CHECK (protocolled(randVal_));
153 
154  success = com.undo();
155  CHECK (success); // UNDO invoked successfully
156  CHECK (!protocolled(randVal_));
157  CHECK (protocolled("UNDO"));
158 
159  blowUp_ = true;
160  string current = command2::check_.str();
161 
162  success = com();
163  CHECK (not success); // NOT executed successfully (exception thrown and caught)
164  CHECK (command2::check_.str() == current);
165  CHECK (!lumiera_error_peek()); // already absorbed
166 
167  success = com.undo();
168  CHECK (not success); // UNDO failed (exception thrown and caught)
169  CHECK (command2::check_.str() == current);
170 
171  blowUp_ = false;
172  }
173 
174 
175 
176  void
177  check_ThrowOnError()
178  {
179  Command com = Command::get("test.command2");
180 
181  blowUp_ = false;
182  com.exec(HandlingPattern::SYNC_THROW);
183  CHECK (protocolled(randVal_));
184 
185  blowUp_ = true;
186  string current = command2::check_.str();
187  HandlingPattern const& doThrow = HandlingPattern::get(HandlingPattern::SYNC_THROW);
188 
189  VERIFY_ERROR( EXTERNAL, com.exec (doThrow) );
190  CHECK (command2::check_.str() == current);
191 
192  // we can achieve the same effect,
193  // after changing the default HandlingPatern for this command instance
194  com.setHandlingPattern(HandlingPattern::SYNC_THROW);
195  com.storeDef ("test.command2.1");
196 
197  Command com2 = Command::get("test.command2.1");
198  VERIFY_ERROR( EXTERNAL, com2() );
199  CHECK (command2::check_.str() == current);
200 
201  blowUp_ = false;
202  com2();
203  CHECK (command2::check_.str() > current);
204  CHECK (protocolled(randVal_));
205 
206  com2.undo();
207  CHECK (!protocolled(randVal_));
208  }
209 
210 
211 
221  void
223  {
224  CHECK (not SteamDispatcher::instance().isRunning());
227 #define __DELAY__ usleep(10000);
228 
229  bool thread_has_ended{false};
230  SteamDispatcher::instance().start ([&] (string*) { thread_has_ended = true; });
231 
232  CHECK (SteamDispatcher::instance().isRunning());
233  CHECK (not thread_has_ended);
234 
235  //----Session-Loop-Thread-is-running------------------------
236 
237  string cmdID {"test.command2"};
238  string prevExecLog = command2::check_.str();
239 
240  // previous test cases prepared the arguments
241  // so that we can just trigger command execution.
242  // In the real application, this call is issued
243  // from CoreService when receiving a command
244  // invocation message over the UI-Bus
245  SessionCommand::facade().invoke(cmdID);
246 
247  __DELAY__ // wait a moment for the other thread to dispatch the command...
248  CHECK (prevExecLog != command2::check_.str());
249 
250  //----Session-Loop-Thread-is-running------------------------
251 
252  // shut down the SteamDispatcher...
253  CHECK (SteamDispatcher::instance().isRunning());
254  SteamDispatcher::instance().requestStop();
255 
256  __DELAY__ // wait a moment for the other thread to terminate...
257  CHECK (not SteamDispatcher::instance().isRunning());
258  CHECK (thread_has_ended);
259 
260  lumiera_interfaceregistry_destroy();
261  }
262  };
263 
264 
266  LAUNCHER (CommandUse2_test, "function controller");
267 
268 
269 }}} // namespace steam::control::test
Helper class used solely for defining a Command-Object.
HandlingPattern::ID setHandlingPattern(HandlingPattern::ID)
define a handling pattern to be used by default
Definition: command.cpp:474
static lib::Depend< SteamDispatcher > instance
storage for Singleton access
lumiera_err lumiera_error_peek(void)
Check current error state without clearing it Please avoid this function and use lumiera_error() if p...
Definition: error-state.c:142
static size_t definition_count()
Definition: command.cpp:298
Definition: run.hpp:49
Front-end for printf-style string template interpolation.
void throwOnError()
Check the lumiera error state, which maybe was set by C-code.
Definition: error.hpp:242
Dispatch and execute mutation operations on the High-level model.
#define VERIFY_ERROR(ERROR_ID, ERRONEOUS_STATEMENT)
Macro to verify that a statement indeed raises an exception.
static Command get(Symbol cmdID)
Access existing command for use.
Definition: command.cpp:129
Command storeDef(Symbol newCmdID) const
create a clone definition
Definition: command.cpp:192
Steam-Layer implementation namespace root.
A front-end for using printf-style formatting.
static lib::Depend< SessionCommand > facade
static storage for the facade access front-end
static size_t instance_count()
Definition: command.cpp:307
Simple test class runner.
Tiny helper functions and shortcuts to be used everywhere Consider this header to be effectively incl...
Steam-Layer command frontend.
A collection of frequently used helper functions to support unit testing.
bool protocolled(TY val2check)
diagnostics: checks if the given value has been written to the test protocol (string stream) of comma...
Pre-defined command execution skeletons.
void lumiera_interfaceregistry_init(void)
Initialise the interface registry.
Global registry for interfaces (extension points).
Simple functions to represent objects, for debugging and diagnostics.
Some dummy command functions used for building unit test cases.
Handle object representing a single Command instance to be used by client code.
Definition: command.hpp:124
static HandlingPattern const & get(ID id)
retrieve the pre-configured pattern
Actually defining a command and binding it to execution parameters.
Interface: Operation Skeleton how to invoke or undo a command.
Major public Interface to the Session subsystem of Lumiera GUI.
bool contains(SEQ const &cont, typename SEQ::const_reference val)
shortcut for brute-force containment test in any sequential container
Definition: util.hpp:255