1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file.
4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <vector>
6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/bind.h"
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/bind_helpers.h"
9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/compiler_specific.h"
10a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/format_macros.h"
11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/memory/ref_counted.h"
12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/memory/weak_ptr.h"
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/message_loop/message_loop.h"
15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/run_loop.h"
17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/strings/string_split.h"
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/strings/string_util.h"
19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/strings/stringprintf.h"
20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/time/time.h"
21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/base/address_list.h"
22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/base/io_buffer.h"
23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/base/ip_endpoint.h"
24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/base/net_errors.h"
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/base/net_log.h"
26a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/server/http_server.h"
27a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/server/http_server_request_info.h"
28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/socket/tcp_client_socket.h"
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/socket/tcp_listen_socket.h"
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/url_request/url_request_context.h"
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/url_request/url_request_context_getter.h"
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace net {
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
39a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace {
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void SetTimedOutAndQuitLoop(const base::WeakPtr<bool> timed_out,
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                            const base::Closure& quit_loop_func) {
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (timed_out) {
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    *timed_out = true;
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    quit_loop_func.Run();
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
48a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
49a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool RunLoopWithTimeout(base::RunLoop* run_loop) {
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool timed_out = false;
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::WeakPtrFactory<bool> timed_out_weak_factory(&timed_out);
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::MessageLoop::current()->PostDelayedTask(
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      FROM_HERE,
54a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&SetTimedOutAndQuitLoop,
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 timed_out_weak_factory.GetWeakPtr(),
56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                 run_loop->QuitClosure()),
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::TimeDelta::FromSeconds(1));
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  run_loop->Run();
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return !timed_out;
60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class TestHttpClient {
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public:
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TestHttpClient() : connect_result_(OK) {}
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int ConnectAndWait(const IPEndPoint& address) {
67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    AddressList addresses(address);
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    NetLog::Source source;
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    socket_.reset(new TCPClientSocket(addresses, NULL, source));
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::RunLoop run_loop;
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    connect_result_ = socket_->Connect(base::Bind(&TestHttpClient::OnConnect,
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                                  base::Unretained(this),
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                                  run_loop.QuitClosure()));
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (connect_result_ != OK && connect_result_ != ERR_IO_PENDING)
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return connect_result_;
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (!RunLoopWithTimeout(&run_loop))
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return ERR_TIMED_OUT;
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return connect_result_;
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void Send(const std::string& data) {
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    write_buffer_ =
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        new DrainableIOBuffer(new StringIOBuffer(data), data.length());
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    Write();
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private:
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void OnConnect(const base::Closure& quit_loop, int result) {
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    connect_result_ = result;
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    quit_loop.Run();
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void Write() {
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    int result = socket_->Write(
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        write_buffer_.get(),
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        write_buffer_->BytesRemaining(),
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        base::Bind(&TestHttpClient::OnWrite, base::Unretained(this)));
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (result != ERR_IO_PENDING)
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      OnWrite(result);
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  void OnWrite(int result) {
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_GT(result, 0);
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    write_buffer_->DidConsume(result);
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (write_buffer_->BytesRemaining())
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      Write();
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<DrainableIOBuffer> write_buffer_;
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<TCPClientSocket> socket_;
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int connect_result_;
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class HttpServerTest : public testing::Test,
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                       public HttpServer::Delegate {
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public:
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  HttpServerTest() : quit_after_request_count_(0) {}
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
124a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    TCPListenSocketFactory socket_factory("127.0.0.1", 0);
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    server_ = new HttpServer(socket_factory, this);
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_EQ(OK, server_->GetLocalAddress(&server_address_));
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
128a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual void OnHttpRequest(int connection_id,
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                             const HttpServerRequestInfo& info) OVERRIDE {
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    requests_.push_back(info);
132a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (requests_.size() == quit_after_request_count_)
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      run_loop_quit_func_.Run();
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
136a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual void OnWebSocketRequest(int connection_id,
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  const HttpServerRequestInfo& info) OVERRIDE {
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    NOTREACHED();
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
141a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual void OnWebSocketMessage(int connection_id,
142a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                  const std::string& data) OVERRIDE {
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    NOTREACHED();
144a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
145a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
146a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual void OnClose(int connection_id) OVERRIDE {}
147a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
148a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  bool RunUntilRequestsReceived(size_t count) {
149a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    quit_after_request_count_ = count;
150a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    if (requests_.size() == count)
151a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      return true;
152a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::RunLoop run_loop;
154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    run_loop_quit_func_ = run_loop.QuitClosure();
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    bool success = RunLoopWithTimeout(&run_loop);
156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    run_loop_quit_func_.Reset();
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return success;
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) protected:
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<HttpServer> server_;
162a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  IPEndPoint server_address_;
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::Closure run_loop_quit_func_;
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::vector<HttpServerRequestInfo> requests_;
165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
166a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private:
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  size_t quit_after_request_count_;
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
170a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(HttpServerTest, Request) {
171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TestHttpClient client;
172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  client.Send("GET /test HTTP/1.1\r\n\r\n");
174a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(RunUntilRequestsReceived(1));
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ("GET", requests_[0].method);
176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ("/test", requests_[0].path);
177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ("", requests_[0].data);
178a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(0u, requests_[0].headers.size());
179a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
180a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
181a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(HttpServerTest, RequestWithHeaders) {
182a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TestHttpClient client;
183a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
184a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const char* kHeaders[][3] = {
185a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      {"Header", ": ", "1"},
186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      {"HeaderWithNoWhitespace", ":", "1"},
187a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      {"HeaderWithWhitespace", "   :  \t   ", "1 1 1 \t  "},
188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      {"HeaderWithColon", ": ", "1:1"},
189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      {"EmptyHeader", ":", ""},
190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      {"EmptyHeaderWithWhitespace", ":  \t  ", ""},
1911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      {"HeaderWithNonASCII", ":  ", "\xf7"},
192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  };
193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string headers;
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kHeaders); ++i) {
195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    headers +=
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        std::string(kHeaders[i][0]) + kHeaders[i][1] + kHeaders[i][2] + "\r\n";
197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  client.Send("GET /test HTTP/1.1\r\n" + headers + "\r\n");
200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(RunUntilRequestsReceived(1));
201a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ("", requests_[0].data);
202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kHeaders); ++i) {
204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::string field = StringToLowerASCII(std::string(kHeaders[i][0]));
205a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    std::string value = kHeaders[i][2];
206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_EQ(1u, requests_[0].headers.count(field)) << field;
207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ASSERT_EQ(value, requests_[0].headers[field]) << kHeaders[i][0];
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
209a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(HttpServerTest, RequestWithBody) {
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TestHttpClient client;
213a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
214a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string body = "a" + std::string(1 << 10, 'b') + "c";
215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  client.Send(base::StringPrintf(
216a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "GET /test HTTP/1.1\r\n"
217a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "SomeHeader: 1\r\n"
218a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "Content-Length: %" PRIuS "\r\n\r\n%s",
219a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      body.length(),
220a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      body.c_str()));
221a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(RunUntilRequestsReceived(1));
222a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(2u, requests_[0].headers.size());
223a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(body.length(), requests_[0].data.length());
224a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ('a', body[0]);
225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ('c', *body.rbegin());
226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(HttpServerTest, RequestWithTooLargeBody) {
229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  class TestURLFetcherDelegate : public URLFetcherDelegate {
230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)   public:
231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    TestURLFetcherDelegate(const base::Closure& quit_loop_func)
232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        : quit_loop_func_(quit_loop_func) {}
233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    virtual ~TestURLFetcherDelegate() {}
234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    virtual void OnURLFetchComplete(const URLFetcher* source) OVERRIDE {
236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      EXPECT_EQ(HTTP_INTERNAL_SERVER_ERROR, source->GetResponseCode());
237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      quit_loop_func_.Run();
238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    }
239a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)   private:
241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    base::Closure quit_loop_func_;
242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  };
243a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  base::RunLoop run_loop;
245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TestURLFetcherDelegate delegate(run_loop.QuitClosure());
246a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<URLRequestContextGetter> request_context_getter(
248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      new TestURLRequestContextGetter(base::MessageLoopProxy::current()));
249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_ptr<URLFetcher> fetcher(
250a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      URLFetcher::Create(GURL(base::StringPrintf("http://127.0.0.1:%d/test",
251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                                 server_address_.port())),
252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                         URLFetcher::GET,
253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                         &delegate));
254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  fetcher->SetRequestContext(request_context_getter.get());
255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  fetcher->AddExtraRequestHeader(
256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::StringPrintf("content-length:%d", 1 << 30));
257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  fetcher->Start();
258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(RunLoopWithTimeout(&run_loop));
260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(0u, requests_.size());
261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace {
264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class MockStreamListenSocket : public StreamListenSocket {
266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public:
267a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MockStreamListenSocket(StreamListenSocket::Delegate* delegate)
268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      : StreamListenSocket(kInvalidSocket, delegate) {}
269a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
270a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual void Accept() OVERRIDE { NOTREACHED(); }
271a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
272a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private:
273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual ~MockStreamListenSocket() {}
274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace
277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(HttpServerTest, RequestWithBodySplitAcrossPackets) {
27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  StreamListenSocket* socket =
28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      new MockStreamListenSocket(server_.get());
28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  server_->DidAccept(NULL, make_scoped_ptr(socket));
282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string body("body");
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string request = base::StringPrintf(
284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "GET /test HTTP/1.1\r\n"
285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "SomeHeader: 1\r\n"
286a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "Content-Length: %" PRIuS "\r\n\r\n%s",
287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      body.length(),
288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      body.c_str());
28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  server_->DidRead(socket, request.c_str(), request.length() - 2);
290a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(0u, requests_.size());
29158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  server_->DidRead(socket, request.c_str() + request.length() - 2, 2);
292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(1u, requests_.size());
293a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(body, requests_[0].data);
294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(HttpServerTest, MultipleRequestsOnSameConnection) {
297a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // The idea behind this test is that requests with or without bodies should
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // not break parsing of the next request.
299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TestHttpClient client;
300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string body = "body";
302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  client.Send(base::StringPrintf(
303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "GET /test HTTP/1.1\r\n"
304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "Content-Length: %" PRIuS "\r\n\r\n%s",
305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      body.length(),
306a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      body.c_str()));
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(RunUntilRequestsReceived(1));
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ(body, requests_[0].data);
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
310a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  client.Send("GET /test2 HTTP/1.1\r\n\r\n");
311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(RunUntilRequestsReceived(2));
312a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ("/test2", requests_[1].path);
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
314a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  client.Send("GET /test3 HTTP/1.1\r\n\r\n");
315a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_TRUE(RunUntilRequestsReceived(3));
316a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ASSERT_EQ("/test3", requests_[2].path);
317a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
318a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace net
320