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