Ticket #6660: boost_async_read_test.cc

File boost_async_read_test.cc, 3.6 KB (added by Sam Creasey <sammy@…>, 11 years ago)

Test program demonstrating async_read_until() behavior

Line 
1/*
2
3This is a test program to reproduce a bug which appears in the
4implementation of boost::asio::async_read_some() somewhere between
5boost 1.42.0 and 1.46.1. From the async_read_some() documentation:
6(http://www.boost.org/doc/libs/1_46_1/doc/html/boost_asio/reference/async_read_until/overload2.html)
7
8"If the streambuf's get area already contains the delimiter, this
9asynchronous operation completes immediately."
10
11This condition appears to be met under boost 1.42.0, and not under
12boost 1.46.1, boost 1.49.0, or boost trunk from subversion.
13
14Output on ubuntu 11.10, using boost 1.42.0:
15
16% ./boost_async_read_test
17Calling readline, streambuf:
18async_read_some, invocations: 1
19HandleLine: test line
20Calling readline, streambuf: more
21async_read_some, invocations: 2
22HandleLine: more lines
23Calling readline, streambuf: another line
24
25HandleLine: another line
26
27Output on ubuntu 11.10, using boost 1.46.1 (1.49.0 and trunk produce
28identical output):
29
30% ./boost_async_read_test
31Calling readline, streambuf:
32async_read_some, invocations: 1
33HandleLine: test line
34Calling readline, streambuf: more
35async_read_some, invocations: 2
36HandleLine: more lines
37Calling readline, streambuf: another line
38
39async_read_some, invocations: 3
40
41*/
42
43#include <list>
44#include <iostream>
45#include <string>
46
47#include <boost/asio.hpp>
48#include <boost/assert.hpp>
49#include <boost/bind.hpp>
50#include <boost/noncopyable.hpp>
51#include <boost/system/error_code.hpp>
52
53const std::string line1 = "test line\nmore ";
54const std::string line2 = "lines\nanother line\n";
55
56namespace asio = boost::asio;
57
58namespace {
59
60class StreamStub : boost::noncopyable {
61 public:
62 explicit StreamStub(asio::io_service& service)
63 : service_(service), invocations_(0) {}
64
65 asio::io_service& get_io_service() { return service_; }
66
67 template <typename MutableBufferSequence,
68 typename Handler>
69 void async_read_some(MutableBufferSequence mb, Handler h) {
70 ++invocations_;
71 std::cout << "async_read_some, invocations: " << invocations_ << "\n";
72 const std::string* line;
73 if (invocations_ == 1) {
74 line = &line1;
75 } else if (invocations_ == 2) {
76 line = &line2;
77 } else {
78 // don't call the handler on later reads
79 return;
80 }
81
82 size_t bufsize = asio::buffer_size(*mb.begin());
83 BOOST_ASSERT(bufsize >= line->size());
84 memcpy(asio::buffer_cast<char*>(*mb.begin()), line->data(), line->size());
85 h(boost::system::error_code(), line->size());
86 }
87
88 private:
89 asio::io_service& service_;
90 int invocations_;
91};
92
93class Reader : boost::noncopyable {
94 public:
95 Reader()
96 : stream_(service_) {}
97
98 void Readline() {
99 std::cout << "Calling readline, streambuf: " <<
100 std::string(
101 asio::buffer_cast<const char*>(*streambuf_.data().begin()),
102 asio::buffer_size(*streambuf_.data().begin())) <<
103 "\n";
104 asio::async_read_until(
105 stream_, streambuf_, "\n",
106 boost::bind(&Reader::HandleLine, this,
107 boost::asio::placeholders::error,
108 boost::asio::placeholders::bytes_transferred));
109 }
110
111 asio::io_service service_;
112
113 private:
114 void HandleLine(boost::system::error_code ec, size_t len) {
115 BOOST_ASSERT(!ec);
116
117 std::istream is(&streambuf_);
118 std::string line;
119 std::getline(is, line);
120 std::cout << "HandleLine: " << line << "\n";
121 }
122
123 StreamStub stream_;
124 std::list<std::string> lines_;
125 asio::streambuf streambuf_;
126
127};
128}
129
130int main(int ac, char *av[]) {
131
132 Reader reader;
133
134 reader.Readline();
135 reader.service_.poll();
136 reader.service_.reset();
137
138 reader.Readline();
139 reader.service_.poll();
140 reader.service_.reset();
141
142 reader.Readline();
143 reader.service_.poll();
144 reader.service_.reset();
145
146}