Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
mitkMessageTest.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkMessage.h"
18 
19 #include "mitkTestingMacros.h"
20 
21 #include <iostream>
22 
23 namespace mitk
24 {
25  class mitkMessageTestTestClass
26  {
27  public:
28  // dummy class to send around
29  class Package
30  {
31  public:
32  Package(int content = 43) : m_Content(content) {}
33  void Clear() { m_Content = 0; }
34  bool operator==(const Package &other) { return m_Content == other.m_Content; }
35  private:
36  int m_Content;
37  };
38 
39  class MessageSenderClass
40  {
41  public:
42  // message without any parameters, pure notification
43  Message<> WaveHand;
44 
45  // message without any parameters, pure notification
46  Message<> ShowFinger;
47 
48  // message with one parameter of type std::string
49  Message1<const std::string &> Say;
50 
51  // message with one parameter of type double
52  Message1<double> WalkMeters;
53 
54  // message with one parameter of class type Package
55  Message1<const Package &> GivePackage;
56 
57  // message with two parameters of type int and float
58  Message2<int, float> ShoutAgeAndFootSize;
59 
60  void DoShowFinger()
61  {
62  ShowFinger.Send();
63  // ShowFinger() does the same
64  }
65 
66  void DoWaveHand()
67  {
68  WaveHand();
69  // WaveHand.Send() does the same
70  }
71 
72  void DoSay(const std::string &words) { Say(words); }
73  void DoWalk(double meters) { WalkMeters(meters); }
74  void DoGivePackage(const Package &package) { GivePackage.Send(package); }
75  void DoShoutAgeAndFootSize(int age, float size) { ShoutAgeAndFootSize(age, size); }
76  };
77 
78  // Receiver class remembers events received.
79  // Will tell about received events when asked.
80  class MessageReceiverClass
81  {
82  public:
83  MessageReceiverClass() { Amnesia(); }
84  void OnWaveHand() { m_HandWaved = true; }
85  bool HandWaved() { return m_HandWaved; }
86  void OnSay(const std::string &words) { m_WordsSaid = words; }
87  const std::string WordsSaid() { return m_WordsSaid; }
88  void OnWalk(double meters) { m_MetersWalked = meters; }
89  double MetersWalked() { return m_MetersWalked; }
90  void OnGivePackage(const Package &p) { m_PackageReceived = p; }
91  Package PackageReceived() { return m_PackageReceived; }
92  void OnShoutAgeAndFootSize(int age, float footSize)
93  {
94  m_Age = age;
95  m_FootSize = footSize;
96  }
97 
98  int Age() { return m_Age; }
99  float FootSize() { return m_FootSize; }
100  void Amnesia()
101  {
102  m_HandWaved = false;
103  m_WordsSaid.clear();
104  m_MetersWalked = 0.0;
105  m_PackageReceived.Clear();
106  m_Age = 0;
107  m_FootSize = 0.0;
108  }
109 
110  void RegisterObservers(MessageSenderClass &sender)
111  {
112  sender.WaveHand += MessageDelegate<MessageReceiverClass>(this, &MessageReceiverClass::OnWaveHand);
113  sender.ShowFinger += MessageDelegate<MessageReceiverClass>(
114  this, &MessageReceiverClass::OnWaveHand); // we cannot see clearly, misinterpret this
115 
116  sender.Say += MessageDelegate1<MessageReceiverClass, const std::string &>(this, &MessageReceiverClass::OnSay);
117  sender.WalkMeters += MessageDelegate1<MessageReceiverClass, double>(this, &MessageReceiverClass::OnWalk);
118  sender.GivePackage +=
119  MessageDelegate1<MessageReceiverClass, const Package &>(this, &MessageReceiverClass::OnGivePackage);
120  sender.ShoutAgeAndFootSize +=
121  MessageDelegate2<MessageReceiverClass, int, float>(this, &MessageReceiverClass::OnShoutAgeAndFootSize);
122  }
123 
124  private:
125  bool m_HandWaved;
126  std::string m_WordsSaid;
127  double m_MetersWalked;
128  Package m_PackageReceived;
129  int m_Age;
130  float m_FootSize;
131  };
132 
133  /* MessageMacro Test classes */
134  class Law
135  {
136  private:
137  std::string m_Description;
138 
139  public:
140  Law(const std::string &law) : m_Description(law) {}
141  std::string GetDescription() const { return m_Description; }
142  };
143 
144  // The NewtonMachine will issue specific events
145  class NewtonMachine
146  {
147  mitkNewMessageMacro(AnalysisStarted);
148  mitkNewMessage1Macro(AnalysisStopped, bool);
149  mitkNewMessage1Macro(LawDiscovered, const Law &);
150  // mitkNewMessageWithReturnMacro(PatentFiled, bool);
151 
152  public:
153  void StartAnalysis()
154  {
155  // send the "started" signal
156  m_AnalysisStartedMessage();
157 
158  // we found a new law of nature by creating one :-)
159  Law massLaw("Unit tests are mandatory!");
160  m_LawDiscoveredMessage(massLaw);
161  }
162 
163  void StopAnalysis()
164  {
165  // send the "stop" message with true, indicating
166  // that an error occurred
167  m_AnalysisStoppedMessage(true);
168  }
169  bool PatentLaw()
170  {
171  // bool patentAccepted = m_PatentFiledMessage();
172  // return patentAccepted;
173  // m_PatentFiledMessage();
174  return false;
175  }
176  };
177 
178  class Observer
179  {
180  private:
181  NewtonMachine *m_Machine;
182 
183  public:
184  Observer(NewtonMachine *machine)
185  : m_Machine(machine), m_MachineStarted(false), m_MachineStopped(false), m_Error(false), m_Law("NONE")
186  {
187  // Add "observers", i.e. function pointers to the machine
188  m_Machine->AddAnalysisStartedListener(::mitk::MessageDelegate<Observer>(this, &Observer::MachineStarted));
189  m_Machine->AddAnalysisStoppedListener(
190  ::mitk::MessageDelegate1<Observer, bool>(this, &Observer::MachineStopped));
191  m_Machine->AddLawDiscoveredListener(
192  ::mitk::MessageDelegate1<Observer, const Law &>(this, &Observer::LawDiscovered));
193  // m_Machine->AddPatentFiledListener(
194  // ::mitk::MessageDelegate<Observer>(this, &Observer::ReviewPatent));
195  }
196 
197  ~Observer()
198  {
199  // Always remove your observers when finished
200  m_Machine->RemoveAnalysisStartedListener(::mitk::MessageDelegate<Observer>(this, &Observer::MachineStarted));
201  m_Machine->RemoveAnalysisStoppedListener(
202  ::mitk::MessageDelegate1<Observer, bool>(this, &Observer::MachineStopped));
203  m_Machine->RemoveLawDiscoveredListener(
204  ::mitk::MessageDelegate1<Observer, const Law &>(this, &Observer::LawDiscovered));
205  // m_Machine->RemoveLawDiscoveredListener(
206  // ::mitk::MessageDelegate<Observer>(this, &Observer::ReviewPatent));
207  }
208 
209  void MachineStarted() { m_MachineStarted = true; }
210  void MachineStopped(bool error)
211  {
212  m_MachineStopped = true;
213  m_Error = error;
214  }
215 
216  void LawDiscovered(const Law &law) { m_Law = law; }
217  bool ReviewPatent()
218  {
219  m_PatentReviewed = true;
220  return false; // laws of nature are not patentable.
221  }
222  bool m_MachineStarted;
223  bool m_MachineStopped;
224  bool m_Error;
225  Law m_Law;
226  bool m_PatentReviewed;
227  };
228 
229  }; // end test class
230 
231 } // end namespace
232 
233 int mitkMessageTest(int /* argc */, char * /*argv*/ [])
234 {
235  MITK_TEST_BEGIN("Message")
236 
237  mitk::mitkMessageTestTestClass::MessageSenderClass sender;
238  mitk::mitkMessageTestTestClass::MessageReceiverClass receiver;
239 
240  MITK_TEST_CONDITION_REQUIRED(true, "Testing instantiation");
241 
242  receiver.RegisterObservers(sender);
243 
244  MITK_TEST_CONDITION_REQUIRED(true, "Testing registration to messages");
245 
246  MITK_TEST_CONDITION_REQUIRED((sender.DoWaveHand(), // This is called "comma operator". Don't ask, read!
247  receiver.HandWaved()),
248  "Message without parameters");
249  receiver.Amnesia();
250 
251  MITK_TEST_CONDITION_REQUIRED((sender.DoShowFinger(), receiver.HandWaved()), "Message without parameters");
252  receiver.Amnesia();
253 
254  MITK_TEST_CONDITION_REQUIRED((sender.DoSay("Blooodworsch"), receiver.WordsSaid() == "Blooodworsch"),
255  "Message with std::string parameter");
256  receiver.Amnesia();
257 
258  MITK_TEST_CONDITION_REQUIRED((sender.DoWalk(2.67), (receiver.MetersWalked() - 2.67) < 0.0001),
259  "Message with double parameter");
260  receiver.Amnesia();
261 
262  mitk::mitkMessageTestTestClass::Package package(8);
263  MITK_TEST_CONDITION_REQUIRED((sender.DoGivePackage(package), receiver.PackageReceived() == package),
264  "Message with class parameter");
265  receiver.Amnesia();
266 
268  (sender.DoShoutAgeAndFootSize(46, 30.5), (receiver.Age() == 46 && (receiver.FootSize() - 30.5 < 0.0001))),
269  "Message with int AND float parameter");
270  receiver.Amnesia();
271 
272  mitk::mitkMessageTestTestClass::NewtonMachine newtonMachine;
273  mitk::mitkMessageTestTestClass::Observer observer1(&newtonMachine);
274  mitk::mitkMessageTestTestClass::Observer observer2(&newtonMachine);
275 
276  // This will send two events to registered observers
277  newtonMachine.StartAnalysis();
278  MITK_TEST_CONDITION(observer1.m_MachineStarted == true, "Message from Message Macro send to receiver 1");
279  MITK_TEST_CONDITION(observer2.m_MachineStarted == true, "Message from Message Macro send to receiver 2");
280 
281  MITK_TEST_CONDITION(observer1.m_Law.GetDescription() == std::string("Unit tests are mandatory!"),
282  "Message1 from Message Macro send to receiver 1");
283  MITK_TEST_CONDITION(observer2.m_Law.GetDescription() == std::string("Unit tests are mandatory!"),
284  "Message1 from Message Macro send to receiver 2");
285 
286  // This will send one event to registered observers
287  newtonMachine.StopAnalysis();
288  MITK_TEST_CONDITION(observer1.m_MachineStopped == true, "Message1 from Message Macro send to receiver 1");
289  MITK_TEST_CONDITION(observer1.m_Error == true, "Message1 parameter from Message Macro send to receiver 1");
290 
291  MITK_TEST_CONDITION(observer2.m_MachineStopped == true, "Message1 from Message Macro send to receiver 2");
292  MITK_TEST_CONDITION(observer2.m_Error == true, "Message1 parameter from Message Macro send to receiver 2");
293 
294  /* Message with return type tests are work in progess... */
295  // bool patentSuccessful = newtonMachine.PatentLaw(); // what with return types from multiple observers?
296 
297  // MITK_TEST_CONDITION((observer1.m_PatentReviewed == true) && (patentSuccessful == false),
298  // "Message with return type from Message Macro send to receiver 1");
299  //
300  // MITK_TEST_CONDITION((observer2.m_PatentReviewed == true) && (patentSuccessful == false),
301  // "Message with return type from Message Macro send to receiver 2");
302 
303  MITK_TEST_END();
304 }
#define mitkNewMessage1Macro(msgHandleObject, type1)
Definition: mitkMessage.h:56
#define MITK_TEST_CONDITION_REQUIRED(COND, MSG)
DataCollection - Class to facilitate loading/accessing structured data.
section GeneralTestsDeprecatedOldTestingStyle Deprecated macros All tests with MITK_TEST_BEGIN()
MITKCORE_EXPORT bool operator==(const InteractionEvent &a, const InteractionEvent &b)
#define mitkNewMessageMacro(msgHandleObject)
Definition: mitkMessage.h:28
#define MITK_TEST_CONDITION(COND, MSG)
int mitkMessageTest(int, char *[])
and MITK_TEST_END()