Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / beast / test / beast / core / basic_stream.cpp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 // Test that header file is self-contained.
11 #include <boost/beast/core/basic_stream.hpp>
12
13 #include "stream_tests.hpp"
14
15 #include <boost/beast/_experimental/unit_test/suite.hpp>
16 #include <boost/beast/core/flat_buffer.hpp>
17 #include <boost/beast/core/stream_traits.hpp>
18 #include <boost/beast/core/string.hpp>
19 #include <boost/beast/core/tcp_stream.hpp>
20 #include <boost/beast/http/message.hpp>
21 #include <boost/beast/http/empty_body.hpp>
22 #include <boost/beast/http/read.hpp>
23 #include <boost/beast/http/string_body.hpp>
24 #include <boost/beast/http/write.hpp>
25 #include <boost/asio/ip/tcp.hpp>
26 #include <boost/asio/spawn.hpp>
27 #include <boost/asio/strand.hpp>
28 #include <boost/asio/write.hpp>
29 #include <boost/optional.hpp>
30 #include <array>
31 #include <thread>
32
33 namespace boost {
34 namespace beast {
35
36 #if 0
37 template class basic_stream<
38     net::ip::tcp,
39     net::executor,
40     unlimited_rate_policy>;
41
42 template class basic_stream<
43     net::ip::tcp,
44     net::executor,
45     simple_rate_policy>;
46 #endif
47
48 namespace {
49
50 template<class Executor = net::io_context::executor_type>
51 class test_executor
52 {
53 public:
54     // VFALCO These need to be atomic or something
55     struct info
56     {
57         int dispatch = 0;
58         int post = 0;
59         int defer = 0;
60         int work = 0;
61         int total = 0;
62     };
63
64 private:
65     struct state
66     {
67         Executor ex;
68         info info_;
69
70         state(Executor const& ex_)
71             : ex(ex_)
72         {
73         }
74     };
75
76     std::shared_ptr<state> sp_;
77
78 public:
79     test_executor(test_executor const&) = default;
80     test_executor& operator=(test_executor const&) = default;
81
82     explicit
83     test_executor(Executor const& ex)
84         : sp_(std::make_shared<state>(ex))
85     {
86     }
87
88     decltype(sp_->ex.context())
89     context() const noexcept
90     {
91         return sp_->ex.context();
92     }
93
94     info&
95     operator*() noexcept
96     {
97         return sp_->info_;
98     }
99
100     info*
101     operator->() noexcept
102     {
103         return &sp_->info_;
104     }
105
106     void
107     on_work_started() const noexcept
108     {
109         ++sp_->info_.work;
110     }
111
112     void
113     on_work_finished() const noexcept
114     {
115     }
116
117     template<class F, class A>
118     void
119     dispatch(F&& f, A const& a)
120     {
121         ++sp_->info_.dispatch;
122         ++sp_->info_.total;
123         sp_->ex.dispatch(
124             std::forward<F>(f), a);
125     }
126
127     template<class F, class A>
128     void
129     post(F&& f, A const& a)
130     {
131         ++sp_->info_.post;
132         ++sp_->info_.total;
133         sp_->ex.post(
134             std::forward<F>(f), a);
135     }
136
137     template<class F, class A>
138     void
139     defer(F&& f, A const& a)
140     {
141         ++sp_->info_.defer;
142         ++sp_->info_.total;
143         sp_->ex.defer(
144             std::forward<F>(f), a);
145     }
146 };
147
148 struct test_acceptor
149 {
150     net::io_context ioc;
151     net::ip::tcp::acceptor a;
152     net::ip::tcp::endpoint ep;
153
154     test_acceptor()
155         : a(ioc)
156         , ep(net::ip::make_address_v4("127.0.0.1"), 0)
157     {
158         a.open(ep.protocol());
159         a.set_option(
160             net::socket_base::reuse_address(true));
161         a.bind(ep);
162         a.listen(net::socket_base::max_listen_connections);
163         ep = a.local_endpoint();
164         a.async_accept(
165             [](error_code, net::ip::tcp::socket)
166             {
167             });
168     }
169 };
170
171 class test_server
172 {
173     string_view s_;
174     std::ostream& log_;
175     net::io_context ioc_;
176     net::ip::tcp::acceptor acceptor_;
177     net::ip::tcp::socket socket_;
178     std::thread t_;
179
180     void
181     fail(error_code const& ec, string_view what)
182     {
183         if(ec != net::error::operation_aborted)
184             log_ << what << ": " << ec.message() << "\n";
185     }
186
187 public:
188     test_server(
189         string_view s,
190         net::ip::tcp::endpoint ep,
191         std::ostream& log)
192         : s_(s)
193         , log_(log)
194         , ioc_(1)
195         , acceptor_(ioc_)
196         , socket_(ioc_)
197     {
198         boost::system::error_code ec;
199
200         acceptor_.open(ep.protocol(), ec);
201         if(ec)
202         {
203             fail(ec, "open");
204             return;
205         }
206
207         acceptor_.set_option(
208             net::socket_base::reuse_address(true), ec);
209         if(ec)
210         {
211             fail(ec, "set_option");
212             return;
213         }
214
215         acceptor_.bind(ep, ec);
216         if(ec)
217         {
218             fail(ec, "bind");
219             return;
220         }
221
222         acceptor_.listen(
223             net::socket_base::max_listen_connections, ec);
224         if(ec)
225         {
226             fail(ec, "listen");
227             return;
228         }
229
230         acceptor_.async_accept(socket_,
231             [this](error_code ec)
232             {
233                 this->on_accept(ec);
234             });
235
236         t_ = std::thread(
237             [this]
238             {
239                 ioc_.run();
240             });
241     }
242
243     ~test_server()
244     {
245         ioc_.stop();
246         t_.join();
247     }
248
249     net::ip::tcp::endpoint
250     local_endpoint() const noexcept
251     {
252         return acceptor_.local_endpoint();
253     }
254
255 private:
256     class session
257         : public std::enable_shared_from_this<session>
258     {
259         string_view s_;
260         net::ip::tcp::socket socket_;
261         
262     public:
263         session(
264             string_view s,
265             net::ip::tcp::socket sock,
266             std::ostream&)
267             : s_(s)
268             , socket_(std::move(sock))
269         {
270         }
271
272         void
273         run()
274         {
275             if(s_.empty())
276                 socket_.async_wait(
277                     net::socket_base::wait_read,
278                     bind_front_handler(
279                         &session::on_read,
280                         shared_from_this()));
281             else
282                 net::async_write(
283                     socket_,
284                     net::const_buffer(s_.data(), s_.size()),
285                     bind_front_handler(
286                         &session::on_write,
287                         shared_from_this()));
288         }
289
290     protected:
291         void
292         on_read(error_code const&)
293         {
294         }
295
296         void
297         on_write(error_code const&, std::size_t)
298         {
299         }
300     };
301
302     void
303     on_accept(error_code const& ec)
304     {
305         if(! acceptor_.is_open())
306             return;
307         if(ec)
308             fail(ec, "accept");
309         else
310             std::make_shared<session>(
311                 s_, std::move(socket_), log_)->run();
312         acceptor_.async_accept(socket_,
313             [this](error_code ec)
314             {
315                 this->on_accept(ec);
316             });
317     }
318 };
319
320 } // (anon)
321
322 class basic_stream_test
323     : public beast::unit_test::suite
324 {
325 public:
326     using tcp = net::ip::tcp;
327     using strand = net::io_context::strand;
328     using executor = net::io_context::executor_type;
329
330     //--------------------------------------------------------------------------
331
332     void
333     testSpecialMembers()
334     {
335         net::io_context ioc;
336
337         // net::io_context::executor_type
338
339         {
340             auto ex = ioc.get_executor();
341             basic_stream<tcp, executor> s1(ioc);
342             basic_stream<tcp, executor> s2(ex);
343             basic_stream<tcp, executor> s3(ioc, tcp::v4());
344             basic_stream<tcp, executor> s4(std::move(s1));
345             s2.socket() =
346                 net::basic_stream_socket<tcp, executor>(ioc);
347             BEAST_EXPECT(s1.get_executor() == ex);
348             BEAST_EXPECT(s2.get_executor() == ex);
349             BEAST_EXPECT(s3.get_executor() == ex);
350             BEAST_EXPECT(s4.get_executor() == ex);
351
352             BEAST_EXPECT((! static_cast<
353                 basic_stream<tcp, executor> const&>(
354                     s2).socket().is_open()));
355
356             test_sync_stream<
357                 basic_stream<
358                     tcp, net::io_context::executor_type>>();
359
360             test_async_stream<
361                 basic_stream<
362                     tcp, net::io_context::executor_type>>();
363         }
364
365         // net::io_context::strand
366
367         {
368             auto ex = strand{ioc};
369             basic_stream<tcp, strand> s1(ex);
370             basic_stream<tcp, strand> s2(ex, tcp::v4());
371             basic_stream<tcp, strand> s3(std::move(s1));
372         #if 0
373             s2.socket() = net::basic_stream_socket<
374                 tcp, strand>(ioc);
375         #endif
376             BEAST_EXPECT(s1.get_executor() == ex);
377             BEAST_EXPECT(s2.get_executor() == ex);
378             BEAST_EXPECT(s3.get_executor() == ex);
379
380 #if 0
381             BEAST_EXPECT((! static_cast<
382                 basic_stream<tcp, strand> const&>(
383                     s2).socket().is_open()));
384 #endif
385
386             test_sync_stream<
387                 basic_stream<
388                     tcp, net::io_context::strand>>();
389
390             test_async_stream<
391                 basic_stream<
392                     tcp, net::io_context::strand>>();
393         }
394
395         // construction from existing socket
396
397 #if 0
398         {
399             tcp::socket sock(ioc);
400             basic_stream<tcp, executor> stream(std::move(sock));
401         }
402
403         {
404             tcp::socket sock(ioc);
405             basic_stream<tcp, strand> stream(std::move(sock));
406         }
407 #endif
408
409         // layers
410
411         {
412             net::socket_base::keep_alive opt;
413             tcp_stream s(ioc);
414             s.socket().open(tcp::v4());
415             s.socket().get_option(opt);
416             BEAST_EXPECT(! opt.value());
417             opt = true;
418             s.socket().set_option(opt);
419             opt = false;
420             BEAST_EXPECT(! opt.value());
421         }
422
423         // rate policies
424
425         {
426             basic_stream<tcp,
427                 net::io_context::executor_type,
428                 simple_rate_policy> s(ioc);
429         }
430
431         {
432             basic_stream<tcp,
433                 net::io_context::executor_type,
434                 simple_rate_policy> s(
435                     simple_rate_policy{}, ioc);
436         }
437
438         {
439             basic_stream<tcp,
440                 net::io_context::executor_type,
441                 unlimited_rate_policy> s(ioc);
442         }
443
444         {
445             basic_stream<tcp,
446                 net::io_context::executor_type,
447                 unlimited_rate_policy> s(
448                     unlimited_rate_policy{}, ioc);
449         }
450     }
451
452     class handler
453     {
454         boost::optional<error_code> ec_;
455         std::size_t n_;
456
457     public:
458         handler(error_code ec, std::size_t n)
459             : ec_(ec)
460             , n_(n)
461         {
462         }
463
464         handler(handler&& other)
465             : ec_(other.ec_)
466             , n_(boost::exchange(other.n_,
467                 (std::numeric_limits<std::size_t>::max)()))
468         {
469         }
470
471         ~handler()
472         {
473             BEAST_EXPECT(
474                 n_ == (std::numeric_limits<std::size_t>::max)());
475         }
476
477         void
478         operator()(error_code const& ec, std::size_t n)
479         {
480             BEAST_EXPECTS(ec == ec_, ec.message());
481             BEAST_EXPECT(n == n_);
482             n_ = (std::numeric_limits<std::size_t>::max)();
483         }
484     };
485
486     void
487     testRead()
488     {
489         using stream_type = basic_stream<tcp,
490             net::io_context::executor_type>;
491
492         char buf[4];
493         net::io_context ioc;
494         std::memset(buf, 0, sizeof(buf));
495         net::mutable_buffer mb(buf, sizeof(buf));
496         auto const ep = net::ip::tcp::endpoint(
497             net::ip::make_address("127.0.0.1"), 0);
498
499         // read_some
500
501         {
502             error_code ec;
503             stream_type s(ioc, tcp::v4());
504             BEAST_EXPECT(s.read_some(net::mutable_buffer{}) == 0);
505             BEAST_EXPECT(s.read_some(net::mutable_buffer{}, ec) == 0);
506             BEAST_EXPECTS(! ec, ec.message());
507         }
508
509         // async_read_some
510
511         {
512             // success
513             test_server srv("*", ep, log);
514             stream_type s(ioc);
515             s.socket().connect(srv.local_endpoint());
516             s.expires_never();
517             s.async_read_some(mb, handler({}, 1));
518             ioc.run();
519             ioc.restart();
520         }
521
522         {
523             // success, with timeout
524             test_server srv("*", ep, log);
525             stream_type s(ioc);
526             s.socket().connect(srv.local_endpoint());
527             s.expires_after(std::chrono::seconds(30));
528             s.async_read_some(mb, handler({}, 1));
529             ioc.run();
530             ioc.restart();
531         }
532
533         {
534             // empty buffer
535             test_server srv("*", ep, log);
536             stream_type s(ioc);
537             s.socket().connect(srv.local_endpoint());
538             s.expires_never();
539             s.async_read_some(
540                 net::mutable_buffer{}, handler({}, 0));
541             ioc.run();
542             ioc.restart();
543         }
544
545         {
546             // empty buffer, timeout
547             test_server srv("*", ep, log);
548             stream_type s(ioc);
549             s.socket().connect(srv.local_endpoint());
550             s.expires_after(std::chrono::seconds(0));
551             s.async_read_some(net::mutable_buffer{},
552                 handler(error::timeout, 0));
553             ioc.run();
554             ioc.restart();
555         }
556
557         {
558             // expires_after
559             test_server srv("", ep, log);
560             stream_type s(ioc);
561             s.socket().connect(srv.local_endpoint());
562             s.expires_after(std::chrono::seconds(0));
563             s.async_read_some(mb, handler(error::timeout, 0));
564             ioc.run();
565             ioc.restart();
566         }
567
568         {
569             // expires_at
570             test_server srv("", ep, log);
571             stream_type s(ioc);
572             s.socket().connect(srv.local_endpoint());
573             s.expires_at(std::chrono::steady_clock::now());
574             s.async_read_some(mb, handler(error::timeout, 0));
575             ioc.run();
576             ioc.restart();
577         }
578
579         {
580             // stream destroyed
581             test_server srv("", ep, log);
582             {
583                 stream_type s(ioc);
584                 s.socket().connect(srv.local_endpoint());
585                 s.expires_after(std::chrono::seconds(0));
586                 s.async_read_some(mb,
587                     [](error_code, std::size_t)
588                     {
589                     });
590             }
591             ioc.run();
592             ioc.restart();
593         }
594
595         {
596             // stale timer
597             test_acceptor a;
598             stream_type s(ioc);
599             s.expires_after(std::chrono::milliseconds(50));
600             s.async_read_some(mb,
601                 [](error_code, std::size_t)
602                 {
603                 });
604             std::this_thread::sleep_for(
605                 std::chrono::milliseconds(100));
606             ioc.run();
607             ioc.restart();
608         }
609
610         // abandoned operation
611         {
612             stream_type s(ioc);
613             s.async_read_some(net::mutable_buffer{},
614                 [](error_code, std::size_t)
615                 {
616                     BEAST_FAIL();
617                 });
618         }
619     }
620
621     void
622     testWrite()
623     {
624         using stream_type = basic_stream<tcp,
625             net::io_context::executor_type>;
626
627         char buf[4];
628         net::io_context ioc;
629         std::memset(buf, 0, sizeof(buf));
630         net::const_buffer cb(buf, sizeof(buf));
631         auto const ep = net::ip::tcp::endpoint(
632             net::ip::make_address("127.0.0.1"), 0);
633
634         // write_some
635
636         {
637             error_code ec;
638             stream_type s(ioc, tcp::v4());
639             BEAST_EXPECT(s.write_some(net::const_buffer{}) == 0);
640             BEAST_EXPECT(s.write_some(net::const_buffer{}, ec) == 0);
641             BEAST_EXPECTS(! ec, ec.message());
642         }
643
644         // async_write_some
645
646         {
647             // success
648             test_server srv("*", ep, log);
649             stream_type s(ioc);
650             s.socket().connect(srv.local_endpoint());
651             s.expires_never();
652             s.async_write_some(cb, handler({}, 4));
653             ioc.run();
654             ioc.restart();
655         }
656
657         {
658             // success, with timeout
659             test_server srv("*", ep, log);
660             stream_type s(ioc);
661             s.socket().connect(srv.local_endpoint());
662             s.expires_after(std::chrono::seconds(30));
663             s.async_write_some(cb, handler({}, 4));
664             ioc.run();
665             ioc.restart();
666         }
667
668         {
669             // empty buffer
670             test_server srv("*", ep, log);
671             stream_type s(ioc);
672             s.socket().connect(srv.local_endpoint());
673             s.expires_never();
674             s.async_write_some(
675                 net::const_buffer{}, handler({}, 0));
676             ioc.run();
677             ioc.restart();
678         }
679
680         {
681             // empty buffer, timeout
682             test_server srv("*", ep, log);
683             stream_type s(ioc);
684             s.socket().connect(srv.local_endpoint());
685             s.expires_after(std::chrono::seconds(0));
686             s.async_write_some(net::const_buffer{},
687                 handler(error::timeout, 0));
688             ioc.run();
689             ioc.restart();
690         }
691
692         // abandoned operation
693         {
694             stream_type s(ioc);
695             s.async_write_some(cb,
696                 [](error_code, std::size_t)
697                 {
698                     BEAST_FAIL();
699                 });
700         }
701     }
702
703     void
704     testConnect()
705     {
706         using stream_type = basic_stream<tcp,
707             net::io_context::executor_type>;
708
709         struct range
710         {
711             tcp::endpoint ep;
712
713             using iterator =
714                 tcp::endpoint const*;
715
716             // VFALCO This is here because asio mistakenly requires it
717             using const_iterator =
718                 tcp::endpoint const*;
719
720             iterator begin() const noexcept
721             {
722                 return &ep;
723             }
724
725             // VFALCO need to use const_iterator to silence
726             //        warning about unused types
727             const_iterator end() const noexcept
728             {
729                 return begin() + 1;
730             }
731         };
732
733         class connect_handler
734         {
735             bool pass_ = false;
736             boost::optional<error_code> expected_ = {};
737
738         public:
739             ~connect_handler()
740             {
741                 BEAST_EXPECT(pass_);
742             }
743
744             connect_handler()
745                 : expected_(error_code{})
746             {
747             }
748
749             explicit
750             connect_handler(error_code expected)
751                 : expected_(expected)
752             {
753             }
754
755             explicit
756             connect_handler(boost::none_t)
757             {
758             }
759
760             connect_handler(connect_handler&& other)
761                 : pass_(boost::exchange(other.pass_, true))
762                 , expected_(other.expected_)
763             {
764             }
765
766             void operator()(error_code ec)
767             {
768                 pass_ = true;
769                 if(expected_)
770                     BEAST_EXPECTS(
771                         ec == expected_, ec.message());
772             }
773         };
774
775         struct range_handler
776         {
777             bool pass = false;
778
779             range_handler() = default;
780
781             range_handler(range_handler&& other)
782                 : pass(boost::exchange(other.pass, true))
783             {
784             }
785
786             ~range_handler()
787             {
788                 BEAST_EXPECT(pass);
789             }
790
791             void operator()(error_code ec, tcp::endpoint)
792             {
793                 pass = true;
794                 BEAST_EXPECTS(! ec, ec.message());
795             }
796         };
797
798         struct iterator_handler
799         {
800             bool pass = false;
801
802             iterator_handler() = default;
803
804             iterator_handler(iterator_handler&& other)
805                 : pass(boost::exchange(other.pass, true))
806             {
807             }
808
809             ~iterator_handler()
810             {
811                 BEAST_EXPECT(pass);
812             }
813
814             void operator()(error_code ec, tcp::endpoint const*)
815             {
816                 pass = true;
817                 BEAST_EXPECTS(! ec, ec.message());
818             }
819         };
820
821         struct connect_condition
822         {
823             bool operator()(error_code, tcp::endpoint) const
824             {
825                 return true;
826             };
827         };
828
829         range r;
830         net::io_context ioc;
831         connect_condition cond;
832
833         // connect (member)
834
835         {
836             test_acceptor a;
837             stream_type s(ioc);
838             error_code ec;
839             s.connect(a.ep);
840             s.socket().close();
841             s.connect(a.ep, ec);
842             BEAST_EXPECTS(! ec, ec.message());
843         }
844
845         // connect
846
847         {
848             test_acceptor a;
849             stream_type s(ioc);
850             error_code ec;
851             r.ep = a.ep;
852             s.connect(r);
853             s.socket().close();
854             s.connect(r, ec);
855             BEAST_EXPECTS(! ec, ec.message());
856         }
857
858         {
859             test_acceptor a;
860             stream_type s(ioc);
861             error_code ec;
862             r.ep = a.ep;
863             s.connect(r, cond);
864             s.socket().close();
865             s.connect(r, cond, ec);
866             BEAST_EXPECTS(! ec, ec.message());
867         }
868
869         {
870             test_acceptor a;
871             stream_type s(ioc);
872             error_code ec;
873             r.ep = a.ep;
874             s.connect(r.begin(), r.end());
875             s.socket().close();
876             s.connect(r.begin(), r.end(), ec);
877             BEAST_EXPECTS(! ec, ec.message());
878         }
879
880         {
881             test_acceptor a;
882             stream_type s(ioc);
883             error_code ec;
884             r.ep = a.ep;
885             s.connect(r.begin(), r.end(), cond);
886             s.socket().close();
887             s.connect(r.begin(), r.end(), cond, ec);
888             BEAST_EXPECTS(! ec, ec.message());
889         }
890
891         // async_connect (member)
892
893         {
894             test_acceptor a;
895             stream_type s(ioc);
896             s.expires_never();
897             s.async_connect(a.ep, connect_handler{});
898             ioc.run();
899             ioc.restart();
900             s.socket().close();
901             s.expires_after(std::chrono::seconds(30));
902             s.async_connect(a.ep, connect_handler{});
903             ioc.run();
904             ioc.restart();
905         }
906
907         // async_connect
908
909         {
910             test_acceptor a;
911             stream_type s(ioc);
912             r.ep = a.ep;
913             s.expires_never();
914             s.async_connect(r, range_handler{});
915             ioc.run();
916             ioc.restart();
917             s.socket().close();
918             s.expires_after(std::chrono::seconds(30));
919             s.async_connect(r, range_handler{});
920             ioc.run();
921             ioc.restart();
922         }
923
924         {
925             test_acceptor a;
926             stream_type s(ioc);
927             r.ep = a.ep;
928             s.expires_never();
929             s.async_connect(r, cond, range_handler{});
930             ioc.run();
931             ioc.restart();
932             s.socket().close();
933             s.expires_after(std::chrono::seconds(30));
934             s.async_connect(r, cond, range_handler{});
935             ioc.run();
936             ioc.restart();
937         }
938
939         {
940             test_acceptor a;
941             stream_type s(ioc);
942             r.ep = a.ep;
943             s.expires_never();
944             s.async_connect(r.begin(), r.end(),
945                 iterator_handler{});
946             ioc.run();
947             ioc.restart();
948             s.socket().close();
949             s.expires_after(std::chrono::seconds(30));
950             s.async_connect(r.begin(), r.end(),
951                 iterator_handler{});
952             ioc.run();
953             ioc.restart();
954         }
955
956         {
957             test_acceptor a;
958             stream_type s(ioc);
959             r.ep = a.ep;
960             s.expires_never();
961             s.async_connect(r.begin(), r.end(), cond,
962                 iterator_handler{});
963             ioc.run();
964             ioc.restart();
965             s.socket().close();
966             s.expires_after(std::chrono::seconds(30));
967             s.async_connect(r.begin(), r.end(), cond,
968                 iterator_handler{});
969             ioc.run();
970             ioc.restart();
971         }
972 #if 0
973         // use_future
974
975         BEAST_EXPECT(static_cast<std::future<
976             tcp::endpoint>(*)(stream_type&,
977                 std::array<tcp::endpoint, 2> const&,
978                 net::use_future_t<>&&)>(
979                     &beast::async_connect));
980
981         BEAST_EXPECT(static_cast<std::future<
982             tcp::endpoint>(*)(stream_type&,
983                 std::array<tcp::endpoint, 2> const&,
984                 connect_condition const&,
985                 net::use_future_t<>&&)>(
986                     &beast::async_connect));
987
988         BEAST_EXPECT(static_cast<std::future<
989             tcp::endpoint const*>(*)(stream_type&,
990                 tcp::endpoint const*,
991                 tcp::endpoint const*,
992                 net::use_future_t<>&&)>(
993                     &beast::async_connect));
994
995         BEAST_EXPECT(static_cast<std::future<
996             tcp::endpoint const*>(*)(stream_type&,
997                 tcp::endpoint const*,
998                 tcp::endpoint const*,
999                 connect_condition const&,
1000                 net::use_future_t<>&&)>(
1001                     &beast::async_connect));
1002
1003         // yield_context
1004
1005         BEAST_EXPECT(static_cast<
1006             tcp::endpoint(*)(stream_type&,
1007                 std::array<tcp::endpoint, 2> const&,
1008                 net::yield_context&&)>(
1009                     &beast::async_connect));
1010
1011         BEAST_EXPECT(static_cast<
1012             tcp::endpoint(*)(stream_type&,
1013                 std::array<tcp::endpoint, 2> const&,
1014                 connect_condition const&,
1015                 net::yield_context&&)>(
1016                     &beast::async_connect));
1017
1018         BEAST_EXPECT(static_cast<
1019             tcp::endpoint const*(*)(stream_type&,
1020                 tcp::endpoint const*,
1021                 tcp::endpoint const*,
1022                 net::yield_context&&)>(
1023                     &beast::async_connect));
1024
1025         BEAST_EXPECT(static_cast<
1026             tcp::endpoint const*(*)(stream_type&,
1027                 tcp::endpoint const*,
1028                 tcp::endpoint const*,
1029                 connect_condition const&,
1030                 net::yield_context&&)>(
1031                     &beast::async_connect));
1032 #endif
1033
1034         //
1035         // async_connect timeout
1036         //
1037
1038         {
1039             // normal timeout
1040             // Requires timeout happen before ECONNREFUSED 
1041             stream_type s(ioc);
1042             auto const ep = net::ip::tcp::endpoint(
1043             #if 1
1044                 // This address _should_ be unconnectible
1045                 net::ip::make_address("72.5.65.111"), 1);
1046             #else
1047                 // On Travis ECONNREFUSED happens before the timeout
1048                 net::ip::make_address("127.0.0.1"), 1);
1049             #endif
1050             s.expires_after(std::chrono::seconds(0));
1051             s.async_connect(ep, connect_handler{error::timeout});
1052             ioc.run_for(std::chrono::seconds(1));
1053             ioc.restart();
1054         }
1055
1056         {
1057             // stream destroyed
1058             {
1059                 stream_type s(ioc);
1060                 auto const ep = net::ip::tcp::endpoint(
1061                     net::ip::make_address("127.0.0.1"), 1);
1062                 s.expires_after(std::chrono::seconds(0));
1063                 s.async_connect(ep, connect_handler{boost::none});
1064             }
1065             ioc.run();
1066             ioc.restart();
1067         }
1068
1069         {
1070             // stale timer
1071             test_acceptor a;
1072             stream_type s(ioc);
1073             s.expires_after(std::chrono::milliseconds(50));
1074             s.async_connect(a.ep, connect_handler{});
1075             std::this_thread::sleep_for(
1076                 std::chrono::milliseconds(100));
1077             ioc.run();
1078             ioc.restart();
1079         }
1080
1081         // abandoned operation
1082         {
1083             stream_type s(ioc);
1084             net::ip::tcp::endpoint ep(
1085                 net::ip::make_address_v4("127.0.0.1"), 1);
1086             s.async_connect(ep,
1087                 [](error_code)
1088                 {
1089                     BEAST_FAIL();
1090                 });
1091         }
1092     }
1093
1094     void
1095     testMembers()
1096     {
1097         using stream_type = basic_stream<tcp,
1098             net::io_context::executor_type>;
1099
1100         class handler
1101         {
1102             bool pass_ = false;
1103             boost::optional<error_code> expected_ = {};
1104
1105         public:
1106             ~handler()
1107             {
1108                 BEAST_EXPECT(pass_);
1109             }
1110
1111             handler()
1112                 : expected_(error_code{})
1113             {
1114             }
1115
1116             explicit
1117             handler(error_code expected)
1118                 : expected_(expected)
1119             {
1120             }
1121
1122             explicit
1123             handler(boost::none_t)
1124             {
1125             }
1126
1127             handler(handler&& other)
1128                 : pass_(boost::exchange(other.pass_, true))
1129                 , expected_(other.expected_)
1130             {
1131             }
1132
1133             void operator()(error_code ec, std::size_t)
1134             {
1135                 pass_ = true;
1136                 if(expected_)
1137                     BEAST_EXPECTS(
1138                         ec == expected_, ec.message());
1139             }
1140         };
1141
1142         auto const ep = net::ip::tcp::endpoint(
1143             net::ip::make_address("127.0.0.1"), 0);
1144
1145         char buf[4];
1146         net::io_context ioc;
1147         auto mb = net::buffer(buf);
1148         std::memset(buf, 0, sizeof(buf));
1149
1150         // cancel
1151
1152         {
1153             test_server srv("", ep, log);
1154             stream_type s(ioc);
1155             s.connect(srv.local_endpoint());
1156             s.expires_never();
1157             s.socket().async_read_some(mb, handler(
1158                 net::error::operation_aborted));
1159             s.cancel();
1160             ioc.run();
1161             ioc.restart();
1162         }
1163
1164         // close
1165
1166         {
1167             test_server srv("", ep, log);
1168             stream_type s(ioc);
1169             s.connect(srv.local_endpoint());
1170             s.expires_never();
1171             s.socket().async_read_some(mb,
1172                 handler(boost::none));
1173             s.close();
1174             ioc.run();
1175             ioc.restart();
1176         }
1177
1178         // destructor
1179
1180         {
1181             test_server srv("", ep, log);
1182             {
1183                 stream_type s(ioc);
1184                 s.connect(srv.local_endpoint());
1185                 s.expires_never();
1186                 s.socket().async_read_some(mb,
1187                     handler(boost::none));
1188             }
1189             ioc.run();
1190             ioc.restart();
1191         }
1192
1193         // customization points
1194
1195         {
1196             stream_type s(ioc);
1197             beast::close_socket(s);
1198         }
1199
1200         {
1201             error_code ec;
1202             stream_type s(ioc);
1203             teardown(role_type::client, s, ec);
1204         }
1205
1206         {
1207             stream_type s(ioc);
1208             async_teardown(role_type::server, s,
1209                 [](error_code)
1210                 {
1211                 });
1212         }
1213     }
1214
1215     //--------------------------------------------------------------------------
1216
1217     http::response<http::string_body>
1218     make_response(http::request<http::empty_body>)
1219     {
1220         return {};
1221     }
1222     void process_http_1 (tcp_stream& stream, net::yield_context yield)
1223     {
1224         flat_buffer buffer;
1225         http::request<http::empty_body> req;
1226
1227         // Read the request, with a 15 second timeout
1228         stream.expires_after(std::chrono::seconds(15));
1229         http::async_read(stream, buffer, req, yield);
1230
1231         // Calculate the response
1232         http::response<http::string_body> res = make_response(req);
1233
1234         // Send the response, with a 30 second timeout.
1235         stream.expires_after (std::chrono::seconds(30));
1236         http::async_write (stream, res, yield);
1237     }
1238
1239     void process_http_2 (tcp_stream& stream, net::yield_context yield)
1240     {
1241         flat_buffer buffer;
1242         http::request<http::empty_body> req;
1243
1244         // Require that the read and write combined take no longer than 30 seconds
1245         stream.expires_after(std::chrono::seconds(30));
1246
1247         http::async_read(stream, buffer, req, yield);
1248
1249         http::response<http::string_body> res = make_response(req);
1250         http::async_write (stream, res, yield);
1251     }
1252
1253     void
1254     testJavadocs()
1255     {
1256         BEAST_EXPECT(&basic_stream_test::process_http_1);
1257         BEAST_EXPECT(&basic_stream_test::process_http_2);
1258     }
1259
1260     //--------------------------------------------------------------------------
1261
1262     void
1263     testIssue1589()
1264     {
1265         net::io_context ioc;
1266
1267         // the timer needlessly used polymorphic executor
1268         basic_stream<
1269             net::ip::tcp,
1270             net::io_context::executor_type>{ioc};
1271
1272         // make sure strands work
1273         basic_stream<
1274             net::ip::tcp,
1275             net::strand<
1276                 net::io_context::executor_type>>{
1277                     net::make_strand(ioc)};
1278
1279         // address the problem in the issue
1280         {
1281             net::basic_stream_socket<
1282                 net::ip::tcp,
1283                 net::strand<
1284                     net::io_context::executor_type>
1285                         > sock(net::make_strand(ioc));
1286             basic_stream<
1287                 net::ip::tcp,
1288                 net::strand<
1289                     net::io_context::executor_type>,
1290                 unlimited_rate_policy> stream(std::move(sock));
1291             BOOST_STATIC_ASSERT(
1292                 std::is_convertible<
1293                     decltype(sock)::executor_type,
1294                     decltype(stream)::executor_type>::value);
1295         }
1296     }
1297
1298     //--------------------------------------------------------------------------
1299
1300     void
1301     run()
1302     {
1303         testSpecialMembers();
1304         testRead();
1305         testWrite();
1306         testConnect();
1307         testMembers();
1308         testJavadocs();
1309         testIssue1589();
1310     }
1311 };
1312
1313 BEAST_DEFINE_TESTSUITE(beast,core,basic_stream);
1314
1315 } // beast
1316 } // boost