Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
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()