ChimeraTK-cppext 01.05.02
Loading...
Searching...
No Matches
testPushPop.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"
9
10#include <thread>
11
12BOOST_AUTO_TEST_SUITE(testPushPop)
13
14// test with a custom data type which is not known to the queue
15// we intentionally do not use a convenient standard-like interface to avoid
16// accidental usage of common operators etc.
17struct MovableDataType {
18 constexpr static int undef = -987654321;
20 explicit MovableDataType(int value) : _value(value) {}
21 MovableDataType(MovableDataType&& other) : _value(other._value) { other._value = undef; }
23 _value = other._value;
24 other._value = undef;
25 return *this;
26 }
27 int value() { return _value; }
28
29 private:
30 int _value{undef};
31};
32constexpr int MovableDataType::undef;
33
34/*********************************************************************************************************************/
35
36BOOST_AUTO_TEST_CASE(singleThreaded) {
37 std::cout << "singleThreaded" << std::endl;
38
39 // test up to a queue length of 100, start with 1
40 for(size_t length = 1; length <= 100; ++length) {
42
43 // single value transport
44 {
45 MovableDataType value(length + 42);
46 BOOST_CHECK(q1.push(std::move(value)) == true);
47 BOOST_CHECK_EQUAL(value.value(), MovableDataType::undef);
48 }
49 {
50 MovableDataType value;
51 BOOST_CHECK(q1.pop(value) == true);
52 BOOST_CHECK_EQUAL(value.value(), length + 42);
53 }
54
55 // transport maximum number of values at a time
56 for(size_t n = 0; n < length; ++n) {
57 MovableDataType value(length + n + 120);
58 BOOST_CHECK(q1.push(std::move(value)) == true);
59 BOOST_CHECK_EQUAL(value.value(), MovableDataType::undef);
60 }
61 for(size_t n = 0; n < length; ++n) {
62 MovableDataType value;
63 BOOST_CHECK(q1.pop(value) == true);
64 BOOST_CHECK_EQUAL(value.value(), length + n + 120);
65 }
66
67 // test correct behaviour if queue is full resp. empty
68 for(size_t n = 0; n < length; ++n) {
69 MovableDataType value(length + n + 120);
70 BOOST_CHECK(q1.push(std::move(value)) == true);
71 BOOST_CHECK_EQUAL(value.value(), MovableDataType::undef);
72 }
73 { // queue is already full
74 MovableDataType value(-666);
75 BOOST_CHECK(q1.push(std::move(value)) == false);
76 BOOST_CHECK_EQUAL(value.value(), -666);
77 }
78 for(size_t n = 0; n < length; ++n) {
79 MovableDataType value;
80 BOOST_CHECK(q1.pop(value) == true);
81 BOOST_CHECK_EQUAL(value.value(), length + n + 120);
82 }
83 { // queue is already empty
84 MovableDataType value(-777);
85 BOOST_CHECK(q1.pop(value) == false);
86 BOOST_CHECK_EQUAL(value.value(), -777);
87 }
88 }
89}
90
91/*********************************************************************************************************************/
92
93BOOST_AUTO_TEST_CASE(multiThreaded) {
94 std::cout << "multiThreaded" << std::endl;
95
96 // test up to a queue length of 100, start with 1
97 for(size_t length = 1; length <= 100; ++length) {
99
100 // single value transport
101 {
102 std::thread sender([&q1, length] {
103 MovableDataType value(length + 42);
104 BOOST_CHECK_TS(q1.push(std::move(value)) == true);
106 }); // end sender thread
107 std::thread receiver([&q1, length] {
108 MovableDataType value;
109 BOOST_CHECK_TIMEOUT(q1.pop(value) == true);
110 BOOST_CHECK_EQUAL_TS(value.value(), (signed)length + 42);
111 }); // end receiver thread
112 sender.join();
113 receiver.join();
114 }
115
116 // single value transport with pop_wait
117 {
118 std::thread receiver([&q1, length] {
119 MovableDataType value;
120 q1.pop_wait(value);
121 BOOST_CHECK_EQUAL_TS(value.value(), (signed)length + 42);
122 }); // end receiver thread
123 std::thread sender([&q1, length] {
124 MovableDataType value(length + 42);
125 usleep(10000); // intentionally slow down sender
126 BOOST_CHECK_TS(q1.push(std::move(value)) == true);
128 }); // end sender thread
129 sender.join();
130 receiver.join();
131 }
132
133 // transport maximum number of values at a time
134 {
135 std::thread sender([&q1, length] {
136 for(size_t n = 0; n < length; ++n) {
137 MovableDataType value(length + n + 120);
138 BOOST_CHECK_TS(q1.push(std::move(value)) == true);
140 }
141 }); // end sender thread
142 std::thread receiver([&q1, length] {
143 for(size_t n = 0; n < length; ++n) {
144 usleep(100); // intentionally slow down receiver
145 MovableDataType value;
146 BOOST_CHECK_TIMEOUT(q1.pop(value) == true);
147 BOOST_CHECK_EQUAL_TS(value.value(), (signed)length + (signed)n + 120);
148 }
149 }); // end receiver thread
150 sender.join();
151 receiver.join();
152 }
153
154 // transport values with pop_wait
155 {
156 std::thread receiver([&q1, length] {
157 for(size_t n = 0; n < length; ++n) {
158 MovableDataType value;
159 q1.pop_wait(value);
160 BOOST_CHECK_EQUAL_TS(value.value(), (signed)length + (signed)n + 120);
161 }
162 }); // end receiver thread
163 std::thread sender([&q1, length] {
164 for(size_t n = 0; n < length; ++n) {
165 usleep(100); // intentionally slow down sender
166 MovableDataType value(length + n + 120);
167 BOOST_CHECK_TS(q1.push(std::move(value)) == true);
169 }
170 }); // end sender thread
171 sender.join();
172 receiver.join();
173 }
174
175 // test correct behaviour if queue is full resp. empty
176 {
177 std::thread sender([&q1, length] {
178 for(size_t n = 0; n < length; ++n) {
179 MovableDataType value(length + n + 120);
180 BOOST_CHECK_TS(q1.push(std::move(value)) == true);
182 }
183 { // queue is already full
184 MovableDataType value(-666);
185 BOOST_CHECK_TS(q1.push(std::move(value)) == false);
186 BOOST_CHECK_EQUAL_TS(value.value(), -666);
187 }
188 }); // end sender thread
189 sender.join(); // otherwise the queue will never be full
190 std::thread receiver([&q1, length] {
191 for(size_t n = 0; n < length; ++n) {
192 MovableDataType value;
193 BOOST_CHECK_TS(q1.pop(value) == true);
194 BOOST_CHECK_EQUAL_TS(value.value(), (signed)length + (signed)n + 120);
195 }
196 { // queue is already empty
197 MovableDataType value(-777);
198 BOOST_CHECK_TS(q1.pop(value) == false);
199 BOOST_CHECK_EQUAL_TS(value.value(), -777);
200 }
201 }); // end receiver thread
202 receiver.join();
203 }
204 }
205}
206
207/*********************************************************************************************************************/
208
209BOOST_AUTO_TEST_SUITE_END()
MovableDataType(MovableDataType &&other)
MovableDataType & operator=(MovableDataType &&other)
static constexpr int undef
Definition testEmpty.cc:18
MovableDataType(int value)
BOOST_AUTO_TEST_CASE(singleThreaded)
#define BOOST_CHECK_TIMEOUT(condition)
#define BOOST_CHECK_EQUAL_TS(a, b)
#define BOOST_CHECK_TS(condition)