ChimeraTK-cppext 01.05.02
Loading...
Searching...
No Matches
testWhenAny.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(testWaitAny)
10
11// test with a custom data type which is not known to the queue
12// we intentionally do not use a convenient standard-like interface to avoid
13// accidental usage of common operators etc.
14struct MovableDataType {
15 constexpr static int undef = -987654321;
17 explicit MovableDataType(int value) : _value(value) {}
18 MovableDataType(MovableDataType&& other) : _value(other._value) { other._value = undef; }
20 _value = other._value;
21 other._value = undef;
22 return *this;
23 }
24 int value() const { return _value; }
25
26 private:
27 int _value{undef};
28};
29constexpr int MovableDataType::undef;
30
31/*********************************************************************************************************************/
32
33BOOST_AUTO_TEST_CASE(singleThreaded) { // note: multi-threaded test is part of the stresstest
34
35 // test up to 100 queues up to a queue length of 100
36 for(size_t length = 2; length <= 10; ++length) {
37 for(size_t nqueues = 1; nqueues <= 10; ++nqueues) {
38 std::list<cppext::future_queue<MovableDataType>> q;
39 for(size_t iq = 0; iq < nqueues; ++iq) {
40 q.emplace_back(length);
41 }
42
43 // create notification queue
44 auto nq = when_any(q.begin(), q.end());
45
46 // write once to a single queue and find the change with wait_any
47 size_t iq = 0;
48 for(auto& theQ : q) {
49 MovableDataType value(length * nqueues + iq);
50 theQ.push(std::move(value));
51 size_t id;
52 BOOST_CHECK(nq.pop(id));
53 BOOST_CHECK(id == iq);
54 MovableDataType readValue;
55 BOOST_CHECK(theQ.pop(readValue));
56 BOOST_CHECK_EQUAL(readValue.value(), length * nqueues + iq);
57 ++iq;
58 }
59
60 // write a mixed sequece to the queues and check that the order is
61 // properly reflected in the notification queue
62 for(size_t i = 0; i < length; ++i) {
63 iq = 0;
64 for(auto& theQ : q) {
65 MovableDataType value(length * nqueues + i + iq);
66 if(iq % 2 == 0) {
67 BOOST_CHECK(theQ.push(std::move(value)));
68 }
69 else {
70 BOOST_CHECK(theQ.push_overwrite(std::move(value)));
71 }
72 ++iq;
73 }
74 }
75 // all queues are now full, now overwrite the last written value in the
76 // first queue
77 {
78 MovableDataType value(42);
79 BOOST_CHECK(q.front().push_overwrite(std::move(value)) == false);
80 }
81 // check notifications in the notification queue (the overwrite in the
82 // first queue is not visible there!)
83 for(size_t i = 0; i < length; ++i) {
84 iq = 0;
85 for(auto& theQ : q) {
86 size_t id;
87 nq.pop_wait(id);
88 BOOST_CHECK(id == iq);
89 MovableDataType readValue;
90 BOOST_CHECK(theQ.pop(readValue));
91 if(i < length - 1 || iq > 0) {
92 BOOST_CHECK_EQUAL(readValue.value(), length * nqueues + i + iq);
93 }
94 else {
95 BOOST_CHECK_EQUAL(readValue.value(), 42); // was overwritten!
96 }
97 ++iq;
98 }
99 }
100 }
101 }
102}
103
104/*********************************************************************************************************************/
105
106BOOST_AUTO_TEST_CASE(calledWithFilledQueues) {
107 // test calling when_any with queues that already contain data
108
109 // test up to 100 queues up to a queue length of 100
110 for(size_t length = 2; length <= 10; ++length) {
111 for(size_t nqueues = 1; nqueues <= 10; ++nqueues) {
112 std::vector<cppext::future_queue<MovableDataType>> q;
113 for(size_t iq = 0; iq < nqueues; ++iq) q.emplace_back(length);
114
115 // write once to a single queue
116 for(size_t iq = 0; iq < nqueues; ++iq) {
117 for(size_t i = 0; i < iq; ++i) { // note: writes might get rejected
118 // since the queue is too short
119 MovableDataType value(length * nqueues + iq + 3 * i);
120 if(iq % 2 == 0) {
121 q[iq].push_overwrite(std::move(value));
122 }
123 else {
124 q[iq].push(std::move(value));
125 }
126 }
127 }
128
129 // create notification queue
130 auto nq = when_any(q.begin(), q.end());
131
132 // find the previously written data with wait_any
133 for(size_t iq = 0; iq < nqueues; ++iq) {
134 for(size_t i = 0; i < std::min(iq, length); ++i) { // only check until length of the queue
135 size_t id;
136 BOOST_CHECK(nq.pop(id));
137 BOOST_CHECK(id == iq);
138 MovableDataType readValue;
139 BOOST_CHECK(q[iq].pop(readValue));
140 // don't compare the value since in case of push_overwrite this gets
141 // complicated...
142 }
143 }
144
145 // write a mixed sequece to the queues and check that the order is
146 // properly reflected in the notification queue
147 for(size_t i = 0; i < length; ++i) {
148 for(size_t iq = 0; iq < nqueues; ++iq) {
149 MovableDataType value(length * nqueues + i + iq);
150 BOOST_CHECK(q[iq].push(std::move(value)));
151 }
152 }
153 // all queues are now full, now overwrite the last written value in the
154 // first queue
155 {
156 MovableDataType value(42);
157 BOOST_CHECK(q.front().push_overwrite(std::move(value)) == false);
158 }
159 // check notifications in the notification queue (the overwrite in the
160 // first queue is not visible there!)
161 for(size_t i = 0; i < length; ++i) {
162 for(size_t iq = 0; iq < nqueues; ++iq) {
163 size_t id;
164 nq.pop_wait(id);
165 BOOST_CHECK(id == iq);
166 MovableDataType readValue;
167 BOOST_CHECK(q[iq].pop(readValue));
168 if(i < length - 1 || iq > 0) {
169 BOOST_CHECK_EQUAL(readValue.value(), length * nqueues + i + iq);
170 }
171 else {
172 BOOST_CHECK_EQUAL(readValue.value(), 42); // was overwritten!
173 }
174 }
175 }
176 }
177 }
178}
179
180/*********************************************************************************************************************/
181
182BOOST_AUTO_TEST_SUITE_END()
MovableDataType(MovableDataType &&other)
MovableDataType & operator=(MovableDataType &&other)
static constexpr int undef
Definition testEmpty.cc:18
MovableDataType(int value)
int value() const
BOOST_AUTO_TEST_CASE(singleThreaded)