ChimeraTK-cppext 01.05.02
Loading...
Searching...
No Matches
testContinuations.cc
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3#define BOOST_TEST_MODULE test_future_queue
4#include <boost/test/included/unit_test.hpp>
5using namespace boost::unit_test_framework;
6
7#include "future_queue.hpp"
8
9BOOST_AUTO_TEST_SUITE(testContinuations)
10
11class MyException {};
12
13/*********************************************************************************************************************/
14
15BOOST_AUTO_TEST_CASE(testDeferredContinuation) {
17 std::atomic<size_t> continuationCounter;
18 continuationCounter = 0;
19
20 bool throwException = false;
21
22 auto qc = q.then<std::string>(
23 [&continuationCounter, &throwException](int x) {
24 if(throwException) throw MyException();
25 ++continuationCounter;
26 return std::to_string(x * 10);
27 },
28 std::launch::deferred);
29
30 usleep(100000);
31 BOOST_CHECK(qc.empty() == true);
32 BOOST_CHECK_EQUAL(continuationCounter, 0);
33 BOOST_CHECK(qc.pop() == false);
34 BOOST_CHECK_EQUAL(continuationCounter, 0);
35
36 q.push(1);
37 q.push(2);
38 q.push(3);
39 q.push(4);
40 q.push(5);
41
42 std::string res;
43
44 qc.pop(res);
45 BOOST_CHECK_EQUAL(res, "10");
46
47 qc.pop(res);
48 BOOST_CHECK_EQUAL(res, "20");
49
50 qc.pop(res);
51 BOOST_CHECK_EQUAL(res, "30");
52
53 qc.pop(res);
54 BOOST_CHECK_EQUAL(res, "40");
55
56 qc.pop(res);
57 BOOST_CHECK_EQUAL(res, "50");
58
59 // test with exception in input queue
60 try {
61 throw MyException();
62 }
63 catch(...) {
64 q.push_exception(std::current_exception());
65 }
66 BOOST_CHECK_THROW(qc.pop(res), MyException);
67 q.push(6);
68 qc.pop(res);
69 BOOST_CHECK_EQUAL(res, "60");
70 BOOST_CHECK(qc.pop() == false);
71
72 // test with exception thrown in continuation
73 throwException = true;
74 q.push(7);
75 BOOST_CHECK_THROW(qc.pop(res), MyException);
76 BOOST_CHECK(qc.pop() == false);
77
78 throwException = false;
79 q.push(8);
80 qc.pop(res);
81 BOOST_CHECK_EQUAL(res, "80");
82 BOOST_CHECK(qc.pop() == false);
83}
84
85/*********************************************************************************************************************/
86
87BOOST_AUTO_TEST_CASE(testDeferredContinuation_wait) {
89 std::atomic<size_t> continuationCounter;
90 continuationCounter = 0;
91
92 bool throwException = false;
93
94 auto qc = q.then<std::string>(
95 [&continuationCounter, &throwException](int x) {
96 if(throwException) throw MyException();
97 ++continuationCounter;
98 return std::to_string(x * 10);
99 },
100 std::launch::deferred);
101
102 usleep(100000);
103 BOOST_CHECK(qc.empty() == true);
104 BOOST_CHECK_EQUAL(continuationCounter, 0);
105
106 std::thread sender([&q] {
107 for(int i = 1; i < 6; ++i) {
108 usleep(100000);
109 q.push(i);
110 }
111 });
112
113 std::string res;
114
115 BOOST_CHECK_EQUAL(continuationCounter, 0);
116 qc.pop_wait(res);
117 BOOST_CHECK_EQUAL(continuationCounter, 1);
118 BOOST_CHECK_EQUAL(res, "10");
119
120 qc.pop_wait(res);
121 BOOST_CHECK_EQUAL(continuationCounter, 2);
122 BOOST_CHECK_EQUAL(res, "20");
123
124 qc.pop_wait(res);
125 BOOST_CHECK_EQUAL(continuationCounter, 3);
126 BOOST_CHECK_EQUAL(res, "30");
127
128 qc.pop_wait(res);
129 BOOST_CHECK_EQUAL(continuationCounter, 4);
130 BOOST_CHECK_EQUAL(res, "40");
131
132 usleep(200000);
133 BOOST_CHECK_EQUAL(continuationCounter, 4);
134
135 qc.pop_wait(res);
136 BOOST_CHECK_EQUAL(continuationCounter, 5);
137 BOOST_CHECK_EQUAL(res, "50");
138
139 // test with exception in input queue
140 try {
141 throw MyException();
142 }
143 catch(...) {
144 q.push_exception(std::current_exception());
145 }
146 BOOST_CHECK_THROW(qc.pop_wait(res), MyException);
147 q.push(6);
148 qc.pop_wait(res);
149 BOOST_CHECK_EQUAL(res, "60");
150 BOOST_CHECK(qc.pop() == false);
151
152 // test with exception thrown in continuation
153 throwException = true;
154 q.push(7);
155 BOOST_CHECK_THROW(qc.pop_wait(res), MyException);
156 BOOST_CHECK(qc.pop() == false);
157
158 throwException = false;
159 q.push(8);
160 qc.pop_wait(res);
161 BOOST_CHECK_EQUAL(res, "80");
162 BOOST_CHECK(qc.pop() == false);
163
164 sender.join();
165}
166
167/*********************************************************************************************************************/
168
169BOOST_AUTO_TEST_CASE(testAsyncContinuation) {
171 std::atomic<bool> throwException{false};
172
173 auto qc = q.then<std::string>(
174 [&throwException](int x) {
175 usleep(100000);
176 if(throwException) throw MyException();
177 return std::to_string(x * 10);
178 },
179 std::launch::async);
180
181 q.push(1);
182 q.push(2);
183 q.push(3);
184 q.push(4);
185 q.push(5);
186
187 std::string res;
188
189 BOOST_CHECK(qc.empty() == true);
190 qc.pop_wait(res);
191 BOOST_CHECK_EQUAL(res, "10");
192
193 BOOST_CHECK(qc.empty() == true);
194 qc.pop_wait(res);
195 BOOST_CHECK_EQUAL(res, "20");
196
197 BOOST_CHECK(qc.empty() == true);
198 qc.pop_wait(res);
199 BOOST_CHECK_EQUAL(res, "30");
200
201 BOOST_CHECK(qc.empty() == true);
202 qc.pop_wait(res);
203 BOOST_CHECK_EQUAL(res, "40");
204
205 BOOST_CHECK(qc.empty() == true);
206 qc.pop_wait(res);
207 BOOST_CHECK_EQUAL(res, "50");
208
209 // test with exception in input queue
210 try {
211 throw MyException();
212 }
213 catch(...) {
214 q.push_exception(std::current_exception());
215 }
216 BOOST_CHECK_THROW(qc.pop_wait(res), MyException);
217 q.push(6);
218 qc.pop_wait(res);
219 BOOST_CHECK_EQUAL(res, "60");
220 BOOST_CHECK(qc.pop() == false);
221
222 // test with exception thrown in continuation
223 throwException = true;
224 q.push(7);
225 BOOST_CHECK_THROW(qc.pop_wait(res), MyException);
226 BOOST_CHECK(qc.pop() == false);
227
228 throwException = false;
229 q.push(8);
230 qc.pop_wait(res);
231 BOOST_CHECK_EQUAL(res, "80");
232 BOOST_CHECK(qc.pop() == false);
233}
234
235/*********************************************************************************************************************/
236
237BOOST_AUTO_TEST_CASE(testDeferredContinuation_void) {
239 std::atomic<size_t> continuationCounter;
240 continuationCounter = 0;
241 bool throwException = false;
242
243 auto qc = q.then<void>(
244 [&continuationCounter, &throwException] {
245 if(throwException) throw MyException();
246 ++continuationCounter;
247 return;
248 },
249 std::launch::deferred);
250
251 usleep(100000);
252 BOOST_CHECK(qc.empty() == true);
253 BOOST_CHECK_EQUAL(continuationCounter, 0);
254 BOOST_CHECK(qc.pop() == false);
255 BOOST_CHECK_EQUAL(continuationCounter, 0);
256
257 q.push();
258 q.push();
259 q.push();
260 q.push();
261 q.push();
262
263 BOOST_CHECK(qc.pop() == true);
264 BOOST_CHECK(qc.pop() == true);
265 BOOST_CHECK(qc.pop() == true);
266 BOOST_CHECK(qc.pop() == true);
267 BOOST_CHECK(qc.pop() == true);
268
269 // test with exception in input queue
270 try {
271 throw MyException();
272 }
273 catch(...) {
274 q.push_exception(std::current_exception());
275 }
276 BOOST_CHECK_THROW(qc.pop(), MyException);
277 q.push();
278 BOOST_CHECK(qc.pop() == true);
279 BOOST_CHECK(qc.pop() == false);
280
281 // test with exception thrown in continuation
282 throwException = true;
283 q.push();
284 BOOST_CHECK_THROW(qc.pop(), MyException);
285 BOOST_CHECK(qc.pop() == false);
286
287 throwException = false;
288 q.push();
289 BOOST_CHECK(qc.pop() == true);
290 BOOST_CHECK(qc.pop() == false);
291}
292
293/*********************************************************************************************************************/
294
295BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_CASE(testDeferredContinuation)