1//
2// read_until.cpp
3// ~~~~~~~~~~~~~~
4//
5// Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6//
7// Distributed under the Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9//
10
11// Disable autolinking for unit tests.
12#if !defined(BOOST_ALL_NO_LIB)
13#define BOOST_ALL_NO_LIB 1
14#endif // !defined(BOOST_ALL_NO_LIB)
15
16// Test that header file is self-contained.
17#include <boost/asio/read_until.hpp>
18
19#include <cstring>
20#include "archetypes/async_result.hpp"
21#include <boost/asio/io_service.hpp>
22#include <boost/asio/streambuf.hpp>
23#include "unit_test.hpp"
24
25#if defined(BOOST_ASIO_HAS_BOOST_BIND)
26# include <boost/bind.hpp>
27#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
28# include <functional>
29#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
30
31class test_stream
32{
33public:
34 typedef boost::asio::io_service io_service_type;
35
36 test_stream(boost::asio::io_service& io_service)
37 : io_service_(io_service),
38 length_(0),
39 position_(0),
40 next_read_length_(0)
41 {
42 }
43
44 io_service_type& get_io_service()
45 {
46 return io_service_;
47 }
48
49 void reset(const void* data, size_t length)
50 {
51 using namespace std; // For memcpy.
52
53 BOOST_ASIO_CHECK(length <= max_length);
54
55 memcpy(data_, data, length);
56 length_ = length;
57 position_ = 0;
58 next_read_length_ = length;
59 }
60
61 void next_read_length(size_t length)
62 {
63 next_read_length_ = length;
64 }
65
66 template <typename Mutable_Buffers>
67 size_t read_some(const Mutable_Buffers& buffers)
68 {
69 size_t n = boost::asio::buffer_copy(buffers,
70 boost::asio::buffer(data_, length_) + position_,
71 next_read_length_);
72 position_ += n;
73 return n;
74 }
75
76 template <typename Mutable_Buffers>
77 size_t read_some(const Mutable_Buffers& buffers,
78 boost::system::error_code& ec)
79 {
80 ec = boost::system::error_code();
81 return read_some(buffers);
82 }
83
84 template <typename Mutable_Buffers, typename Handler>
85 void async_read_some(const Mutable_Buffers& buffers, Handler handler)
86 {
87 size_t bytes_transferred = read_some(buffers);
88 io_service_.post(boost::asio::detail::bind_handler(
89 handler, boost::system::error_code(), bytes_transferred));
90 }
91
92private:
93 io_service_type& io_service_;
94 enum { max_length = 8192 };
95 char data_[max_length];
96 size_t length_;
97 size_t position_;
98 size_t next_read_length_;
99};
100
101static const char read_data[]
102 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
103
104void test_char_read_until()
105{
106 boost::asio::io_service ios;
107 test_stream s(ios);
108 boost::asio::streambuf sb1;
109 boost::asio::streambuf sb2(25);
110 boost::system::error_code ec;
111
112 s.reset(read_data, sizeof(read_data));
113 sb1.consume(sb1.size());
114 std::size_t length = boost::asio::read_until(s, sb1, 'Z');
115 BOOST_ASIO_CHECK(length == 26);
116
117 s.reset(read_data, sizeof(read_data));
118 s.next_read_length(1);
119 sb1.consume(sb1.size());
120 length = boost::asio::read_until(s, sb1, 'Z');
121 BOOST_ASIO_CHECK(length == 26);
122
123 s.reset(read_data, sizeof(read_data));
124 s.next_read_length(10);
125 sb1.consume(sb1.size());
126 length = boost::asio::read_until(s, sb1, 'Z');
127 BOOST_ASIO_CHECK(length == 26);
128
129 s.reset(read_data, sizeof(read_data));
130 sb1.consume(sb1.size());
131 length = boost::asio::read_until(s, sb1, 'Z', ec);
132 BOOST_ASIO_CHECK(!ec);
133 BOOST_ASIO_CHECK(length == 26);
134
135 s.reset(read_data, sizeof(read_data));
136 s.next_read_length(1);
137 sb1.consume(sb1.size());
138 length = boost::asio::read_until(s, sb1, 'Z', ec);
139 BOOST_ASIO_CHECK(!ec);
140 BOOST_ASIO_CHECK(length == 26);
141
142 s.reset(read_data, sizeof(read_data));
143 s.next_read_length(10);
144 sb1.consume(sb1.size());
145 length = boost::asio::read_until(s, sb1, 'Z', ec);
146 BOOST_ASIO_CHECK(!ec);
147 BOOST_ASIO_CHECK(length == 26);
148
149 s.reset(read_data, sizeof(read_data));
150 sb2.consume(sb2.size());
151 length = boost::asio::read_until(s, sb2, 'Z', ec);
152 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
153 BOOST_ASIO_CHECK(length == 0);
154
155 s.reset(read_data, sizeof(read_data));
156 s.next_read_length(1);
157 sb2.consume(sb2.size());
158 length = boost::asio::read_until(s, sb2, 'Z', ec);
159 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
160 BOOST_ASIO_CHECK(length == 0);
161
162 s.reset(read_data, sizeof(read_data));
163 s.next_read_length(10);
164 sb2.consume(sb2.size());
165 length = boost::asio::read_until(s, sb2, 'Z', ec);
166 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
167 BOOST_ASIO_CHECK(length == 0);
168
169 s.reset(read_data, sizeof(read_data));
170 sb2.consume(sb2.size());
171 length = boost::asio::read_until(s, sb2, 'Y', ec);
172 BOOST_ASIO_CHECK(!ec);
173 BOOST_ASIO_CHECK(length == 25);
174
175 s.reset(read_data, sizeof(read_data));
176 s.next_read_length(1);
177 sb2.consume(sb2.size());
178 length = boost::asio::read_until(s, sb2, 'Y', ec);
179 BOOST_ASIO_CHECK(!ec);
180 BOOST_ASIO_CHECK(length == 25);
181
182 s.reset(read_data, sizeof(read_data));
183 s.next_read_length(10);
184 sb2.consume(sb2.size());
185 length = boost::asio::read_until(s, sb2, 'Y', ec);
186 BOOST_ASIO_CHECK(!ec);
187 BOOST_ASIO_CHECK(length == 25);
188}
189
190void test_string_read_until()
191{
192 boost::asio::io_service ios;
193 test_stream s(ios);
194 boost::asio::streambuf sb1;
195 boost::asio::streambuf sb2(25);
196 boost::system::error_code ec;
197
198 s.reset(read_data, sizeof(read_data));
199 sb1.consume(sb1.size());
200 std::size_t length = boost::asio::read_until(s, sb1, "XYZ");
201 BOOST_ASIO_CHECK(length == 26);
202
203 s.reset(read_data, sizeof(read_data));
204 s.next_read_length(1);
205 sb1.consume(sb1.size());
206 length = boost::asio::read_until(s, sb1, "XYZ");
207 BOOST_ASIO_CHECK(length == 26);
208
209 s.reset(read_data, sizeof(read_data));
210 s.next_read_length(10);
211 sb1.consume(sb1.size());
212 length = boost::asio::read_until(s, sb1, "XYZ");
213 BOOST_ASIO_CHECK(length == 26);
214
215 s.reset(read_data, sizeof(read_data));
216 sb1.consume(sb1.size());
217 length = boost::asio::read_until(s, sb1, "XYZ", ec);
218 BOOST_ASIO_CHECK(!ec);
219 BOOST_ASIO_CHECK(length == 26);
220
221 s.reset(read_data, sizeof(read_data));
222 s.next_read_length(1);
223 sb1.consume(sb1.size());
224 length = boost::asio::read_until(s, sb1, "XYZ", ec);
225 BOOST_ASIO_CHECK(!ec);
226 BOOST_ASIO_CHECK(length == 26);
227
228 s.reset(read_data, sizeof(read_data));
229 s.next_read_length(10);
230 sb1.consume(sb1.size());
231 length = boost::asio::read_until(s, sb1, "XYZ", ec);
232 BOOST_ASIO_CHECK(!ec);
233 BOOST_ASIO_CHECK(length == 26);
234
235 s.reset(read_data, sizeof(read_data));
236 sb2.consume(sb2.size());
237 length = boost::asio::read_until(s, sb2, "XYZ", ec);
238 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
239 BOOST_ASIO_CHECK(length == 0);
240
241 s.reset(read_data, sizeof(read_data));
242 s.next_read_length(1);
243 sb2.consume(sb2.size());
244 length = boost::asio::read_until(s, sb2, "XYZ", ec);
245 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
246 BOOST_ASIO_CHECK(length == 0);
247
248 s.reset(read_data, sizeof(read_data));
249 s.next_read_length(10);
250 sb2.consume(sb2.size());
251 length = boost::asio::read_until(s, sb2, "XYZ", ec);
252 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
253 BOOST_ASIO_CHECK(length == 0);
254
255 s.reset(read_data, sizeof(read_data));
256 sb2.consume(sb2.size());
257 length = boost::asio::read_until(s, sb2, "WXY", ec);
258 BOOST_ASIO_CHECK(!ec);
259 BOOST_ASIO_CHECK(length == 25);
260
261 s.reset(read_data, sizeof(read_data));
262 s.next_read_length(1);
263 sb2.consume(sb2.size());
264 length = boost::asio::read_until(s, sb2, "WXY", ec);
265 BOOST_ASIO_CHECK(!ec);
266 BOOST_ASIO_CHECK(length == 25);
267
268 s.reset(read_data, sizeof(read_data));
269 s.next_read_length(10);
270 sb2.consume(sb2.size());
271 length = boost::asio::read_until(s, sb2, "WXY", ec);
272 BOOST_ASIO_CHECK(!ec);
273 BOOST_ASIO_CHECK(length == 25);
274}
275
276class match_char
277{
278public:
279 explicit match_char(char c) : c_(c) {}
280
281 template <typename Iterator>
282 std::pair<Iterator, bool> operator()(
283 Iterator begin, Iterator end) const
284 {
285 Iterator i = begin;
286 while (i != end)
287 if (c_ == *i++)
288 return std::make_pair(i, true);
289 return std::make_pair(i, false);
290 }
291
292private:
293 char c_;
294};
295
296namespace boost {
297namespace asio {
298 template <> struct is_match_condition<match_char>
299 {
300 enum { value = true };
301 };
302} // namespace asio
303} // namespace boost
304
305void test_match_condition_read_until()
306{
307 boost::asio::io_service ios;
308 test_stream s(ios);
309 boost::asio::streambuf sb1;
310 boost::asio::streambuf sb2(25);
311 boost::system::error_code ec;
312
313 s.reset(read_data, sizeof(read_data));
314 sb1.consume(sb1.size());
315 std::size_t length = boost::asio::read_until(s, sb1, match_char('Z'));
316 BOOST_ASIO_CHECK(length == 26);
317
318 s.reset(read_data, sizeof(read_data));
319 s.next_read_length(1);
320 sb1.consume(sb1.size());
321 length = boost::asio::read_until(s, sb1, match_char('Z'));
322 BOOST_ASIO_CHECK(length == 26);
323
324 s.reset(read_data, sizeof(read_data));
325 s.next_read_length(10);
326 sb1.consume(sb1.size());
327 length = boost::asio::read_until(s, sb1, match_char('Z'));
328 BOOST_ASIO_CHECK(length == 26);
329
330 s.reset(read_data, sizeof(read_data));
331 sb1.consume(sb1.size());
332 length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
333 BOOST_ASIO_CHECK(!ec);
334 BOOST_ASIO_CHECK(length == 26);
335
336 s.reset(read_data, sizeof(read_data));
337 s.next_read_length(1);
338 sb1.consume(sb1.size());
339 length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
340 BOOST_ASIO_CHECK(!ec);
341 BOOST_ASIO_CHECK(length == 26);
342
343 s.reset(read_data, sizeof(read_data));
344 s.next_read_length(10);
345 sb1.consume(sb1.size());
346 length = boost::asio::read_until(s, sb1, match_char('Z'), ec);
347 BOOST_ASIO_CHECK(!ec);
348 BOOST_ASIO_CHECK(length == 26);
349
350 s.reset(read_data, sizeof(read_data));
351 sb2.consume(sb2.size());
352 length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
353 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
354 BOOST_ASIO_CHECK(length == 0);
355
356 s.reset(read_data, sizeof(read_data));
357 s.next_read_length(1);
358 sb2.consume(sb2.size());
359 length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
360 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
361 BOOST_ASIO_CHECK(length == 0);
362
363 s.reset(read_data, sizeof(read_data));
364 s.next_read_length(10);
365 sb2.consume(sb2.size());
366 length = boost::asio::read_until(s, sb2, match_char('Z'), ec);
367 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
368 BOOST_ASIO_CHECK(length == 0);
369
370 s.reset(read_data, sizeof(read_data));
371 sb2.consume(sb2.size());
372 length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
373 BOOST_ASIO_CHECK(!ec);
374 BOOST_ASIO_CHECK(length == 25);
375
376 s.reset(read_data, sizeof(read_data));
377 s.next_read_length(1);
378 sb2.consume(sb2.size());
379 length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
380 BOOST_ASIO_CHECK(!ec);
381 BOOST_ASIO_CHECK(length == 25);
382
383 s.reset(read_data, sizeof(read_data));
384 s.next_read_length(10);
385 sb2.consume(sb2.size());
386 length = boost::asio::read_until(s, sb2, match_char('Y'), ec);
387 BOOST_ASIO_CHECK(!ec);
388 BOOST_ASIO_CHECK(length == 25);
389}
390
391void async_read_handler(
392 const boost::system::error_code& err, boost::system::error_code* err_out,
393 std::size_t bytes_transferred, std::size_t* bytes_out, bool* called)
394{
395 *err_out = err;
396 *bytes_out = bytes_transferred;
397 *called = true;
398}
399
400void test_char_async_read_until()
401{
402#if defined(BOOST_ASIO_HAS_BOOST_BIND)
403 namespace bindns = boost;
404#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
405 namespace bindns = std;
406 using std::placeholders::_1;
407 using std::placeholders::_2;
408#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
409
410 boost::asio::io_service ios;
411 test_stream s(ios);
412 boost::asio::streambuf sb1;
413 boost::asio::streambuf sb2(25);
414 boost::system::error_code ec;
415 std::size_t length;
416 bool called;
417
418 s.reset(read_data, sizeof(read_data));
419 ec = boost::system::error_code();
420 length = 0;
421 called = false;
422 sb1.consume(sb1.size());
423 boost::asio::async_read_until(s, sb1, 'Z',
424 bindns::bind(async_read_handler, _1, &ec,
425 _2, &length, &called));
426 ios.reset();
427 ios.run();
428 BOOST_ASIO_CHECK(called);
429 BOOST_ASIO_CHECK(!ec);
430 BOOST_ASIO_CHECK(length == 26);
431
432 s.reset(read_data, sizeof(read_data));
433 s.next_read_length(1);
434 ec = boost::system::error_code();
435 length = 0;
436 called = false;
437 sb1.consume(sb1.size());
438 boost::asio::async_read_until(s, sb1, 'Z',
439 bindns::bind(async_read_handler, _1, &ec,
440 _2, &length, &called));
441 ios.reset();
442 ios.run();
443 BOOST_ASIO_CHECK(called);
444 BOOST_ASIO_CHECK(!ec);
445 BOOST_ASIO_CHECK(length == 26);
446
447 s.reset(read_data, sizeof(read_data));
448 s.next_read_length(10);
449 ec = boost::system::error_code();
450 length = 0;
451 called = false;
452 sb1.consume(sb1.size());
453 boost::asio::async_read_until(s, sb1, 'Z',
454 bindns::bind(async_read_handler, _1, &ec,
455 _2, &length, &called));
456 ios.reset();
457 ios.run();
458 BOOST_ASIO_CHECK(called);
459 BOOST_ASIO_CHECK(!ec);
460 BOOST_ASIO_CHECK(length == 26);
461
462 s.reset(read_data, sizeof(read_data));
463 ec = boost::system::error_code();
464 length = 0;
465 called = false;
466 sb2.consume(sb2.size());
467 boost::asio::async_read_until(s, sb2, 'Z',
468 bindns::bind(async_read_handler, _1, &ec,
469 _2, &length, &called));
470 ios.reset();
471 ios.run();
472 BOOST_ASIO_CHECK(called);
473 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
474 BOOST_ASIO_CHECK(length == 0);
475
476 s.reset(read_data, sizeof(read_data));
477 s.next_read_length(1);
478 ec = boost::system::error_code();
479 length = 0;
480 called = false;
481 sb2.consume(sb2.size());
482 boost::asio::async_read_until(s, sb2, 'Z',
483 bindns::bind(async_read_handler, _1, &ec,
484 _2, &length, &called));
485 ios.reset();
486 ios.run();
487 BOOST_ASIO_CHECK(called);
488 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
489 BOOST_ASIO_CHECK(length == 0);
490
491 s.reset(read_data, sizeof(read_data));
492 s.next_read_length(10);
493 ec = boost::system::error_code();
494 length = 0;
495 called = false;
496 sb2.consume(sb2.size());
497 boost::asio::async_read_until(s, sb2, 'Z',
498 bindns::bind(async_read_handler, _1, &ec,
499 _2, &length, &called));
500 ios.reset();
501 ios.run();
502 BOOST_ASIO_CHECK(called);
503 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
504 BOOST_ASIO_CHECK(length == 0);
505
506 s.reset(read_data, sizeof(read_data));
507 ec = boost::system::error_code();
508 length = 0;
509 called = false;
510 sb2.consume(sb2.size());
511 boost::asio::async_read_until(s, sb2, 'Y',
512 bindns::bind(async_read_handler, _1, &ec,
513 _2, &length, &called));
514 ios.reset();
515 ios.run();
516 BOOST_ASIO_CHECK(called);
517 BOOST_ASIO_CHECK(!ec);
518 BOOST_ASIO_CHECK(length == 25);
519
520 s.reset(read_data, sizeof(read_data));
521 s.next_read_length(1);
522 ec = boost::system::error_code();
523 length = 0;
524 called = false;
525 sb2.consume(sb2.size());
526 boost::asio::async_read_until(s, sb2, 'Y',
527 bindns::bind(async_read_handler, _1, &ec,
528 _2, &length, &called));
529 ios.reset();
530 ios.run();
531 BOOST_ASIO_CHECK(called);
532 BOOST_ASIO_CHECK(!ec);
533 BOOST_ASIO_CHECK(length == 25);
534
535 s.reset(read_data, sizeof(read_data));
536 s.next_read_length(10);
537 ec = boost::system::error_code();
538 length = 0;
539 called = false;
540 sb2.consume(sb2.size());
541 boost::asio::async_read_until(s, sb2, 'Y',
542 bindns::bind(async_read_handler, _1, &ec,
543 _2, &length, &called));
544 ios.reset();
545 ios.run();
546 BOOST_ASIO_CHECK(called);
547 BOOST_ASIO_CHECK(!ec);
548 BOOST_ASIO_CHECK(length == 25);
549
550 s.reset(read_data, sizeof(read_data));
551 sb2.consume(sb2.size());
552 int i = boost::asio::async_read_until(s, sb2, 'Y',
553 archetypes::lazy_handler());
554 BOOST_ASIO_CHECK(i == 42);
555 ios.reset();
556 ios.run();
557}
558
559void test_string_async_read_until()
560{
561#if defined(BOOST_ASIO_HAS_BOOST_BIND)
562 namespace bindns = boost;
563#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
564 namespace bindns = std;
565 using std::placeholders::_1;
566 using std::placeholders::_2;
567#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
568
569 boost::asio::io_service ios;
570 test_stream s(ios);
571 boost::asio::streambuf sb1;
572 boost::asio::streambuf sb2(25);
573 boost::system::error_code ec;
574 std::size_t length;
575 bool called;
576
577 s.reset(read_data, sizeof(read_data));
578 ec = boost::system::error_code();
579 length = 0;
580 called = false;
581 sb1.consume(sb1.size());
582 boost::asio::async_read_until(s, sb1, "XYZ",
583 bindns::bind(async_read_handler, _1, &ec,
584 _2, &length, &called));
585 ios.reset();
586 ios.run();
587 BOOST_ASIO_CHECK(called);
588 BOOST_ASIO_CHECK(!ec);
589 BOOST_ASIO_CHECK(length == 26);
590
591 s.reset(read_data, sizeof(read_data));
592 s.next_read_length(1);
593 ec = boost::system::error_code();
594 length = 0;
595 called = false;
596 sb1.consume(sb1.size());
597 boost::asio::async_read_until(s, sb1, "XYZ",
598 bindns::bind(async_read_handler, _1, &ec,
599 _2, &length, &called));
600 ios.reset();
601 ios.run();
602 BOOST_ASIO_CHECK(called);
603 BOOST_ASIO_CHECK(!ec);
604 BOOST_ASIO_CHECK(length == 26);
605
606 s.reset(read_data, sizeof(read_data));
607 s.next_read_length(10);
608 ec = boost::system::error_code();
609 length = 0;
610 called = false;
611 sb1.consume(sb1.size());
612 boost::asio::async_read_until(s, sb1, "XYZ",
613 bindns::bind(async_read_handler, _1, &ec,
614 _2, &length, &called));
615 ios.reset();
616 ios.run();
617 BOOST_ASIO_CHECK(called);
618 BOOST_ASIO_CHECK(!ec);
619 BOOST_ASIO_CHECK(length == 26);
620
621 s.reset(read_data, sizeof(read_data));
622 ec = boost::system::error_code();
623 length = 0;
624 called = false;
625 sb2.consume(sb2.size());
626 boost::asio::async_read_until(s, sb2, "XYZ",
627 bindns::bind(async_read_handler, _1, &ec,
628 _2, &length, &called));
629 ios.reset();
630 ios.run();
631 BOOST_ASIO_CHECK(called);
632 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
633 BOOST_ASIO_CHECK(length == 0);
634
635 s.reset(read_data, sizeof(read_data));
636 s.next_read_length(1);
637 ec = boost::system::error_code();
638 length = 0;
639 called = false;
640 sb2.consume(sb2.size());
641 boost::asio::async_read_until(s, sb2, "XYZ",
642 bindns::bind(async_read_handler, _1, &ec,
643 _2, &length, &called));
644 ios.reset();
645 ios.run();
646 BOOST_ASIO_CHECK(called);
647 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
648 BOOST_ASIO_CHECK(length == 0);
649
650 s.reset(read_data, sizeof(read_data));
651 s.next_read_length(10);
652 ec = boost::system::error_code();
653 length = 0;
654 called = false;
655 sb2.consume(sb2.size());
656 boost::asio::async_read_until(s, sb2, "XYZ",
657 bindns::bind(async_read_handler, _1, &ec,
658 _2, &length, &called));
659 ios.reset();
660 ios.run();
661 BOOST_ASIO_CHECK(called);
662 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
663 BOOST_ASIO_CHECK(length == 0);
664
665 s.reset(read_data, sizeof(read_data));
666 ec = boost::system::error_code();
667 length = 0;
668 called = false;
669 sb2.consume(sb2.size());
670 boost::asio::async_read_until(s, sb2, "WXY",
671 bindns::bind(async_read_handler, _1, &ec,
672 _2, &length, &called));
673 ios.reset();
674 ios.run();
675 BOOST_ASIO_CHECK(called);
676 BOOST_ASIO_CHECK(!ec);
677 BOOST_ASIO_CHECK(length == 25);
678
679 s.reset(read_data, sizeof(read_data));
680 s.next_read_length(1);
681 ec = boost::system::error_code();
682 length = 0;
683 called = false;
684 sb2.consume(sb2.size());
685 boost::asio::async_read_until(s, sb2, "WXY",
686 bindns::bind(async_read_handler, _1, &ec,
687 _2, &length, &called));
688 ios.reset();
689 ios.run();
690 BOOST_ASIO_CHECK(called);
691 BOOST_ASIO_CHECK(!ec);
692 BOOST_ASIO_CHECK(length == 25);
693
694 s.reset(read_data, sizeof(read_data));
695 s.next_read_length(10);
696 ec = boost::system::error_code();
697 length = 0;
698 called = false;
699 sb2.consume(sb2.size());
700 boost::asio::async_read_until(s, sb2, "WXY",
701 bindns::bind(async_read_handler, _1, &ec,
702 _2, &length, &called));
703 ios.reset();
704 ios.run();
705 BOOST_ASIO_CHECK(called);
706 BOOST_ASIO_CHECK(!ec);
707 BOOST_ASIO_CHECK(length == 25);
708
709 s.reset(read_data, sizeof(read_data));
710 sb2.consume(sb2.size());
711 int i = boost::asio::async_read_until(s, sb2, "WXY",
712 archetypes::lazy_handler());
713 BOOST_ASIO_CHECK(i == 42);
714 ios.reset();
715 ios.run();
716}
717
718void test_match_condition_async_read_until()
719{
720#if defined(BOOST_ASIO_HAS_BOOST_BIND)
721 namespace bindns = boost;
722#else // defined(BOOST_ASIO_HAS_BOOST_BIND)
723 namespace bindns = std;
724 using std::placeholders::_1;
725 using std::placeholders::_2;
726#endif // defined(BOOST_ASIO_HAS_BOOST_BIND)
727
728 boost::asio::io_service ios;
729 test_stream s(ios);
730 boost::asio::streambuf sb1;
731 boost::asio::streambuf sb2(25);
732 boost::system::error_code ec;
733 std::size_t length;
734 bool called;
735
736 s.reset(read_data, sizeof(read_data));
737 ec = boost::system::error_code();
738 length = 0;
739 called = false;
740 sb1.consume(sb1.size());
741 boost::asio::async_read_until(s, sb1, match_char('Z'),
742 bindns::bind(async_read_handler, _1, &ec,
743 _2, &length, &called));
744 ios.reset();
745 ios.run();
746 BOOST_ASIO_CHECK(called);
747 BOOST_ASIO_CHECK(!ec);
748 BOOST_ASIO_CHECK(length == 26);
749
750 s.reset(read_data, sizeof(read_data));
751 s.next_read_length(1);
752 ec = boost::system::error_code();
753 length = 0;
754 called = false;
755 sb1.consume(sb1.size());
756 boost::asio::async_read_until(s, sb1, match_char('Z'),
757 bindns::bind(async_read_handler, _1, &ec,
758 _2, &length, &called));
759 ios.reset();
760 ios.run();
761 BOOST_ASIO_CHECK(called);
762 BOOST_ASIO_CHECK(!ec);
763 BOOST_ASIO_CHECK(length == 26);
764
765 s.reset(read_data, sizeof(read_data));
766 s.next_read_length(10);
767 ec = boost::system::error_code();
768 length = 0;
769 called = false;
770 sb1.consume(sb1.size());
771 boost::asio::async_read_until(s, sb1, match_char('Z'),
772 bindns::bind(async_read_handler, _1, &ec,
773 _2, &length, &called));
774 ios.reset();
775 ios.run();
776 BOOST_ASIO_CHECK(called);
777 BOOST_ASIO_CHECK(!ec);
778 BOOST_ASIO_CHECK(length == 26);
779
780 s.reset(read_data, sizeof(read_data));
781 ec = boost::system::error_code();
782 length = 0;
783 called = false;
784 sb2.consume(sb2.size());
785 boost::asio::async_read_until(s, sb2, match_char('Z'),
786 bindns::bind(async_read_handler, _1, &ec,
787 _2, &length, &called));
788 ios.reset();
789 ios.run();
790 BOOST_ASIO_CHECK(called);
791 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
792 BOOST_ASIO_CHECK(length == 0);
793
794 s.reset(read_data, sizeof(read_data));
795 s.next_read_length(1);
796 ec = boost::system::error_code();
797 length = 0;
798 called = false;
799 sb2.consume(sb2.size());
800 boost::asio::async_read_until(s, sb2, match_char('Z'),
801 bindns::bind(async_read_handler, _1, &ec,
802 _2, &length, &called));
803 ios.reset();
804 ios.run();
805 BOOST_ASIO_CHECK(called);
806 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
807 BOOST_ASIO_CHECK(length == 0);
808
809 s.reset(read_data, sizeof(read_data));
810 s.next_read_length(10);
811 ec = boost::system::error_code();
812 length = 0;
813 called = false;
814 sb2.consume(sb2.size());
815 boost::asio::async_read_until(s, sb2, match_char('Z'),
816 bindns::bind(async_read_handler, _1, &ec,
817 _2, &length, &called));
818 ios.reset();
819 ios.run();
820 BOOST_ASIO_CHECK(called);
821 BOOST_ASIO_CHECK(ec == boost::asio::error::not_found);
822 BOOST_ASIO_CHECK(length == 0);
823
824 s.reset(read_data, sizeof(read_data));
825 ec = boost::system::error_code();
826 length = 0;
827 called = false;
828 sb2.consume(sb2.size());
829 boost::asio::async_read_until(s, sb2, match_char('Y'),
830 bindns::bind(async_read_handler, _1, &ec,
831 _2, &length, &called));
832 ios.reset();
833 ios.run();
834 BOOST_ASIO_CHECK(called);
835 BOOST_ASIO_CHECK(!ec);
836 BOOST_ASIO_CHECK(length == 25);
837
838 s.reset(read_data, sizeof(read_data));
839 s.next_read_length(1);
840 ec = boost::system::error_code();
841 length = 0;
842 called = false;
843 sb2.consume(sb2.size());
844 boost::asio::async_read_until(s, sb2, match_char('Y'),
845 bindns::bind(async_read_handler, _1, &ec,
846 _2, &length, &called));
847 ios.reset();
848 ios.run();
849 BOOST_ASIO_CHECK(called);
850 BOOST_ASIO_CHECK(!ec);
851 BOOST_ASIO_CHECK(length == 25);
852
853 s.reset(read_data, sizeof(read_data));
854 s.next_read_length(10);
855 ec = boost::system::error_code();
856 length = 0;
857 called = false;
858 sb2.consume(sb2.size());
859 boost::asio::async_read_until(s, sb2, match_char('Y'),
860 bindns::bind(async_read_handler, _1, &ec,
861 _2, &length, &called));
862 ios.reset();
863 ios.run();
864 BOOST_ASIO_CHECK(called);
865 BOOST_ASIO_CHECK(!ec);
866 BOOST_ASIO_CHECK(length == 25);
867
868 s.reset(read_data, sizeof(read_data));
869 sb2.consume(sb2.size());
870 int i = boost::asio::async_read_until(s, sb2, match_char('Y'),
871 archetypes::lazy_handler());
872 BOOST_ASIO_CHECK(i == 42);
873 ios.reset();
874 ios.run();
875}
876
877BOOST_ASIO_TEST_SUITE
878(
879 "read_until",
880 BOOST_ASIO_TEST_CASE(test_char_read_until)
881 BOOST_ASIO_TEST_CASE(test_string_read_until)
882 BOOST_ASIO_TEST_CASE(test_match_condition_read_until)
883 BOOST_ASIO_TEST_CASE(test_char_async_read_until)
884 BOOST_ASIO_TEST_CASE(test_string_async_read_until)
885 BOOST_ASIO_TEST_CASE(test_match_condition_async_read_until)
886)
887