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