1//
2// PriorityEventTest.cpp
3//
4// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "PriorityEventTest.h"
12#include "DummyDelegate.h"
13#include "Poco/CppUnit/TestCaller.h"
14#include "Poco/CppUnit/TestSuite.h"
15#include "Poco/PriorityDelegate.h"
16#include "Poco/PriorityExpire.h"
17#include "Poco/Thread.h"
18#include "Poco/Exception.h"
19
20
21using namespace Poco;
22
23
24#define LARGEINC 100
25
26
27PriorityEventTest::PriorityEventTest(const std::string& rName): CppUnit::TestCase(rName)
28{
29}
30
31
32PriorityEventTest::~PriorityEventTest()
33{
34}
35
36void PriorityEventTest::testNoDelegate()
37{
38 int tmp = 0;
39 EventArgs args;
40
41 assertTrue (_count == 0);
42 Void.notify(this);
43 assertTrue (_count == 0);
44
45 Void += priorityDelegate(this, &PriorityEventTest::onVoid, 0);
46 Void -= priorityDelegate(this, &PriorityEventTest::onVoid, 0);
47 Void.notify(this);
48 assertTrue (_count == 0);
49
50 Simple.notify(this, tmp);
51 assertTrue (_count == 0);
52
53 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
54 Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 0);
55 Simple.notify(this, tmp);
56 assertTrue (_count == 0);
57
58 Simple += priorityDelegate(this, &PriorityEventTest::onSimpleNoSender, 0);
59 Simple -= priorityDelegate(this, &PriorityEventTest::onSimpleNoSender, 0);
60 Simple.notify(this, tmp);
61 assertTrue (_count == 0);
62
63 ConstSimple += priorityDelegate(this, &PriorityEventTest::onConstSimple, 0);
64 ConstSimple -= priorityDelegate(this, &PriorityEventTest::onConstSimple, 0);
65 ConstSimple.notify(this, tmp);
66 assertTrue (_count == 0);
67
68 //Note: passing &args will not work due to &
69 EventArgs* pArgs = &args;
70 Complex += priorityDelegate(this, &PriorityEventTest::onComplex, 0);
71 Complex -= priorityDelegate(this, &PriorityEventTest::onComplex, 0);
72 Complex.notify(this, pArgs);
73 assertTrue (_count == 0);
74
75 Complex2 += priorityDelegate(this, &PriorityEventTest::onComplex2, 0);
76 Complex2 -= priorityDelegate(this, &PriorityEventTest::onComplex2, 0);
77 Complex2.notify(this, args);
78 assertTrue (_count == 0);
79
80 const EventArgs* pCArgs = &args;
81 ConstComplex += priorityDelegate(this, &PriorityEventTest::onConstComplex, 0);
82 ConstComplex -= priorityDelegate(this, &PriorityEventTest::onConstComplex, 0);
83 ConstComplex.notify(this, pCArgs);
84 assertTrue (_count == 0);
85
86 Const2Complex += priorityDelegate(this, &PriorityEventTest::onConst2Complex, 0);
87 Const2Complex -= priorityDelegate(this, &PriorityEventTest::onConst2Complex, 0);
88 Const2Complex.notify(this, pArgs);
89 assertTrue (_count == 0);
90
91 Simple += priorityDelegate(&PriorityEventTest::onStaticSimple, 0);
92 Simple += priorityDelegate(&PriorityEventTest::onStaticSimple, 0);
93 Simple += priorityDelegate(&PriorityEventTest::onStaticSimple, 1);
94 Simple += priorityDelegate(&PriorityEventTest::onStaticSimple2, 2);
95 Simple += priorityDelegate(&PriorityEventTest::onStaticSimple3, 3);
96
97 Simple.notify(this, tmp);
98 assertTrue (_count == 4);
99 Simple -= priorityDelegate(PriorityEventTest::onStaticSimple, 0);
100
101
102 Void += priorityDelegate(&PriorityEventTest::onStaticVoid, 0);
103 Void += priorityDelegate(&PriorityEventTest::onStaticVoid, 0);
104 Void += priorityDelegate(&PriorityEventTest::onStaticVoid, 1);
105
106 Void.notify(this);
107 assertTrue (_count == 7);
108 Void -= priorityDelegate(PriorityEventTest::onStaticVoid, 0);
109}
110
111void PriorityEventTest::testSingleDelegate()
112{
113 int tmp = 0;
114 EventArgs args;
115
116 assertTrue (_count == 0);
117
118 Void += priorityDelegate(this, &PriorityEventTest::onVoid, 0);
119 // unregistering with a different priority --> different observer, is ignored
120 Void -= priorityDelegate(this, &PriorityEventTest::onVoid, 3);
121 Void.notify(this);
122 assertTrue (_count == 1);
123
124 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
125 // unregistering with a different priority --> different observer, is ignored
126 Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 3);
127 Simple.notify(this, tmp);
128 assertTrue (_count == 2);
129
130 ConstSimple += priorityDelegate(this, &PriorityEventTest::onConstSimple, 0);
131 ConstSimple -= priorityDelegate(this, &PriorityEventTest::onConstSimple, 3);
132 ConstSimple.notify(this, tmp);
133 assertTrue (_count == 3);
134
135 EventArgs* pArgs = &args;
136 Complex += priorityDelegate(this, &PriorityEventTest::onComplex, 0);
137 Complex -= priorityDelegate(this, &PriorityEventTest::onComplex, 3);
138 Complex.notify(this, pArgs);
139 assertTrue (_count == 4);
140
141 Complex2 += priorityDelegate(this, &PriorityEventTest::onComplex2, 0);
142 Complex2 -= priorityDelegate(this, &PriorityEventTest::onComplex2, 3);
143 Complex2.notify(this, args);
144 assertTrue (_count == 5);
145
146 const EventArgs* pCArgs = &args;
147 ConstComplex += priorityDelegate(this, &PriorityEventTest::onConstComplex, 0);
148 ConstComplex -= priorityDelegate(this, &PriorityEventTest::onConstComplex, 3);
149 ConstComplex.notify(this, pCArgs);
150 assertTrue (_count == 6);
151
152 Const2Complex += priorityDelegate(this, &PriorityEventTest::onConst2Complex, 0);
153 Const2Complex -= priorityDelegate(this, &PriorityEventTest::onConst2Complex, 3);
154 Const2Complex.notify(this, pArgs);
155 assertTrue (_count == 7);
156 // check if 2nd notify also works
157 Const2Complex.notify(this, pArgs);
158 assertTrue (_count == 8);
159
160}
161
162void PriorityEventTest::testDuplicateRegister()
163{
164 int tmp = 0;
165
166 assertTrue (_count == 0);
167
168 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
169 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
170 Simple.notify(this, tmp);
171 assertTrue (_count == 2);
172 Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 0);
173 Simple.notify(this, tmp);
174 assertTrue (_count == 3);
175
176 Simple += priorityDelegate(this, &PriorityEventTest::onSimpleOther, 1);
177 Simple.notify(this, tmp);
178 assertTrue (_count == 4 + LARGEINC);
179 Simple -= priorityDelegate(this, &PriorityEventTest::onSimpleOther, 1);
180 Simple.notify(this, tmp);
181 assertTrue (_count == 5 + LARGEINC);
182}
183
184void PriorityEventTest::testDuplicateUnregister()
185{
186 // duplicate unregister shouldn't give an error,
187 int tmp = 0;
188
189 assertTrue (_count == 0);
190
191 Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 0); // should work
192 Simple.notify(this, tmp);
193 assertTrue (_count == 0);
194
195 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
196 Simple.notify(this, tmp);
197 assertTrue (_count == 1);
198
199 Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 0);
200 Simple.notify(this, tmp);
201 assertTrue (_count == 1);
202
203 Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 0);
204 Simple.notify(this, tmp);
205 assertTrue (_count == 1);
206}
207
208
209void PriorityEventTest::testDisabling()
210{
211 int tmp = 0;
212
213 assertTrue (_count == 0);
214
215 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 0);
216 Simple.disable();
217 Simple.notify(this, tmp);
218 assertTrue (_count == 0);
219 Simple.enable();
220 Simple.notify(this, tmp);
221 assertTrue (_count == 1);
222
223 // unregister should also work with disabled event
224 Simple.disable();
225 Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 0);
226 Simple.enable();
227 Simple.notify(this, tmp);
228 assertTrue (_count == 1);
229}
230
231void PriorityEventTest::testPriorityOrder()
232{
233 DummyDelegate o1;
234 DummyDelegate o2;
235
236 assertTrue (_count == 0);
237
238 Simple += PriorityDelegate<DummyDelegate, int>(&o2, &DummyDelegate::onSimple2, 1);
239 Simple += PriorityDelegate<DummyDelegate, int>(&o1, &DummyDelegate::onSimple, 0);
240
241 int tmp = 0;
242 Simple.notify(this, tmp);
243 assertTrue (tmp == 2);
244
245 Simple -= PriorityDelegate<DummyDelegate, int>(&o1, &DummyDelegate::onSimple, 0);
246 Simple -= PriorityDelegate<DummyDelegate, int>(&o2, &DummyDelegate::onSimple2, 1);
247
248 // now try with the wrong order
249 Simple += PriorityDelegate<DummyDelegate, int>(&o2, &DummyDelegate::onSimple2, 0);
250 Simple += PriorityDelegate<DummyDelegate, int>(&o1, &DummyDelegate::onSimple, 1);
251
252 try
253 {
254 tmp = 0;
255 Simple.notify(this, tmp);
256 failmsg ("Notify should not work");
257 }
258 catch (Poco::InvalidArgumentException&)
259 {
260 }
261
262 Simple -= PriorityDelegate<DummyDelegate, int>(&o2, &DummyDelegate::onSimple2, 0);
263 Simple -= PriorityDelegate<DummyDelegate, int>(&o1, &DummyDelegate::onSimple, 1);
264}
265
266void PriorityEventTest::testPriorityOrderExpire()
267{
268 // expire must not break order!
269 DummyDelegate o1;
270 DummyDelegate o2;
271
272 assertTrue (_count == 0);
273
274 Simple += priorityDelegate(&o2, &DummyDelegate::onSimple2, 1, 500000);
275 Simple += priorityDelegate(&o1, &DummyDelegate::onSimple, 0, 500000);
276 int tmp = 0;
277 Simple.notify(this, tmp);
278 assertTrue (tmp == 2);
279
280 // both ways of unregistering should work
281 Simple -= priorityDelegate(&o1, &DummyDelegate::onSimple, 0, 500000);
282 Simple -= priorityDelegate(&o2, &DummyDelegate::onSimple2, 1);
283 Simple.notify(this, tmp);
284 assertTrue (tmp == 2);
285
286 // now start mixing of expire and non expire
287 tmp = 0;
288 Simple += priorityDelegate(&o2, &DummyDelegate::onSimple2, 1, 500000);
289 Simple += priorityDelegate(&o1, &DummyDelegate::onSimple, 0);
290
291 Simple.notify(this, tmp);
292 assertTrue (tmp == 2);
293
294 Simple -= priorityDelegate(&o2, &DummyDelegate::onSimple2, 1);
295 // it is not forbidden to unregister a non expiring event with an expire decorator (it is just stupid ;-))
296 Simple -= priorityDelegate(&o1, &DummyDelegate::onSimple, 0, 500000);
297 Simple.notify(this, tmp);
298 assertTrue (tmp == 2);
299
300 // now try with the wrong order
301 Simple += priorityDelegate(&o2, &DummyDelegate::onSimple2, 0, 500000);
302 Simple += priorityDelegate(&o1, &DummyDelegate::onSimple, 1);
303
304 try
305 {
306 tmp = 0;
307 Simple.notify(this, tmp);
308 failmsg ("Notify should not work");
309 }
310 catch (Poco::InvalidArgumentException&)
311 {
312 }
313
314 Simple -= priorityDelegate(&o2, &DummyDelegate::onSimple2, 0, 500000);
315 Simple -= priorityDelegate(&o1, &DummyDelegate::onSimple, 1);
316
317}
318
319void PriorityEventTest::testExpire()
320{
321 int tmp = 0;
322
323 assertTrue (_count == 0);
324
325 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 1, 500);
326 Simple.notify(this, tmp);
327 assertTrue (_count == 1);
328 Poco::Thread::sleep(700);
329 Simple.notify(this, tmp);
330 assertTrue (_count == 1);
331 Simple -= priorityDelegate(this, &PriorityEventTest::onSimple, 1, 500);
332
333 Simple += priorityDelegate(&PriorityEventTest::onStaticSimple, 1, 500);
334 Simple += priorityDelegate(&PriorityEventTest::onStaticSimple2, 1, 500);
335 Simple += priorityDelegate(&PriorityEventTest::onStaticSimple3, 1, 500);
336 Simple.notify(this, tmp);
337 assertTrue (_count == 3);
338 Poco::Thread::sleep(700);
339 Simple.notify(this, tmp);
340 assertTrue (_count == 3);
341}
342
343
344void PriorityEventTest::testExpireReRegister()
345{
346 int tmp = 0;
347
348 assertTrue (_count == 0);
349
350 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 1, 500);
351 Simple.notify(this, tmp);
352 assertTrue (_count == 1);
353 Poco::Thread::sleep(200);
354 Simple.notify(this, tmp);
355 assertTrue (_count == 2);
356 // renew registration
357 Simple += priorityDelegate(this, &PriorityEventTest::onSimple, 1, 600);
358 Poco::Thread::sleep(400);
359 Simple.notify(this, tmp);
360 assertTrue (_count == 3);
361 Poco::Thread::sleep(300);
362 Simple.notify(this, tmp);
363 assertTrue (_count == 3);
364}
365
366
367void PriorityEventTest::testReturnParams()
368{
369 DummyDelegate o1;
370 Simple += priorityDelegate(&o1, &DummyDelegate::onSimple, 0);
371
372 int tmp = 0;
373 Simple.notify(this, tmp);
374 assertTrue (tmp == 1);
375}
376
377void PriorityEventTest::testOverwriteDelegate()
378{
379 DummyDelegate o1;
380 Simple += priorityDelegate(&o1, &DummyDelegate::onSimple, 0);
381 Simple += priorityDelegate(&o1, &DummyDelegate::onSimple2, 0);
382
383 int tmp = 0; // onsimple requires 0 as input
384 Simple.notify(this, tmp);
385 assertTrue (tmp == 2);
386}
387
388void PriorityEventTest::testAsyncNotify()
389{
390 Poco::PriorityEvent<int >* pSimple= new Poco::PriorityEvent<int>();
391 (*pSimple) += priorityDelegate(this, &PriorityEventTest::onAsync, 0);
392 assertTrue (_count == 0);
393 int tmp = 0;
394 Poco::ActiveResult<int>retArg = pSimple->notifyAsync(this, tmp);
395 delete pSimple; // must work even when the event got deleted!
396 pSimple = NULL;
397 assertTrue (_count == 0);
398 retArg.wait();
399 assertTrue (retArg.data() == tmp);
400 assertTrue (_count == LARGEINC);
401
402}
403
404void PriorityEventTest::onStaticVoid(const void* pSender)
405{
406 PriorityEventTest* p = const_cast<PriorityEventTest*>(reinterpret_cast<const PriorityEventTest*>(pSender));
407 p->_count++;
408}
409
410void PriorityEventTest::onVoid(const void* pSender){
411 _count++;
412}
413
414void PriorityEventTest::onStaticSimple(const void* pSender, int& i)
415{
416 PriorityEventTest* p = const_cast<PriorityEventTest*>(reinterpret_cast<const PriorityEventTest*>(pSender));
417 p->_count++;
418}
419
420
421void PriorityEventTest::onStaticSimple2(void* pSender, int& i)
422{
423 PriorityEventTest* p = reinterpret_cast<PriorityEventTest*>(pSender);
424 p->_count++;
425}
426
427
428void PriorityEventTest::onStaticSimple3(int& i)
429{
430}
431
432
433void PriorityEventTest::onSimpleNoSender(int& i)
434{
435 _count++;
436}
437
438
439void PriorityEventTest::onSimple(const void* pSender, int& i)
440{
441 _count++;
442}
443
444void PriorityEventTest::onSimpleOther(const void* pSender, int& i)
445{
446 _count += LARGEINC ;
447}
448
449void PriorityEventTest::onConstSimple(const void* pSender, const int& i)
450{
451 _count++;
452}
453
454void PriorityEventTest::onComplex(const void* pSender, Poco::EventArgs* & i)
455{
456 _count++;
457}
458
459void PriorityEventTest::onComplex2(const void* pSender, Poco::EventArgs & i)
460{
461 _count++;
462}
463
464void PriorityEventTest::onConstComplex(const void* pSender, const Poco::EventArgs*& i)
465{
466 _count++;
467}
468
469void PriorityEventTest::onConst2Complex(const void* pSender, const Poco::EventArgs * const & i)
470{
471 _count++;
472}
473
474void PriorityEventTest::onAsync(const void* pSender, int& i)
475{
476 Poco::Thread::sleep(700);
477 _count += LARGEINC ;
478}
479
480int PriorityEventTest::getCount() const
481{
482 return _count;
483}
484
485void PriorityEventTest::setUp()
486{
487 _count = 0;
488 // must clear events, otherwise repeating test executions will fail
489 // because tests are only created once, only setup is called before
490 // each test run
491 Void.clear();
492 Simple.clear();
493 ConstSimple.clear();
494 Complex.clear();
495 Complex2.clear();
496 ConstComplex.clear();
497 Const2Complex.clear();
498}
499
500
501void PriorityEventTest::tearDown()
502{
503}
504
505
506CppUnit::Test* PriorityEventTest::suite()
507{
508 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PriorityEventTest");
509
510 CppUnit_addTest(pSuite, PriorityEventTest, testNoDelegate);
511 CppUnit_addTest(pSuite, PriorityEventTest, testSingleDelegate);
512 CppUnit_addTest(pSuite, PriorityEventTest, testReturnParams);
513 CppUnit_addTest(pSuite, PriorityEventTest, testDuplicateRegister);
514 CppUnit_addTest(pSuite, PriorityEventTest, testDuplicateUnregister);
515 CppUnit_addTest(pSuite, PriorityEventTest, testDisabling);
516 CppUnit_addTest(pSuite, PriorityEventTest, testPriorityOrder);
517 CppUnit_addTest(pSuite, PriorityEventTest, testPriorityOrderExpire);
518 CppUnit_addTest(pSuite, PriorityEventTest, testExpire);
519 CppUnit_addTest(pSuite, PriorityEventTest, testExpireReRegister);
520 CppUnit_addTest(pSuite, PriorityEventTest, testOverwriteDelegate);
521 CppUnit_addTest(pSuite, PriorityEventTest, testAsyncNotify);
522 return pSuite;
523}
524