• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 //          Copyright Oliver Kowalke 2013.
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 #include <chrono>
8 #include <sstream>
9 #include <string>
10 #include <vector>
11 
12 #include <boost/assert.hpp>
13 #include <boost/test/unit_test.hpp>
14 
15 #include <boost/fiber/all.hpp>
16 
17 struct moveable {
18     bool    state;
19     int     value;
20 
moveablemoveable21     moveable() :
22         state( false),
23         value( -1) {
24     }
25 
moveablemoveable26     moveable( int v) :
27         state( true),
28         value( v) {
29     }
30 
moveablemoveable31     moveable( moveable && other) :
32         state( other.state),
33         value( other.value) {
34         other.state = false;
35         other.value = -1;
36     }
37 
operator =moveable38     moveable & operator=( moveable && other) {
39         if ( this == & other) return * this;
40         state = other.state;
41         other.state = false;
42         value = other.value;
43         other.value = -1;
44         return * this;
45     }
46 };
47 
test_push()48 void test_push() {
49     boost::fibers::unbuffered_channel< int > c;
50     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
51         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
52     });
53     int value = 0;
54     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
55     BOOST_CHECK_EQUAL( 1, value);
56     f.join();
57 }
58 
test_push_closed()59 void test_push_closed() {
60     boost::fibers::unbuffered_channel< int > c;
61     c.close();
62     BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push( 1) );
63 }
64 
65 
test_push_wait_for()66 void test_push_wait_for() {
67     boost::fibers::unbuffered_channel< int > c;
68     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
69         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
70     });
71     int value = 0;
72     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
73     BOOST_CHECK_EQUAL( 1, value);
74     f.join();
75 }
76 
test_push_wait_for_closed()77 void test_push_wait_for_closed() {
78     boost::fibers::unbuffered_channel< int > c;
79     c.close();
80     BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
81 }
82 
test_push_wait_for_timeout()83 void test_push_wait_for_timeout() {
84     boost::fibers::unbuffered_channel< int > c;
85     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
86         int value = 0;
87         BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
88         BOOST_CHECK_EQUAL( 1, value);
89     });
90     BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
91     BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_for( 1, std::chrono::seconds( 1) ) );
92     f.join();
93 }
94 
test_push_wait_until()95 void test_push_wait_until() {
96     boost::fibers::unbuffered_channel< int > c;
97     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
98         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
99                         std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
100     });
101     int value = 0;
102     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
103     BOOST_CHECK_EQUAL( 1, value);
104     f.join();
105 }
106 
test_push_wait_until_closed()107 void test_push_wait_until_closed() {
108     boost::fibers::unbuffered_channel< int > c;
109     c.close();
110     BOOST_CHECK( boost::fibers::channel_op_status::closed == c.push_wait_until( 1,
111                     std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
112 }
113 
test_push_wait_until_timeout()114 void test_push_wait_until_timeout() {
115     boost::fibers::unbuffered_channel< int > c;
116     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c](){
117         int value = 0;
118         BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( value) );
119         BOOST_CHECK_EQUAL( 1, value);
120     });
121     BOOST_CHECK( boost::fibers::channel_op_status::success == c.push_wait_until( 1,
122                 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
123     BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.push_wait_until( 1,
124                 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
125     f.join();
126 }
127 
test_pop()128 void test_pop() {
129     boost::fibers::unbuffered_channel< int > c;
130     int v1 = 2, v2 = 0;
131     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&v1,&c](){
132         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
133     });
134     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
135     BOOST_CHECK_EQUAL( v1, v2);
136     f.join();
137 }
138 
test_pop_closed()139 void test_pop_closed() {
140     boost::fibers::unbuffered_channel< int > c;
141     int v1 = 2, v2 = 0;
142     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&v1,&c](){
143         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
144         c.close();
145     });
146     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
147     BOOST_CHECK_EQUAL( v1, v2);
148     BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop( v2) );
149     f.join();
150 }
151 
test_pop_success()152 void test_pop_success() {
153     boost::fibers::unbuffered_channel< int > c;
154     int v1 = 2, v2 = 0;
155     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v2](){
156         BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( v2) );
157     });
158     BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
159     f.join();
160     BOOST_CHECK_EQUAL( v1, v2);
161 }
162 
test_value_pop()163 void test_value_pop() {
164     boost::fibers::unbuffered_channel< int > c;
165     int v1 = 2, v2 = 0;
166     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
167         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
168     });
169     v2 = c.value_pop();
170     f.join();
171     BOOST_CHECK_EQUAL( v1, v2);
172 }
173 
test_value_pop_closed()174 void test_value_pop_closed() {
175     boost::fibers::unbuffered_channel< int > c;
176     int v1 = 2;
177     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
178         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
179         c.close();
180     });
181     int v2 = c.value_pop();
182     BOOST_CHECK_EQUAL( v1, v2);
183     f.join();
184     bool thrown = false;
185     try {
186         c.value_pop();
187     } catch ( boost::fibers::fiber_error const&) {
188         thrown = true;
189     }
190     BOOST_CHECK( thrown);
191 }
192 
test_value_pop_success()193 void test_value_pop_success() {
194     boost::fibers::unbuffered_channel< int > c;
195     int v1 = 2, v2 = 0;
196     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v2](){
197         v2 = c.value_pop();
198     });
199     BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
200     f.join();
201     BOOST_CHECK_EQUAL( v1, v2);
202 }
203 
test_pop_wait_for()204 void test_pop_wait_for() {
205     boost::fibers::unbuffered_channel< int > c;
206     int v1 = 2, v2 = 0;
207     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
208         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
209     });
210     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
211     f.join();
212     BOOST_CHECK_EQUAL( v1, v2);
213 }
214 
test_pop_wait_for_closed()215 void test_pop_wait_for_closed() {
216     boost::fibers::unbuffered_channel< int > c;
217     int v1 = 2, v2 = 0;
218     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
219         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
220         c.close();
221     });
222     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
223     BOOST_CHECK_EQUAL( v1, v2);
224     BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
225     f.join();
226 }
227 
test_pop_wait_for_success()228 void test_pop_wait_for_success() {
229     boost::fibers::unbuffered_channel< int > c;
230     int v1 = 2, v2 = 0;
231     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v2](){
232         BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_for( v2, std::chrono::seconds( 1) ) );
233     });
234     BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
235     f.join();
236     BOOST_CHECK_EQUAL( v1, v2);
237 }
238 
test_pop_wait_for_timeout()239 void test_pop_wait_for_timeout() {
240     boost::fibers::unbuffered_channel< int > c;
241     int v = 0;
242     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v](){
243         BOOST_CHECK( boost::fibers::channel_op_status::timeout == c.pop_wait_for( v, std::chrono::seconds( 1) ) );
244     });
245     f.join();
246 }
247 
test_pop_wait_until()248 void test_pop_wait_until() {
249     boost::fibers::unbuffered_channel< int > c;
250     int v1 = 2, v2 = 0;
251     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
252         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
253     });
254     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
255             std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
256     BOOST_CHECK_EQUAL( v1, v2);
257     f.join();
258 }
259 
test_pop_wait_until_closed()260 void test_pop_wait_until_closed() {
261     boost::fibers::unbuffered_channel< int > c;
262     int v1 = 2, v2 = 0;
263     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v1](){
264         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
265         c.close();
266     });
267     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
268             std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
269     BOOST_CHECK_EQUAL( v1, v2);
270     BOOST_CHECK( boost::fibers::channel_op_status::closed == c.pop_wait_until( v2,
271             std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
272     f.join();
273 }
274 
test_pop_wait_until_success()275 void test_pop_wait_until_success() {
276     boost::fibers::unbuffered_channel< int > c;
277     int v1 = 2, v2 = 0;
278     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c,&v2](){
279         BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop_wait_until( v2,
280                     std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
281     });
282     BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( v1) );
283     f.join();
284     BOOST_CHECK_EQUAL( v1, v2);
285 }
286 
test_pop_wait_until_timeout()287 void test_pop_wait_until_timeout() {
288     boost::fibers::unbuffered_channel< int > c;
289     int v = 0;
290     BOOST_CHECK(
291             boost::fibers::channel_op_status::timeout == c.pop_wait_until( v,
292                 std::chrono::system_clock::now() + std::chrono::seconds( 1) ) );
293 }
294 
test_wm_1()295 void test_wm_1() {
296     boost::fibers::unbuffered_channel< int > c;
297     std::vector< boost::fibers::fiber::id > ids;
298     boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&c,&ids](){
299         ids.push_back( boost::this_fiber::get_id() );
300         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 1) );
301 
302         ids.push_back( boost::this_fiber::get_id() );
303         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 2) );
304 
305         ids.push_back( boost::this_fiber::get_id() );
306         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 3) );
307 
308         ids.push_back( boost::this_fiber::get_id() );
309         // would be blocked because channel is full
310         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 4) );
311 
312         ids.push_back( boost::this_fiber::get_id() );
313         // would be blocked because channel is full
314         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( 5) );
315 
316         ids.push_back( boost::this_fiber::get_id() );
317     });
318     boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&c,&ids](){
319         ids.push_back( boost::this_fiber::get_id() );
320         BOOST_CHECK_EQUAL( 1, c.value_pop() );
321 
322         // let other fiber run
323         boost::this_fiber::yield();
324 
325         ids.push_back( boost::this_fiber::get_id() );
326         BOOST_CHECK_EQUAL( 2, c.value_pop() );
327 
328         ids.push_back( boost::this_fiber::get_id() );
329         BOOST_CHECK_EQUAL( 3, c.value_pop() );
330 
331         ids.push_back( boost::this_fiber::get_id() );
332         BOOST_CHECK_EQUAL( 4, c.value_pop() );
333 
334         ids.push_back( boost::this_fiber::get_id() );
335         // would block because channel is empty
336         BOOST_CHECK_EQUAL( 5, c.value_pop() );
337 
338         ids.push_back( boost::this_fiber::get_id() );
339     });
340     boost::fibers::fiber::id id1 = f1.get_id();
341     boost::fibers::fiber::id id2 = f2.get_id();
342     f1.join();
343     f2.join();
344     BOOST_CHECK_EQUAL( 12u, ids.size() );
345     BOOST_CHECK_EQUAL( id1, ids[0]);
346     BOOST_CHECK_EQUAL( id2, ids[1]);
347     BOOST_CHECK_EQUAL( id1, ids[2]);
348     BOOST_CHECK_EQUAL( id2, ids[3]);
349     BOOST_CHECK_EQUAL( id2, ids[4]);
350     BOOST_CHECK_EQUAL( id1, ids[5]);
351     BOOST_CHECK_EQUAL( id2, ids[6]);
352     BOOST_CHECK_EQUAL( id1, ids[7]);
353     BOOST_CHECK_EQUAL( id2, ids[8]);
354     BOOST_CHECK_EQUAL( id1, ids[9]);
355     BOOST_CHECK_EQUAL( id2, ids[10]);
356     BOOST_CHECK_EQUAL( id1, ids[11]);
357 }
358 
test_moveable()359 void test_moveable() {
360     boost::fibers::unbuffered_channel< moveable > c;
361     boost::fibers::fiber f( boost::fibers::launch::dispatch, [&c]{
362         moveable m1( 3);
363         BOOST_CHECK( m1.state);
364         BOOST_CHECK_EQUAL( 3, m1.value);
365         BOOST_CHECK( boost::fibers::channel_op_status::success == c.push( std::move( m1) ) );
366     });
367     moveable m2;
368     BOOST_CHECK( ! m2.state);
369     BOOST_CHECK_EQUAL( -1, m2.value);
370     BOOST_CHECK( boost::fibers::channel_op_status::success == c.pop( m2) );
371     BOOST_CHECK( m2.state);
372     BOOST_CHECK_EQUAL( 3, m2.value);
373     f.join();
374 }
375 
test_rangefor()376 void test_rangefor() {
377     boost::fibers::unbuffered_channel< int > chan;
378     std::vector< int > vec;
379     boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&chan]{
380         chan.push( 1);
381         chan.push( 1);
382         chan.push( 2);
383         chan.push( 3);
384         chan.push( 5);
385         chan.push( 8);
386         chan.push( 12);
387         chan.close();
388     });
389     boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&vec,&chan]{
390         for ( int value : chan) {
391             vec.push_back( value);
392         }
393     });
394     f1.join();
395     f2.join();
396     BOOST_CHECK_EQUAL( 1, vec[0]);
397     BOOST_CHECK_EQUAL( 1, vec[1]);
398     BOOST_CHECK_EQUAL( 2, vec[2]);
399     BOOST_CHECK_EQUAL( 3, vec[3]);
400     BOOST_CHECK_EQUAL( 5, vec[4]);
401     BOOST_CHECK_EQUAL( 8, vec[5]);
402     BOOST_CHECK_EQUAL( 12, vec[6]);
403 }
404 
test_issue_181()405 void test_issue_181() {
406     boost::fibers::unbuffered_channel< int > chan;
407     boost::fibers::fiber f1( boost::fibers::launch::dispatch, [&chan]() {
408         auto state = chan.push( 1);
409         BOOST_CHECK( boost::fibers::channel_op_status::closed == state);
410     });
411     boost::fibers::fiber f2( boost::fibers::launch::dispatch, [&chan]() {
412         boost::this_fiber::sleep_for( std::chrono::milliseconds( 100) );
413         chan.close();
414     });
415     f2.join();
416     f1.join();
417 }
418 
init_unit_test_suite(int,char * [])419 boost::unit_test::test_suite * init_unit_test_suite( int, char* []) {
420     boost::unit_test::test_suite * test =
421         BOOST_TEST_SUITE("Boost.Fiber: unbuffered_channel test suite");
422 
423      test->add( BOOST_TEST_CASE( & test_push) );
424      test->add( BOOST_TEST_CASE( & test_push_closed) );
425      test->add( BOOST_TEST_CASE( & test_push_wait_for) );
426      test->add( BOOST_TEST_CASE( & test_push_wait_for_closed) );
427      test->add( BOOST_TEST_CASE( & test_push_wait_for_timeout) );
428      test->add( BOOST_TEST_CASE( & test_push_wait_until) );
429      test->add( BOOST_TEST_CASE( & test_push_wait_until_closed) );
430      test->add( BOOST_TEST_CASE( & test_push_wait_until_timeout) );
431      test->add( BOOST_TEST_CASE( & test_pop) );
432      test->add( BOOST_TEST_CASE( & test_pop_closed) );
433      test->add( BOOST_TEST_CASE( & test_pop_success) );
434      test->add( BOOST_TEST_CASE( & test_value_pop) );
435      test->add( BOOST_TEST_CASE( & test_value_pop_closed) );
436      test->add( BOOST_TEST_CASE( & test_value_pop_success) );
437      test->add( BOOST_TEST_CASE( & test_pop_wait_for) );
438      test->add( BOOST_TEST_CASE( & test_pop_wait_for_closed) );
439      test->add( BOOST_TEST_CASE( & test_pop_wait_for_success) );
440      test->add( BOOST_TEST_CASE( & test_pop_wait_for_timeout) );
441      test->add( BOOST_TEST_CASE( & test_pop_wait_until) );
442      test->add( BOOST_TEST_CASE( & test_pop_wait_until_closed) );
443      test->add( BOOST_TEST_CASE( & test_pop_wait_until_success) );
444      test->add( BOOST_TEST_CASE( & test_pop_wait_until_timeout) );
445      test->add( BOOST_TEST_CASE( & test_wm_1) );
446      test->add( BOOST_TEST_CASE( & test_moveable) );
447      test->add( BOOST_TEST_CASE( & test_rangefor) );
448      test->add( BOOST_TEST_CASE( & test_issue_181) );
449 
450     return test;
451 }
452