comparison UnitTestsSources/TestMessageBroker.cpp @ 428:751fb354149e am-vsol-upgrade

ability to change the scene of the RadiographyWidget
author am@osimis.io
date Wed, 28 Nov 2018 10:44:28 +0100
parents 1d9dd542adfe
children a750f11892ec
comparison
equal deleted inserted replaced
426:660fe6f6bf4a 428:751fb354149e
1 ///** 1 /**
2 // * Stone of Orthanc 2 * Stone of Orthanc
3 // * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics 3 * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
4 // * Department, University Hospital of Liege, Belgium 4 * Department, University Hospital of Liege, Belgium
5 // * Copyright (C) 2017-2018 Osimis S.A., Belgium 5 * Copyright (C) 2017-2018 Osimis S.A., Belgium
6 // * 6 *
7 // * This program is free software: you can redistribute it and/or 7 * This program is free software: you can redistribute it and/or
8 // * modify it under the terms of the GNU Affero General Public License 8 * modify it under the terms of the GNU Affero General Public License
9 // * as published by the Free Software Foundation, either version 3 of 9 * as published by the Free Software Foundation, either version 3 of
10 // * the License, or (at your option) any later version. 10 * the License, or (at your option) any later version.
11 // * 11 *
12 // * This program is distributed in the hope that it will be useful, but 12 * This program is distributed in the hope that it will be useful, but
13 // * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // * Affero General Public License for more details. 15 * Affero General Public License for more details.
16 // * 16 *
17 // * You should have received a copy of the GNU Affero General Public License 17 * You should have received a copy of the GNU Affero General Public License
18 // * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 // **/ 19 **/
20 20
21 21
22 //#include "gtest/gtest.h" 22 #include "gtest/gtest.h"
23 23
24 //#include "../Framework/Messages/MessageBroker.h" 24 #include "Framework/Messages/MessageBroker.h"
25 //#include "../Framework/Messages/IMessage.h" 25 #include "Framework/Messages/Promise.h"
26 //#include "../Framework/Messages/IObservable.h" 26 #include "Framework/Messages/IObservable.h"
27 //#include "../Framework/Messages/IObserver.h" 27 #include "Framework/Messages/IObserver.h"
28 //#include "../Framework/StoneEnumerations.h" 28 #include "Framework/Messages/MessageForwarder.h"
29 29
30 30
31 //static int test1Counter = 0; 31 int testCounter = 0;
32 //static int test2Counter = 0; 32 namespace {
33 //class MyFullObserver : public OrthancStone::IObserver 33
34 //{ 34 using namespace OrthancStone;
35 35
36 //public: 36
37 // MyFullObserver(OrthancStone::MessageBroker& broker) 37 enum CustomMessageType
38 // : OrthancStone::IObserver(broker) 38 {
39 // { 39 CustomMessageType_First = MessageType_CustomMessage + 1,
40 //// DeclareHandledMessage(OrthancStone::MessageType_Test1); 40
41 //// DeclareIgnoredMessage(OrthancStone::MessageType_Test2); 41 CustomMessageType_Completed,
42 // } 42 CustomMessageType_Increment
43 43 };
44 44
45 // void HandleMessage(OrthancStone::IObservable& from, const OrthancStone::IMessage& message) { 45
46 // switch (message.GetType()) 46 class MyObservable : public IObservable
47 // { 47 {
48 // case OrthancStone::MessageType_Test1: 48 public:
49 // test1Counter++; 49 struct MyCustomMessage: public BaseMessage<CustomMessageType_Completed>
50 // break; 50 {
51 // case OrthancStone::MessageType_Test2: 51 int payload_;
52 // test2Counter++; 52
53 // break; 53 MyCustomMessage(int payload)
54 // default: 54 : BaseMessage(),
55 // throw OrthancStone::MessageNotDeclaredException(message.GetType()); 55 payload_(payload)
56 // } 56 {}
57 // } 57 };
58 58
59 //}; 59 MyObservable(MessageBroker& broker)
60 60 : IObservable(broker)
61 //class MyPartialObserver : public OrthancStone::IObserver 61 {}
62 //{ 62
63 63 };
64 //public: 64
65 // MyPartialObserver(OrthancStone::MessageBroker& broker) 65 class MyObserver : public IObserver
66 // : OrthancStone::IObserver(broker) 66 {
67 // { 67 public:
68 //// DeclareHandledMessage(OrthancStone::MessageType_Test1); 68 MyObserver(MessageBroker& broker)
69 // // don't declare Test2 on purpose 69 : IObserver(broker)
70 // } 70 {}
71 71
72 72 void HandleCompletedMessage(const MyObservable::MyCustomMessage& message)
73 // void HandleMessage(OrthancStone::IObservable& from, const OrthancStone::IMessage& message) { 73 {
74 // switch (message.GetType()) 74 testCounter += message.payload_;
75 // { 75 }
76 // case OrthancStone::MessageType_Test1: 76
77 // test1Counter++; 77 };
78 // break; 78
79 // case OrthancStone::MessageType_Test2: 79
80 // test2Counter++; 80 class MyIntermediate : public IObserver, public IObservable
81 // break; 81 {
82 // default: 82 IObservable& observedObject_;
83 // throw OrthancStone::MessageNotDeclaredException(message.GetType()); 83 public:
84 // } 84 MyIntermediate(MessageBroker& broker, IObservable& observedObject)
85 // } 85 : IObserver(broker),
86 86 IObservable(broker),
87 //}; 87 observedObject_(observedObject)
88 88 {
89 89 observedObject_.RegisterObserverCallback(new MessageForwarder<MyObservable::MyCustomMessage>(broker, *this));
90 //class MyObservable : public OrthancStone::IObservable 90 }
91 //{ 91 };
92 92
93 //public: 93
94 // MyObservable(OrthancStone::MessageBroker& broker) 94 class MyPromiseSource : public IObservable
95 // : OrthancStone::IObservable(broker) 95 {
96 // { 96 Promise* currentPromise_;
97 // DeclareEmittableMessage(OrthancStone::MessageType_Test1); 97 public:
98 // DeclareEmittableMessage(OrthancStone::MessageType_Test2); 98 struct MyPromiseMessage: public BaseMessage<MessageType_Test1>
99 // } 99 {
100 100 int increment;
101 //}; 101
102 102 MyPromiseMessage(int increment)
103 103 : BaseMessage(),
104 //TEST(MessageBroker, NormalUsage) 104 increment(increment)
105 //{ 105 {}
106 // OrthancStone::MessageBroker broker; 106 };
107 // MyObservable observable(broker); 107
108 108 MyPromiseSource(MessageBroker& broker)
109 // test1Counter = 0; 109 : IObservable(broker),
110 110 currentPromise_(NULL)
111 // // no observers have been registered -> nothing shall happen 111 {}
112 // observable.EmitMessage(OrthancStone::IMessage(OrthancStone::MessageType_Test1)); 112
113 113 Promise& StartSomethingAsync()
114 // ASSERT_EQ(0, test1Counter); 114 {
115 115 currentPromise_ = new Promise(GetBroker());
116 // // register an observer, check it is called 116 return *currentPromise_;
117 // MyFullObserver fullObserver(broker); 117 }
118 // ASSERT_NO_THROW(observable.RegisterObserver(fullObserver)); 118
119 119 void CompleteSomethingAsyncWithSuccess(int payload)
120 // observable.EmitMessage(OrthancStone::IMessage(OrthancStone::MessageType_Test1)); 120 {
121 121 currentPromise_->Success(MyPromiseMessage(payload));
122 // ASSERT_EQ(1, test1Counter); 122 delete currentPromise_;
123 123 }
124 // // register an invalid observer, check it raises an exception 124
125 // MyPartialObserver partialObserver(broker); 125 void CompleteSomethingAsyncWithFailure(int payload)
126 // ASSERT_THROW(observable.RegisterObserver(partialObserver), OrthancStone::MessageNotDeclaredException); 126 {
127 127 currentPromise_->Failure(MyPromiseMessage(payload));
128 // // check an exception is thrown when the observable emits an undeclared message 128 delete currentPromise_;
129 // ASSERT_THROW(observable.EmitMessage(OrthancStone::IMessage(OrthancStone::MessageType_VolumeSlicer_GeometryReady)), OrthancStone::MessageNotDeclaredException); 129 }
130 130 };
131 // // unregister the observer, make sure nothing happens afterwards 131
132 // observable.UnregisterObserver(fullObserver); 132
133 // observable.EmitMessage(OrthancStone::IMessage(OrthancStone::MessageType_Test1)); 133 class MyPromiseTarget : public IObserver
134 // ASSERT_EQ(1, test1Counter); 134 {
135 //} 135 public:
136 136 MyPromiseTarget(MessageBroker& broker)
137 //TEST(MessageBroker, DeleteObserverWhileRegistered) 137 : IObserver(broker)
138 //{ 138 {}
139 // OrthancStone::MessageBroker broker; 139
140 // MyObservable observable(broker); 140 void IncrementCounter(const MyPromiseSource::MyPromiseMessage& args)
141 141 {
142 // test1Counter = 0; 142 testCounter += args.increment;
143 143 }
144 // { 144
145 // // register an observer, check it is called 145 void DecrementCounter(const MyPromiseSource::MyPromiseMessage& args)
146 // MyFullObserver observer(broker); 146 {
147 // observable.RegisterObserver(observer); 147 testCounter -= args.increment;
148 148 }
149 // observable.EmitMessage(OrthancStone::IMessage(OrthancStone::MessageType_Test1)); 149 };
150 150 }
151 // ASSERT_EQ(1, test1Counter); 151
152 // } 152
153 153 TEST(MessageBroker, TestPermanentConnectionSimpleUseCase)
154 // // at this point, the observer has been deleted, the handle shall not be called again (and it shall not crash !) 154 {
155 // observable.EmitMessage(OrthancStone::IMessage(OrthancStone::MessageType_Test1)); 155 MessageBroker broker;
156 156 MyObservable observable(broker);
157 // ASSERT_EQ(1, test1Counter); 157 MyObserver observer(broker);
158 //} 158
159 // create a permanent connection between an observable and an observer
160 observable.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage));
161
162 testCounter = 0;
163 observable.EmitMessage(MyObservable::MyCustomMessage(12));
164 ASSERT_EQ(12, testCounter);
165
166 // the connection is permanent; if we emit the same message again, the observer will be notified again
167 testCounter = 0;
168 observable.EmitMessage(MyObservable::MyCustomMessage(20));
169 ASSERT_EQ(20, testCounter);
170
171 // Unregister the observer; make sure it's not called anymore
172 observable.Unregister(&observer);
173 testCounter = 0;
174 observable.EmitMessage(MyObservable::MyCustomMessage(20));
175 ASSERT_EQ(0, testCounter);
176 }
177
178 TEST(MessageBroker, TestMessageForwarderSimpleUseCase)
179 {
180 MessageBroker broker;
181 MyObservable observable(broker);
182 MyIntermediate intermediate(broker, observable);
183 MyObserver observer(broker);
184
185 // let the observer observers the intermediate that is actually forwarding the messages from the observable
186 intermediate.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage));
187
188 testCounter = 0;
189 observable.EmitMessage(MyObservable::MyCustomMessage(12));
190 ASSERT_EQ(12, testCounter);
191
192 // the connection is permanent; if we emit the same message again, the observer will be notified again
193 testCounter = 0;
194 observable.EmitMessage(MyObservable::MyCustomMessage(20));
195 ASSERT_EQ(20, testCounter);
196 }
197
198 TEST(MessageBroker, TestPermanentConnectionDeleteObserver)
199 {
200 MessageBroker broker;
201 MyObservable observable(broker);
202 MyObserver* observer = new MyObserver(broker);
203
204 // create a permanent connection between an observable and an observer
205 observable.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(*observer, &MyObserver::HandleCompletedMessage));
206
207 testCounter = 0;
208 observable.EmitMessage(MyObservable::MyCustomMessage(12));
209 ASSERT_EQ(12, testCounter);
210
211 // delete the observer and check that the callback is not called anymore
212 delete observer;
213
214 // the connection is permanent; if we emit the same message again, the observer will be notified again
215 testCounter = 0;
216 observable.EmitMessage(MyObservable::MyCustomMessage(20));
217 ASSERT_EQ(0, testCounter);
218 }
219
220 TEST(MessageBroker, TestMessageForwarderDeleteIntermediate)
221 {
222 MessageBroker broker;
223 MyObservable observable(broker);
224 MyIntermediate* intermediate = new MyIntermediate(broker, observable);
225 MyObserver observer(broker);
226
227 // let the observer observers the intermediate that is actually forwarding the messages from the observable
228 intermediate->RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage));
229
230 testCounter = 0;
231 observable.EmitMessage(MyObservable::MyCustomMessage(12));
232 ASSERT_EQ(12, testCounter);
233
234 delete intermediate;
235
236 observable.EmitMessage(MyObservable::MyCustomMessage(20));
237 ASSERT_EQ(12, testCounter);
238 }
239
240 TEST(MessageBroker, TestCustomMessage)
241 {
242 MessageBroker broker;
243 MyObservable observable(broker);
244 MyIntermediate intermediate(broker, observable);
245 MyObserver observer(broker);
246
247 // let the observer observers the intermediate that is actually forwarding the messages from the observable
248 intermediate.RegisterObserverCallback(new Callable<MyObserver, MyObservable::MyCustomMessage>(observer, &MyObserver::HandleCompletedMessage));
249
250 testCounter = 0;
251 observable.EmitMessage(MyObservable::MyCustomMessage(12));
252 ASSERT_EQ(12, testCounter);
253
254 // the connection is permanent; if we emit the same message again, the observer will be notified again
255 testCounter = 0;
256 observable.EmitMessage(MyObservable::MyCustomMessage(20));
257 ASSERT_EQ(20, testCounter);
258 }
259
260
261 TEST(MessageBroker, TestPromiseSuccessFailure)
262 {
263 MessageBroker broker;
264 MyPromiseSource source(broker);
265 MyPromiseTarget target(broker);
266
267 // test a successful promise
268 source.StartSomethingAsync()
269 .Then(new Callable<MyPromiseTarget, MyPromiseSource::MyPromiseMessage>(target, &MyPromiseTarget::IncrementCounter))
270 .Else(new Callable<MyPromiseTarget, MyPromiseSource::MyPromiseMessage>(target, &MyPromiseTarget::DecrementCounter));
271
272 testCounter = 0;
273 source.CompleteSomethingAsyncWithSuccess(10);
274 ASSERT_EQ(10, testCounter);
275
276 // test a failing promise
277 source.StartSomethingAsync()
278 .Then(new Callable<MyPromiseTarget, MyPromiseSource::MyPromiseMessage>(target, &MyPromiseTarget::IncrementCounter))
279 .Else(new Callable<MyPromiseTarget, MyPromiseSource::MyPromiseMessage>(target, &MyPromiseTarget::DecrementCounter));
280
281 testCounter = 0;
282 source.CompleteSomethingAsyncWithFailure(15);
283 ASSERT_EQ(-15, testCounter);
284 }
285
286 TEST(MessageBroker, TestPromiseDeleteTarget)
287 {
288 MessageBroker broker;
289 MyPromiseSource source(broker);
290 MyPromiseTarget* target = new MyPromiseTarget(broker);
291
292 // create the promise
293 source.StartSomethingAsync()
294 .Then(new Callable<MyPromiseTarget, MyPromiseSource::MyPromiseMessage>(*target, &MyPromiseTarget::IncrementCounter))
295 .Else(new Callable<MyPromiseTarget, MyPromiseSource::MyPromiseMessage>(*target, &MyPromiseTarget::DecrementCounter));
296
297 // delete the promise target
298 delete target;
299
300 // trigger the promise, make sure it does not throw and does not call the callback
301 testCounter = 0;
302 source.CompleteSomethingAsyncWithSuccess(10);
303 ASSERT_EQ(0, testCounter);
304
305 // test a failing promise
306 source.StartSomethingAsync()
307 .Then(new Callable<MyPromiseTarget, MyPromiseSource::MyPromiseMessage>(*target, &MyPromiseTarget::IncrementCounter))
308 .Else(new Callable<MyPromiseTarget, MyPromiseSource::MyPromiseMessage>(*target, &MyPromiseTarget::DecrementCounter));
309
310 testCounter = 0;
311 source.CompleteSomethingAsyncWithFailure(15);
312 ASSERT_EQ(0, testCounter);
313 }
314
315 #if __cplusplus >= 201103L
316
317 #include <functional>
318
319 namespace OrthancStone {
320
321 template <typename TMessage>
322 class LambdaCallable : public MessageHandler<TMessage>
323 {
324 private:
325
326 IObserver& observer_;
327 std::function<void (const TMessage&)> lambda_;
328
329 public:
330 LambdaCallable(IObserver& observer,
331 std::function<void (const TMessage&)> lambdaFunction) :
332 observer_(observer),
333 lambda_(lambdaFunction)
334 {
335 }
336
337 virtual void Apply(const IMessage& message)
338 {
339 lambda_(dynamic_cast<const TMessage&>(message));
340 }
341
342 virtual MessageType GetMessageType() const
343 {
344 return static_cast<MessageType>(TMessage::Type);
345 }
346
347 virtual IObserver* GetObserver() const
348 {
349 return &observer_;
350 }
351 };
352
353
354 }
355
356 TEST(MessageBroker, TestLambdaSimpleUseCase)
357 {
358 MessageBroker broker;
359 MyObservable observable(broker);
360 MyObserver* observer = new MyObserver(broker);
361
362 // create a permanent connection between an observable and an observer
363 observable.RegisterObserverCallback(new LambdaCallable<MyObservable::MyCustomMessage>(*observer, [&](const MyObservable::MyCustomMessage& message) {testCounter += 2 * message.payload_;}));
364
365 testCounter = 0;
366 observable.EmitMessage(MyObservable::MyCustomMessage(12));
367 ASSERT_EQ(24, testCounter);
368
369 // delete the observer and check that the callback is not called anymore
370 delete observer;
371
372 // the connection is permanent; if we emit the same message again, the observer will be notified again
373 testCounter = 0;
374 observable.EmitMessage(MyObservable::MyCustomMessage(20));
375 ASSERT_EQ(0, testCounter);
376 }
377
378 namespace {
379 class MyObserverWithLambda : public IObserver {
380 private:
381 int multiplier_; // this is a private variable we want to access in a lambda
382
383 public:
384 MyObserverWithLambda(MessageBroker& broker, int multiplier, MyObservable& observable)
385 : IObserver(broker),
386 multiplier_(multiplier)
387 {
388 // register a callable to a lambda that access private members
389 observable.RegisterObserverCallback(new LambdaCallable<MyObservable::MyCustomMessage>(*this, [this](const MyObservable::MyCustomMessage& message) {
390 testCounter += multiplier_ * message.payload_;
391 }));
392
393 }
394 };
395 }
396
397 TEST(MessageBroker, TestLambdaCaptureThisAndAccessPrivateMembers)
398 {
399 MessageBroker broker;
400 MyObservable observable(broker);
401 MyObserverWithLambda* observer = new MyObserverWithLambda(broker, 3, observable);
402
403 testCounter = 0;
404 observable.EmitMessage(MyObservable::MyCustomMessage(12));
405 ASSERT_EQ(36, testCounter);
406
407 // delete the observer and check that the callback is not called anymore
408 delete observer;
409
410 // the connection is permanent; if we emit the same message again, the observer will be notified again
411 testCounter = 0;
412 observable.EmitMessage(MyObservable::MyCustomMessage(20));
413 ASSERT_EQ(0, testCounter);
414 }
415
416 #endif // C++ 11