• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/spdy/spdy_http_stream.h"
6 #include "net/spdy/spdy_session.h"
7 #include "net/spdy/spdy_test_util.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 
10 namespace net {
11 
12 class SpdyHttpStreamTest : public testing::Test {
13  public:
data()14   OrderedSocketData* data() { return data_; }
15  protected:
SpdyHttpStreamTest()16   SpdyHttpStreamTest() {}
17 
EnableCompression(bool enabled)18   void EnableCompression(bool enabled) {
19     spdy::SpdyFramer::set_enable_compression_default(enabled);
20   }
21 
TearDown()22   virtual void TearDown() {
23     MessageLoop::current()->RunAllPending();
24   }
InitSession(MockRead * reads,size_t reads_count,MockWrite * writes,size_t writes_count,HostPortPair & host_port_pair)25   int InitSession(MockRead* reads, size_t reads_count,
26                   MockWrite* writes, size_t writes_count,
27                   HostPortPair& host_port_pair) {
28     HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
29     data_ = new OrderedSocketData(reads, reads_count, writes, writes_count);
30     session_deps_.socket_factory->AddSocketDataProvider(data_.get());
31     http_session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
32     session_ = http_session_->spdy_session_pool()->Get(pair, BoundNetLog());
33     transport_params_ = new TransportSocketParams(host_port_pair,
34                                       MEDIUM, GURL(), false, false);
35     TestCompletionCallback callback;
36     scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
37     EXPECT_EQ(ERR_IO_PENDING,
38               connection->Init(host_port_pair.ToString(),
39                                 transport_params_,
40                                 MEDIUM,
41                                 &callback,
42                                 http_session_->transport_socket_pool(),
43                                 BoundNetLog()));
44     EXPECT_EQ(OK, callback.WaitForResult());
45     return session_->InitializeWithSocket(connection.release(), false, OK);
46   }
47   SpdySessionDependencies session_deps_;
48   scoped_refptr<OrderedSocketData> data_;
49   scoped_refptr<HttpNetworkSession> http_session_;
50   scoped_refptr<SpdySession> session_;
51   scoped_refptr<TransportSocketParams> transport_params_;
52 };
53 
TEST_F(SpdyHttpStreamTest,SendRequest)54 TEST_F(SpdyHttpStreamTest, SendRequest) {
55   EnableCompression(false);
56   SpdySession::SetSSLMode(false);
57 
58   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
59   MockWrite writes[] = {
60     CreateMockWrite(*req.get(), 1),
61   };
62   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
63   MockRead reads[] = {
64     CreateMockRead(*resp, 2),
65     MockRead(false, 0, 3)  // EOF
66   };
67 
68   HostPortPair host_port_pair("www.google.com", 80);
69   HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
70   EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
71       host_port_pair));
72 
73   HttpRequestInfo request;
74   request.method = "GET";
75   request.url = GURL("http://www.google.com/");
76   TestCompletionCallback callback;
77   HttpResponseInfo response;
78   HttpRequestHeaders headers;
79   BoundNetLog net_log;
80   scoped_ptr<SpdyHttpStream> http_stream(
81       new SpdyHttpStream(session_.get(), true));
82   ASSERT_EQ(
83       OK,
84       http_stream->InitializeStream(&request, net_log, NULL));
85 
86   EXPECT_EQ(ERR_IO_PENDING,
87             http_stream->SendRequest(headers, NULL, &response, &callback));
88   EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
89 
90   // This triggers the MockWrite and read 2
91   callback.WaitForResult();
92 
93   // This triggers read 3. The empty read causes the session to shut down.
94   data()->CompleteRead();
95 
96   // Because we abandoned the stream, we don't expect to find a session in the
97   // pool anymore.
98   EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
99   EXPECT_TRUE(data()->at_read_eof());
100   EXPECT_TRUE(data()->at_write_eof());
101 }
102 
TEST_F(SpdyHttpStreamTest,SendChunkedPost)103 TEST_F(SpdyHttpStreamTest, SendChunkedPost) {
104   EnableCompression(false);
105   SpdySession::SetSSLMode(false);
106   UploadDataStream::set_merge_chunks(false);
107 
108   scoped_ptr<spdy::SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0));
109   scoped_ptr<spdy::SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false));
110   scoped_ptr<spdy::SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true));
111   MockWrite writes[] = {
112     CreateMockWrite(*req.get(), 1),
113     CreateMockWrite(*chunk1, 2),  // POST upload frames
114     CreateMockWrite(*chunk2, 3),
115   };
116   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0));
117   MockRead reads[] = {
118     CreateMockRead(*resp, 4),
119     CreateMockRead(*chunk1, 5),
120     CreateMockRead(*chunk2, 5),
121     MockRead(false, 0, 6)  // EOF
122   };
123 
124   HostPortPair host_port_pair("www.google.com", 80);
125   HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
126   EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
127                             host_port_pair));
128 
129   HttpRequestInfo request;
130   request.method = "POST";
131   request.url = GURL("http://www.google.com/");
132   request.upload_data = new UploadData();
133   request.upload_data->set_is_chunked(true);
134   request.upload_data->AppendChunk(kUploadData, kUploadDataSize, false);
135   request.upload_data->AppendChunk(kUploadData, kUploadDataSize, true);
136   TestCompletionCallback callback;
137   HttpResponseInfo response;
138   HttpRequestHeaders headers;
139   BoundNetLog net_log;
140   SpdyHttpStream http_stream(session_.get(), true);
141   ASSERT_EQ(
142       OK,
143       http_stream.InitializeStream(&request, net_log, NULL));
144 
145   UploadDataStream* upload_stream =
146       UploadDataStream::Create(request.upload_data, NULL);
147   EXPECT_EQ(ERR_IO_PENDING, http_stream.SendRequest(
148       headers, upload_stream, &response, &callback));
149   EXPECT_TRUE(http_session_->spdy_session_pool()->HasSession(pair));
150 
151   // This triggers the MockWrite and read 2
152   callback.WaitForResult();
153 
154   // This triggers read 3. The empty read causes the session to shut down.
155   data()->CompleteRead();
156   MessageLoop::current()->RunAllPending();
157 
158   // Because we abandoned the stream, we don't expect to find a session in the
159   // pool anymore.
160   EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
161   EXPECT_TRUE(data()->at_read_eof());
162   EXPECT_TRUE(data()->at_write_eof());
163 }
164 
165 // Test case for bug: http://code.google.com/p/chromium/issues/detail?id=50058
TEST_F(SpdyHttpStreamTest,SpdyURLTest)166 TEST_F(SpdyHttpStreamTest, SpdyURLTest) {
167   EnableCompression(false);
168   SpdySession::SetSSLMode(false);
169 
170   const char * const full_url = "http://www.google.com/foo?query=what#anchor";
171   const char * const base_url = "http://www.google.com/foo?query=what";
172   scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(base_url, false, 1, LOWEST));
173   MockWrite writes[] = {
174     CreateMockWrite(*req.get(), 1),
175   };
176   scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
177   MockRead reads[] = {
178     CreateMockRead(*resp, 2),
179     MockRead(false, 0, 3)  // EOF
180   };
181 
182   HostPortPair host_port_pair("www.google.com", 80);
183   HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
184   EXPECT_EQ(OK, InitSession(reads, arraysize(reads), writes, arraysize(writes),
185       host_port_pair));
186 
187   HttpRequestInfo request;
188   request.method = "GET";
189   request.url = GURL(full_url);
190   TestCompletionCallback callback;
191   HttpResponseInfo response;
192   HttpRequestHeaders headers;
193   BoundNetLog net_log;
194   scoped_ptr<SpdyHttpStream> http_stream(new SpdyHttpStream(session_, true));
195   ASSERT_EQ(
196       OK,
197       http_stream->InitializeStream(&request, net_log, NULL));
198 
199   EXPECT_EQ(ERR_IO_PENDING,
200             http_stream->SendRequest(headers, NULL, &response, &callback));
201 
202   spdy::SpdyHeaderBlock* spdy_header =
203     http_stream->stream()->spdy_headers().get();
204   EXPECT_TRUE(spdy_header != NULL);
205   if (spdy_header->find("url") != spdy_header->end())
206     EXPECT_EQ("/foo?query=what", spdy_header->find("url")->second);
207   else
208     FAIL() << "No url is set in spdy_header!";
209 
210   // This triggers the MockWrite and read 2
211   callback.WaitForResult();
212 
213   // This triggers read 3. The empty read causes the session to shut down.
214   data()->CompleteRead();
215 
216   // Because we abandoned the stream, we don't expect to find a session in the
217   // pool anymore.
218   EXPECT_FALSE(http_session_->spdy_session_pool()->HasSession(pair));
219   EXPECT_TRUE(data()->at_read_eof());
220   EXPECT_TRUE(data()->at_write_eof());
221 }
222 
223 // TODO(willchan): Write a longer test for SpdyStream that exercises all
224 // methods.
225 
226 }  // namespace net
227