- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / asynchttprequest_unittest.cc
1 /*
2  * libjingle
3  * Copyright 2004--2011, Google Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  *  1. Redistributions of source code must retain the above copyright notice,
9  *     this list of conditions and the following disclaimer.
10  *  2. Redistributions in binary form must reproduce the above copyright notice,
11  *     this list of conditions and the following disclaimer in the documentation
12  *     and/or other materials provided with the distribution.
13  *  3. The name of the author may not be used to endorse or promote products
14  *     derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include <string>
29 #include "talk/base/asynchttprequest.h"
30 #include "talk/base/gunit.h"
31 #include "talk/base/httpserver.h"
32 #include "talk/base/socketstream.h"
33 #include "talk/base/thread.h"
34
35 namespace talk_base {
36
37 static const SocketAddress kServerAddr("127.0.0.1", 0);
38 static const SocketAddress kServerHostnameAddr("localhost", 0);
39 static const char kServerGetPath[] = "/get";
40 static const char kServerPostPath[] = "/post";
41 static const char kServerResponse[] = "This is a test";
42
43 class TestHttpServer : public HttpServer, public sigslot::has_slots<> {
44  public:
45   TestHttpServer(Thread* thread, const SocketAddress& addr) :
46       socket_(thread->socketserver()->CreateAsyncSocket(addr.family(),
47                                                         SOCK_STREAM)) {
48     socket_->Bind(addr);
49     socket_->Listen(5);
50     socket_->SignalReadEvent.connect(this, &TestHttpServer::OnAccept);
51   }
52
53   SocketAddress address() const { return socket_->GetLocalAddress(); }
54   void Close() const { socket_->Close(); }
55
56  private:
57   void OnAccept(AsyncSocket* socket) {
58     AsyncSocket* new_socket = socket_->Accept(NULL);
59     if (new_socket) {
60       HandleConnection(new SocketStream(new_socket));
61     }
62   }
63   talk_base::scoped_ptr<AsyncSocket> socket_;
64 };
65
66 class AsyncHttpRequestTest : public testing::Test,
67                              public sigslot::has_slots<> {
68  public:
69   AsyncHttpRequestTest()
70       : started_(false),
71         done_(false),
72         server_(Thread::Current(), kServerAddr) {
73     server_.SignalHttpRequest.connect(this, &AsyncHttpRequestTest::OnRequest);
74   }
75
76   bool started() const { return started_; }
77   bool done() const { return done_; }
78
79   AsyncHttpRequest* CreateGetRequest(const std::string& host, int port,
80                                      const std::string& path) {
81     talk_base::AsyncHttpRequest* request =
82         new talk_base::AsyncHttpRequest("unittest");
83     request->SignalWorkDone.connect(this,
84         &AsyncHttpRequestTest::OnRequestDone);
85     request->request().verb = talk_base::HV_GET;
86     request->set_host(host);
87     request->set_port(port);
88     request->request().path = path;
89     request->response().document.reset(new MemoryStream());
90     return request;
91   }
92   AsyncHttpRequest* CreatePostRequest(const std::string& host, int port,
93                                       const std::string& path,
94                                       const std::string content_type,
95                                       StreamInterface* content) {
96     talk_base::AsyncHttpRequest* request =
97         new talk_base::AsyncHttpRequest("unittest");
98     request->SignalWorkDone.connect(this,
99         &AsyncHttpRequestTest::OnRequestDone);
100     request->request().verb = talk_base::HV_POST;
101     request->set_host(host);
102     request->set_port(port);
103     request->request().path = path;
104     request->request().setContent(content_type, content);
105     request->response().document.reset(new MemoryStream());
106     return request;
107   }
108
109   const TestHttpServer& server() const { return server_; }
110
111  protected:
112   void OnRequest(HttpServer* server, HttpServerTransaction* t) {
113     started_ = true;
114
115     if (t->request.path == kServerGetPath) {
116       t->response.set_success("text/plain", new MemoryStream(kServerResponse));
117     } else if (t->request.path == kServerPostPath) {
118       // reverse the data and reply
119       size_t size;
120       StreamInterface* in = t->request.document.get();
121       StreamInterface* out = new MemoryStream();
122       in->GetSize(&size);
123       for (size_t i = 0; i < size; ++i) {
124         char ch;
125         in->SetPosition(size - i - 1);
126         in->Read(&ch, 1, NULL, NULL);
127         out->Write(&ch, 1, NULL, NULL);
128       }
129       out->Rewind();
130       t->response.set_success("text/plain", out);
131     } else {
132       t->response.set_error(404);
133     }
134     server_.Respond(t);
135   }
136   void OnRequestDone(SignalThread* thread) {
137     done_ = true;
138   }
139
140  private:
141   bool started_;
142   bool done_;
143   TestHttpServer server_;
144 };
145
146 TEST_F(AsyncHttpRequestTest, TestGetSuccess) {
147   AsyncHttpRequest* req = CreateGetRequest(
148       kServerHostnameAddr.hostname(), server().address().port(),
149       kServerGetPath);
150   EXPECT_FALSE(started());
151   req->Start();
152   EXPECT_TRUE_WAIT(started(), 5000);  // Should have started by now.
153   EXPECT_TRUE_WAIT(done(), 5000);
154   std::string response;
155   EXPECT_EQ(200U, req->response().scode);
156   ASSERT_TRUE(req->response().document);
157   req->response().document->Rewind();
158   req->response().document->ReadLine(&response);
159   EXPECT_EQ(kServerResponse, response);
160   req->Release();
161 }
162
163 TEST_F(AsyncHttpRequestTest, TestGetNotFound) {
164   AsyncHttpRequest* req = CreateGetRequest(
165       kServerHostnameAddr.hostname(), server().address().port(),
166       "/bad");
167   req->Start();
168   EXPECT_TRUE_WAIT(done(), 5000);
169   size_t size;
170   EXPECT_EQ(404U, req->response().scode);
171   ASSERT_TRUE(req->response().document);
172   req->response().document->GetSize(&size);
173   EXPECT_EQ(0U, size);
174   req->Release();
175 }
176
177 TEST_F(AsyncHttpRequestTest, TestGetToNonServer) {
178   AsyncHttpRequest* req = CreateGetRequest(
179       "127.0.0.1", server().address().port(),
180       kServerGetPath);
181   // Stop the server before we send the request.
182   server().Close();
183   req->Start();
184   EXPECT_TRUE_WAIT(done(), 10000);
185   size_t size;
186   EXPECT_EQ(500U, req->response().scode);
187   ASSERT_TRUE(req->response().document);
188   req->response().document->GetSize(&size);
189   EXPECT_EQ(0U, size);
190   req->Release();
191 }
192
193 TEST_F(AsyncHttpRequestTest, DISABLED_TestGetToInvalidHostname) {
194   AsyncHttpRequest* req = CreateGetRequest(
195       "invalid", server().address().port(),
196       kServerGetPath);
197   req->Start();
198   EXPECT_TRUE_WAIT(done(), 5000);
199   size_t size;
200   EXPECT_EQ(500U, req->response().scode);
201   ASSERT_TRUE(req->response().document);
202   req->response().document->GetSize(&size);
203   EXPECT_EQ(0U, size);
204   req->Release();
205 }
206
207 TEST_F(AsyncHttpRequestTest, TestPostSuccess) {
208   AsyncHttpRequest* req = CreatePostRequest(
209       kServerHostnameAddr.hostname(), server().address().port(),
210       kServerPostPath, "text/plain", new MemoryStream("abcd1234"));
211   req->Start();
212   EXPECT_TRUE_WAIT(done(), 5000);
213   std::string response;
214   EXPECT_EQ(200U, req->response().scode);
215   ASSERT_TRUE(req->response().document);
216   req->response().document->Rewind();
217   req->response().document->ReadLine(&response);
218   EXPECT_EQ("4321dcba", response);
219   req->Release();
220 }
221
222 // Ensure that we shut down properly even if work is outstanding.
223 TEST_F(AsyncHttpRequestTest, TestCancel) {
224   AsyncHttpRequest* req = CreateGetRequest(
225       kServerHostnameAddr.hostname(), server().address().port(),
226       kServerGetPath);
227   req->Start();
228   req->Destroy(true);
229 }
230
231 TEST_F(AsyncHttpRequestTest, TestGetSuccessDelay) {
232   AsyncHttpRequest* req = CreateGetRequest(
233       kServerHostnameAddr.hostname(), server().address().port(),
234       kServerGetPath);
235   req->set_start_delay(10);  // Delay 10ms.
236   req->Start();
237   Thread::SleepMs(5);
238   EXPECT_FALSE(started());  // Should not have started immediately.
239   EXPECT_TRUE_WAIT(started(), 5000);  // Should have started by now.
240   EXPECT_TRUE_WAIT(done(), 5000);
241   std::string response;
242   EXPECT_EQ(200U, req->response().scode);
243   ASSERT_TRUE(req->response().document);
244   req->response().document->Rewind();
245   req->response().document->ReadLine(&response);
246   EXPECT_EQ(kServerResponse, response);
247   req->Release();
248 }
249
250 }  // namespace talk_base