1//
2// NotificationQueueTest.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 "NotificationQueueTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/NotificationQueue.h"
15#include "Poco/Notification.h"
16#include "Poco/Thread.h"
17#include "Poco/Runnable.h"
18#include "Poco/RunnableAdapter.h"
19#include "Poco/Random.h"
20
21
22using Poco::NotificationQueue;
23using Poco::Notification;
24using Poco::Thread;
25using Poco::RunnableAdapter;
26
27
28namespace
29{
30 class QTestNotification: public Notification
31 {
32 public:
33 QTestNotification(const std::string& data): _data(data)
34 {
35 }
36 ~QTestNotification()
37 {
38 }
39 const std::string& data() const
40 {
41 return _data;
42 }
43
44 private:
45 std::string _data;
46 };
47}
48
49
50NotificationQueueTest::NotificationQueueTest(const std::string& rName): CppUnit::TestCase(rName)
51{
52}
53
54
55NotificationQueueTest::~NotificationQueueTest()
56{
57}
58
59
60void NotificationQueueTest::testQueueDequeue()
61{
62 NotificationQueue queue;
63 assertTrue (queue.empty());
64 assertTrue (queue.size() == 0);
65 Notification* pNf = queue.dequeueNotification();
66 assertNullPtr(pNf);
67 queue.enqueueNotification(new Notification);
68 assertTrue (!queue.empty());
69 assertTrue (queue.size() == 1);
70 pNf = queue.dequeueNotification();
71 assertNotNullPtr(pNf);
72 assertTrue (queue.empty());
73 assertTrue (queue.size() == 0);
74 pNf->release();
75
76 queue.enqueueNotification(new QTestNotification("first"));
77 queue.enqueueNotification(new QTestNotification("second"));
78 assertTrue (!queue.empty());
79 assertTrue (queue.size() == 2);
80 QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
81 assertNotNullPtr(pTNf);
82 assertTrue (pTNf->data() == "first");
83 pTNf->release();
84 assertTrue (!queue.empty());
85 assertTrue (queue.size() == 1);
86 pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
87 assertNotNullPtr(pTNf);
88 assertTrue (pTNf->data() == "second");
89 pTNf->release();
90 assertTrue (queue.empty());
91 assertTrue (queue.size() == 0);
92
93 pNf = queue.dequeueNotification();
94 assertNullPtr(pNf);
95}
96
97
98void NotificationQueueTest::testQueueDequeueUrgent()
99{
100 NotificationQueue queue;
101 queue.enqueueNotification(new QTestNotification("first"));
102 queue.enqueueNotification(new QTestNotification("second"));
103 queue.enqueueUrgentNotification(new QTestNotification("third"));
104 assertTrue (!queue.empty());
105 assertTrue (queue.size() == 3);
106 QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
107 assertNotNullPtr(pTNf);
108 assertTrue (pTNf->data() == "third");
109 pTNf->release();
110 assertTrue (!queue.empty());
111 assertTrue (queue.size() == 2);
112 pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
113 assertTrue (pTNf->data() == "first");
114 pTNf->release();
115 assertTrue (!queue.empty());
116 assertTrue (queue.size() == 1);
117 pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
118 assertNotNullPtr(pTNf);
119 assertTrue (pTNf->data() == "second");
120 pTNf->release();
121 assertTrue (queue.empty());
122 assertTrue (queue.size() == 0);
123
124 Notification* pNf = queue.dequeueNotification();
125 assertNullPtr(pNf);
126}
127
128
129void NotificationQueueTest::testWaitDequeue()
130{
131 NotificationQueue queue;
132 queue.enqueueNotification(new QTestNotification("third"));
133 queue.enqueueNotification(new QTestNotification("fourth"));
134 assertTrue (!queue.empty());
135 assertTrue (queue.size() == 2);
136 QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(10));
137 assertNotNullPtr(pTNf);
138 assertTrue (pTNf->data() == "third");
139 pTNf->release();
140 assertTrue (!queue.empty());
141 assertTrue (queue.size() == 1);
142 pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(10));
143 assertNotNullPtr(pTNf);
144 assertTrue (pTNf->data() == "fourth");
145 pTNf->release();
146 assertTrue (queue.empty());
147 assertTrue (queue.size() == 0);
148
149 Notification* pNf = queue.waitDequeueNotification(10);
150 assertNullPtr(pNf);
151}
152
153
154void NotificationQueueTest::testThreads()
155{
156 const int NOTIFICATION_COUNT = 5000;
157
158 Thread t1("thread1");
159 Thread t2("thread2");
160 Thread t3("thread3");
161
162 RunnableAdapter<NotificationQueueTest> ra(*this, &NotificationQueueTest::work);
163 t1.start(ra);
164 t2.start(ra);
165 t3.start(ra);
166 for (int i = 0; i < NOTIFICATION_COUNT; ++i)
167 {
168 _queue.enqueueNotification(new Notification);
169 }
170 while (!_queue.empty()) Thread::sleep(50);
171 Thread::sleep(20);
172 _queue.wakeUpAll();
173 t1.join();
174 t2.join();
175 t3.join();
176 assertTrue (_handled.size() == NOTIFICATION_COUNT);
177 assertTrue (_handled.count("thread1") > 0);
178 assertTrue (_handled.count("thread2") > 0);
179 assertTrue (_handled.count("thread3") > 0);
180}
181
182
183void NotificationQueueTest::testDefaultQueue()
184{
185 NotificationQueue& queue = NotificationQueue::defaultQueue();
186 assertTrue (queue.empty());
187 assertTrue (queue.size() == 0);
188}
189
190
191void NotificationQueueTest::testQueueRemove()
192{
193 NotificationQueue queue;
194 Notification::Ptr frontNotification = new QTestNotification("front");
195 Notification::Ptr middleNotification = new QTestNotification("middle");
196 Notification::Ptr backNotification = new QTestNotification("back");
197 queue.enqueueNotification(frontNotification);
198 queue.enqueueNotification(new QTestNotification("dummy"));
199 queue.enqueueNotification(middleNotification);
200 queue.enqueueNotification(new QTestNotification("dummy"));
201 queue.enqueueNotification(backNotification);
202 assertTrue (queue.size() == 5);
203 assertTrue (queue.remove(frontNotification));
204 assertTrue (queue.size() == 4);
205 assertTrue (queue.remove(middleNotification));
206 assertTrue (queue.size() == 3);
207 assertTrue (queue.remove(backNotification));
208 assertTrue (queue.size() == 2);
209 assertTrue (!queue.remove(backNotification));
210 assertTrue (queue.size() == 2);
211}
212
213
214void NotificationQueueTest::setUp()
215{
216 _handled.clear();
217}
218
219
220void NotificationQueueTest::tearDown()
221{
222}
223
224
225void NotificationQueueTest::work()
226{
227 Poco::Random rnd;
228 Thread::sleep(50);
229 Notification* pNf = _queue.waitDequeueNotification();
230 while (pNf)
231 {
232 pNf->release();
233 _mutex.lock();
234 _handled.insert(Thread::current()->name());
235 _mutex.unlock();
236 Thread::sleep(rnd.next(5));
237 pNf = _queue.waitDequeueNotification();
238 }
239}
240
241
242CppUnit::Test* NotificationQueueTest::suite()
243{
244 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("NotificationQueueTest");
245
246 CppUnit_addTest(pSuite, NotificationQueueTest, testQueueDequeue);
247 CppUnit_addTest(pSuite, NotificationQueueTest, testQueueDequeueUrgent);
248 CppUnit_addTest(pSuite, NotificationQueueTest, testWaitDequeue);
249 CppUnit_addTest(pSuite, NotificationQueueTest, testThreads);
250 CppUnit_addTest(pSuite, NotificationQueueTest, testDefaultQueue);
251 CppUnit_addTest(pSuite, NotificationQueueTest, testQueueRemove);
252
253 return pSuite;
254}
255