1//
2// PriorityNotificationQueueTest.cpp
3//
4// Copyright (c) 2009, Applied Informatics Software Engineering GmbH.
5// and Contributors.
6//
7// SPDX-License-Identifier: BSL-1.0
8//
9
10
11#include "PriorityNotificationQueueTest.h"
12#include "Poco/CppUnit/TestCaller.h"
13#include "Poco/CppUnit/TestSuite.h"
14#include "Poco/PriorityNotificationQueue.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::PriorityNotificationQueue;
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
50PriorityNotificationQueueTest::PriorityNotificationQueueTest(const std::string& rName): CppUnit::TestCase(rName)
51{
52}
53
54
55PriorityNotificationQueueTest::~PriorityNotificationQueueTest()
56{
57}
58
59
60void PriorityNotificationQueueTest::testQueueDequeue()
61{
62 PriorityNotificationQueue queue;
63 assertTrue (queue.empty());
64 assertTrue (queue.size() == 0);
65 Notification* pNf = queue.dequeueNotification();
66 assertNullPtr(pNf);
67 queue.enqueueNotification(new Notification, 1);
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"), 1);
77 queue.enqueueNotification(new QTestNotification("fourth"), 4);
78 queue.enqueueNotification(new QTestNotification("third"), 3);
79 queue.enqueueNotification(new QTestNotification("second"), 2);
80 assertTrue (!queue.empty());
81 assertTrue (queue.size() == 4);
82 QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
83 assertNotNullPtr(pTNf);
84 assertTrue (pTNf->data() == "first");
85 pTNf->release();
86 assertTrue (!queue.empty());
87 assertTrue (queue.size() == 3);
88 pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
89 assertNotNullPtr(pTNf);
90 assertTrue (pTNf->data() == "second");
91 pTNf->release();
92 assertTrue (!queue.empty());
93 assertTrue (queue.size() == 2);
94 pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
95 assertNotNullPtr(pTNf);
96 assertTrue (pTNf->data() == "third");
97 pTNf->release();
98 assertTrue (!queue.empty());
99 assertTrue (queue.size() == 1);
100 pTNf = dynamic_cast<QTestNotification*>(queue.dequeueNotification());
101 assertNotNullPtr(pTNf);
102 assertTrue (pTNf->data() == "fourth");
103 pTNf->release();
104 assertTrue (queue.empty());
105 assertTrue (queue.size() == 0);
106
107 pNf = queue.dequeueNotification();
108 assertNullPtr(pNf);
109}
110
111
112void PriorityNotificationQueueTest::testWaitDequeue()
113{
114 PriorityNotificationQueue queue;
115 queue.enqueueNotification(new QTestNotification("third"), 3);
116 queue.enqueueNotification(new QTestNotification("fourth"), 4);
117 assertTrue (!queue.empty());
118 assertTrue (queue.size() == 2);
119 QTestNotification* pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(10));
120 assertNotNullPtr(pTNf);
121 assertTrue (pTNf->data() == "third");
122 pTNf->release();
123 assertTrue (!queue.empty());
124 assertTrue (queue.size() == 1);
125 pTNf = dynamic_cast<QTestNotification*>(queue.waitDequeueNotification(10));
126 assertNotNullPtr(pTNf);
127 assertTrue (pTNf->data() == "fourth");
128 pTNf->release();
129 assertTrue (queue.empty());
130 assertTrue (queue.size() == 0);
131
132 Notification* pNf = queue.waitDequeueNotification(10);
133 assertNullPtr(pNf);
134}
135
136
137void PriorityNotificationQueueTest::testThreads()
138{
139 const int NOTIFICATION_COUNT = 5000;
140
141 Thread t1("thread1");
142 Thread t2("thread2");
143 Thread t3("thread3");
144
145 RunnableAdapter<PriorityNotificationQueueTest> ra(*this, &PriorityNotificationQueueTest::work);
146 t1.start(ra);
147 t2.start(ra);
148 t3.start(ra);
149 for (int i = 0; i < NOTIFICATION_COUNT; ++i)
150 {
151 _queue.enqueueNotification(new Notification, 1);
152 }
153 while (!_queue.empty()) Thread::sleep(50);
154 Thread::sleep(20);
155 _queue.wakeUpAll();
156 t1.join();
157 t2.join();
158 t3.join();
159 assertTrue (_handled.size() == NOTIFICATION_COUNT);
160 assertTrue (_handled.count("thread1") > 0);
161 assertTrue (_handled.count("thread2") > 0);
162 assertTrue (_handled.count("thread3") > 0);
163}
164
165
166void PriorityNotificationQueueTest::testDefaultQueue()
167{
168 PriorityNotificationQueue& queue = PriorityNotificationQueue::defaultQueue();
169 assertTrue (queue.empty());
170 assertTrue (queue.size() == 0);
171}
172
173
174void PriorityNotificationQueueTest::setUp()
175{
176 _handled.clear();
177}
178
179
180void PriorityNotificationQueueTest::tearDown()
181{
182}
183
184
185void PriorityNotificationQueueTest::work()
186{
187 Poco::Random rnd;
188 Thread::sleep(50);
189 Notification* pNf = _queue.waitDequeueNotification();
190 while (pNf)
191 {
192 pNf->release();
193 _mutex.lock();
194 _handled.insert(Thread::current()->name());
195 _mutex.unlock();
196 Thread::sleep(rnd.next(5));
197 pNf = _queue.waitDequeueNotification();
198 }
199}
200
201
202CppUnit::Test* PriorityNotificationQueueTest::suite()
203{
204 CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("PriorityNotificationQueueTest");
205
206 CppUnit_addTest(pSuite, PriorityNotificationQueueTest, testQueueDequeue);
207 CppUnit_addTest(pSuite, PriorityNotificationQueueTest, testWaitDequeue);
208 CppUnit_addTest(pSuite, PriorityNotificationQueueTest, testThreads);
209 CppUnit_addTest(pSuite, PriorityNotificationQueueTest, testDefaultQueue);
210
211 return pSuite;
212}
213