1 /*
2  * Copyright (C) 2011 Emweb bv, Herent, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 
7 #include <Wt/WConfig.h>
8 
9 #ifdef WT_THREADED
10 
11 #include <boost/test/unit_test.hpp>
12 #include <thread>
13 #include <condition_variable>
14 #include <mutex>
15 
16 #include <Wt/WApplication.h>
17 #include <Wt/WIOService.h>
18 #include <Wt/Http/Client.h>
19 #include <Wt/Test/WTestEnvironment.h>
20 
21 using namespace Wt;
22 using namespace Wt::Http;
23 
24 namespace {
25 
26   class TestFixture : public WApplication
27   {
28   public:
TestFixture(const WEnvironment & env)29     TestFixture(const WEnvironment& env)
30       : WApplication(env),
31 	done_(false)
32     { }
33 
waitDone()34     void waitDone()
35     {
36       std::unique_lock<std::mutex> guard(doneMutex_);
37 
38       while (!done_)
39 	doneCondition_.wait(guard);
40     }
41 
reset()42     void reset()
43     {
44       done_ = false;
45     }
46 
onDone(Wt::AsioWrapper::error_code err,const Message & m)47     void onDone(Wt::AsioWrapper::error_code err, const Message& m)
48     {
49       assert (WApplication::instance() == this);
50 
51       std::unique_lock<std::mutex> guard(doneMutex_);
52 
53       err_ = err;
54       message_ = m;
55 
56       if (err_)
57 	std::cerr << "Http client error: " << err_.message() << std::endl;
58       else {
59 	std::cerr << "Http client result status: " << m.status() << std::endl;
60 	for (unsigned i = 0; i < m.headers().size(); ++i) {
61 	  const Message::Header& h = m.headers()[i];
62 	  std::cerr << " " << h.name() << ": " << h.value() << std::endl;
63 	}
64 	std::cerr << " Body: -----" << std::endl;
65 	std::cerr << m.body();
66 	std::cerr << "-----" << std::endl;
67       }
68 
69       done_ = true;
70       doneCondition_.notify_one();
71     }
72 
73   private:
74     bool done_;
75     std::condition_variable doneCondition_;
76     std::mutex doneMutex_;
77 
78     Wt::AsioWrapper::error_code err_;
79     Message message_;
80   };
81 }
82 
BOOST_AUTO_TEST_CASE(http_client_test1)83 BOOST_AUTO_TEST_CASE( http_client_test1 )
84 {
85   Wt::Test::WTestEnvironment environment;
86   TestFixture app(environment);
87 
88   std::unique_ptr<Client> c(new Client());
89   c->done().connect(std::bind(&TestFixture::onDone, &app,
90 			      std::placeholders::_1,
91 			      std::placeholders::_2));
92 
93   std::string ok = "www.google.com/";
94 
95   if (c->get("https://" + ok)) {
96     environment.endRequest();
97     app.waitDone();
98     environment.startRequest();
99   }
100 }
101 
BOOST_AUTO_TEST_CASE(http_client_test2)102 BOOST_AUTO_TEST_CASE( http_client_test2 )
103 {
104   Wt::Test::WTestEnvironment environment;
105   TestFixture app(environment);
106 
107   std::unique_ptr<Client> c(new Client());
108   c->done().connect(std::bind(&TestFixture::onDone, &app,
109 			      std::placeholders::_1,
110 			      std::placeholders::_2));
111 
112   std::string verifyFail = "pause.perl.org/";
113 
114   /* Does no longer fail! Too bad */
115   if (c->get("https://" + verifyFail)) {
116     environment.endRequest();
117     app.waitDone();
118     environment.startRequest();
119   }
120 }
121 
BOOST_AUTO_TEST_CASE(http_client_test3)122 BOOST_AUTO_TEST_CASE( http_client_test3 )
123 {
124   Wt::Test::WTestEnvironment environment;
125   TestFixture app(environment);
126 
127   std::unique_ptr<Client> c(new Client());
128   c->done().connect(std::bind(&TestFixture::onDone, &app,
129 			      std::placeholders::_1,
130 			      std::placeholders::_2));
131 
132   std::string asioFail = "www.google.be/";
133 
134   /* Asio no longer fails. Good! */
135   if (c->get("https://" + asioFail)) {
136     environment.endRequest();
137     app.waitDone();
138     environment.startRequest();
139   }
140 }
141 
BOOST_AUTO_TEST_CASE(http_client_test4)142 BOOST_AUTO_TEST_CASE( http_client_test4 )
143 {
144   Wt::Test::WTestEnvironment environment;
145   TestFixture app(environment);
146 
147   environment.server()->ioService().start();
148 
149   std::unique_ptr<Client> c(new Client());
150   c->done().connect(std::bind(&TestFixture::onDone, &app,
151 			      std::placeholders::_1,
152 			      std::placeholders::_2));
153 
154   std::string ok = "www.google.com/";
155 
156   if (c->get("https://" + ok)) {
157     environment.endRequest();
158     app.waitDone();
159     environment.startRequest();
160   }
161 
162   environment.server()->ioService().stop();
163   environment.server()->ioService().start();
164 
165   app.reset();
166 
167   if (c->get("https://" + ok)) {
168     environment.endRequest();
169     app.waitDone();
170     environment.startRequest();
171   }
172 }
173 
BOOST_AUTO_TEST_CASE(http_client_test5)174 BOOST_AUTO_TEST_CASE( http_client_test5 )
175 {
176   // Test parseUrl
177   Wt::Http::Client::URL url;
178   bool result = Wt::Http::Client::parseUrl(
179         "https://www.googleapis.com/calendar/v3/calendars/abcdefgh112233344444@group.calendar.google.com",
180         url);
181 
182   BOOST_REQUIRE(result);
183   BOOST_CHECK_EQUAL(url.auth, "");
184   BOOST_CHECK_EQUAL(url.protocol, "https");
185   BOOST_CHECK_EQUAL(url.host, "www.googleapis.com");
186   BOOST_CHECK_EQUAL(url.port, 443);
187   BOOST_CHECK_EQUAL(url.path, "/calendar/v3/calendars/abcdefgh112233344444@group.calendar.google.com");
188 }
189 
BOOST_AUTO_TEST_CASE(http_client_test6)190 BOOST_AUTO_TEST_CASE( http_client_test6 )
191 {
192   // Test parseUrl with auth
193   Wt::Http::Client::URL url;
194   bool result = Wt::Http::Client::parseUrl(
195         "http://foo:bar@example.com/a/b/c",
196         url);
197 
198   BOOST_REQUIRE(result);
199   BOOST_CHECK_EQUAL(url.auth, "foo:bar");
200   BOOST_CHECK_EQUAL(url.protocol, "http");
201   BOOST_CHECK_EQUAL(url.host, "example.com");
202   BOOST_CHECK_EQUAL(url.port, 80);
203   BOOST_CHECK_EQUAL(url.path, "/a/b/c");
204 }
205 
206 #endif // WT_THREADED
207