OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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/quic/quic_reliable_client_stream.h" | |
6 | |
7 #include "base/macros.h" | |
8 #include "net/base/net_errors.h" | |
9 #include "net/base/test_completion_callback.h" | |
10 #include "net/quic/quic_chromium_client_session.h" | |
11 #include "net/quic/quic_utils.h" | |
12 #include "net/quic/spdy_utils.h" | |
13 #include "net/quic/test_tools/crypto_test_utils.h" | |
14 #include "net/quic/test_tools/quic_test_utils.h" | |
15 #include "testing/gmock/include/gmock/gmock.h" | |
16 #include "testing/gmock_mutant.h" | |
17 | |
18 using testing::AnyNumber; | |
19 using testing::CreateFunctor; | |
20 using testing::Invoke; | |
21 using testing::Return; | |
22 using testing::StrEq; | |
23 using testing::_; | |
24 | |
25 namespace net { | |
26 namespace test { | |
27 namespace { | |
28 | |
29 const QuicStreamId kTestStreamId = 5u; | |
30 | |
31 class MockDelegate : public QuicReliableClientStream::Delegate { | |
32 public: | |
33 MockDelegate() {} | |
34 | |
35 MOCK_METHOD0(OnSendData, int()); | |
36 MOCK_METHOD2(OnSendDataComplete, int(int, bool*)); | |
37 MOCK_METHOD2(OnHeadersAvailable, void(const SpdyHeaderBlock&, size_t)); | |
38 MOCK_METHOD2(OnDataReceived, int(const char*, int)); | |
39 MOCK_METHOD0(OnDataAvailable, void()); | |
40 MOCK_METHOD1(OnClose, void(QuicErrorCode)); | |
41 MOCK_METHOD1(OnError, void(int)); | |
42 MOCK_METHOD0(HasSendHeadersComplete, bool()); | |
43 | |
44 private: | |
45 DISALLOW_COPY_AND_ASSIGN(MockDelegate); | |
46 }; | |
47 | |
48 class QuicReliableClientStreamTest | |
49 : public ::testing::TestWithParam<QuicVersion> { | |
50 public: | |
51 QuicReliableClientStreamTest() | |
52 : crypto_config_(CryptoTestUtils::ProofVerifierForTesting()), | |
53 session_(new MockConnection(&helper_, | |
54 Perspective::IS_CLIENT, | |
55 SupportedVersions(GetParam()))) { | |
56 stream_ = | |
57 new QuicReliableClientStream(kTestStreamId, &session_, BoundNetLog()); | |
58 session_.ActivateStream(stream_); | |
59 stream_->SetDelegate(&delegate_); | |
60 } | |
61 | |
62 void InitializeHeaders() { | |
63 headers_[":host"] = "www.google.com"; | |
64 headers_[":path"] = "/index.hml"; | |
65 headers_[":scheme"] = "https"; | |
66 headers_["cookie"] = | |
67 "__utma=208381060.1228362404.1372200928.1372200928.1372200928.1; " | |
68 "__utmc=160408618; " | |
69 "GX=DQAAAOEAAACWJYdewdE9rIrW6qw3PtVi2-d729qaa-74KqOsM1NVQblK4VhX" | |
70 "hoALMsy6HOdDad2Sz0flUByv7etmo3mLMidGrBoljqO9hSVA40SLqpG_iuKKSHX" | |
71 "RW3Np4bq0F0SDGDNsW0DSmTS9ufMRrlpARJDS7qAI6M3bghqJp4eABKZiRqebHT" | |
72 "pMU-RXvTI5D5oCF1vYxYofH_l1Kviuiy3oQ1kS1enqWgbhJ2t61_SNdv-1XJIS0" | |
73 "O3YeHLmVCs62O6zp89QwakfAWK9d3IDQvVSJzCQsvxvNIvaZFa567MawWlXg0Rh" | |
74 "1zFMi5vzcns38-8_Sns; " | |
75 "GA=v*2%2Fmem*57968640*47239936%2Fmem*57968640*47114716%2Fno-nm-" | |
76 "yj*15%2Fno-cc-yj*5%2Fpc-ch*133685%2Fpc-s-cr*133947%2Fpc-s-t*1339" | |
77 "47%2Fno-nm-yj*4%2Fno-cc-yj*1%2Fceft-as*1%2Fceft-nqas*0%2Fad-ra-c" | |
78 "v_p%2Fad-nr-cv_p-f*1%2Fad-v-cv_p*859%2Fad-ns-cv_p-f*1%2Ffn-v-ad%" | |
79 "2Fpc-t*250%2Fpc-cm*461%2Fpc-s-cr*722%2Fpc-s-t*722%2Fau_p*4" | |
80 "SICAID=AJKiYcHdKgxum7KMXG0ei2t1-W4OD1uW-ecNsCqC0wDuAXiDGIcT_HA2o1" | |
81 "3Rs1UKCuBAF9g8rWNOFbxt8PSNSHFuIhOo2t6bJAVpCsMU5Laa6lewuTMYI8MzdQP" | |
82 "ARHKyW-koxuhMZHUnGBJAM1gJODe0cATO_KGoX4pbbFxxJ5IicRxOrWK_5rU3cdy6" | |
83 "edlR9FsEdH6iujMcHkbE5l18ehJDwTWmBKBzVD87naobhMMrF6VvnDGxQVGp9Ir_b" | |
84 "Rgj3RWUoPumQVCxtSOBdX0GlJOEcDTNCzQIm9BSfetog_eP_TfYubKudt5eMsXmN6" | |
85 "QnyXHeGeK2UINUzJ-D30AFcpqYgH9_1BvYSpi7fc7_ydBU8TaD8ZRxvtnzXqj0RfG" | |
86 "tuHghmv3aD-uzSYJ75XDdzKdizZ86IG6Fbn1XFhYZM-fbHhm3mVEXnyRW4ZuNOLFk" | |
87 "Fas6LMcVC6Q8QLlHYbXBpdNFuGbuZGUnav5C-2I_-46lL0NGg3GewxGKGHvHEfoyn" | |
88 "EFFlEYHsBQ98rXImL8ySDycdLEFvBPdtctPmWCfTxwmoSMLHU2SCVDhbqMWU5b0yr" | |
89 "JBCScs_ejbKaqBDoB7ZGxTvqlrB__2ZmnHHjCr8RgMRtKNtIeuZAo "; | |
90 } | |
91 | |
92 void ReadData(StringPiece expected_data) { | |
93 scoped_refptr<IOBuffer> buffer(new IOBuffer(expected_data.length() + 1)); | |
94 EXPECT_EQ(static_cast<int>(expected_data.length()), | |
95 stream_->Read(buffer.get(), expected_data.length() + 1)); | |
96 EXPECT_EQ(expected_data, | |
97 StringPiece(buffer->data(), expected_data.length())); | |
98 } | |
99 | |
100 QuicCryptoClientConfig crypto_config_; | |
101 testing::StrictMock<MockDelegate> delegate_; | |
102 MockConnectionHelper helper_; | |
103 MockQuicSpdySession session_; | |
104 QuicReliableClientStream* stream_; | |
105 SpdyHeaderBlock headers_; | |
106 }; | |
107 | |
108 INSTANTIATE_TEST_CASE_P(Version, | |
109 QuicReliableClientStreamTest, | |
110 ::testing::ValuesIn(QuicSupportedVersions())); | |
111 | |
112 TEST_P(QuicReliableClientStreamTest, OnFinRead) { | |
113 InitializeHeaders(); | |
114 std::string uncompressed_headers = | |
115 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
116 QuicStreamOffset offset = 0; | |
117 stream_->OnStreamHeaders(uncompressed_headers); | |
118 stream_->OnStreamHeadersComplete(false, uncompressed_headers.length()); | |
119 | |
120 EXPECT_CALL(delegate_, | |
121 OnHeadersAvailable(headers_, uncompressed_headers.length())); | |
122 base::MessageLoop::current()->RunUntilIdle(); | |
123 EXPECT_TRUE(stream_->decompressed_headers().empty()); | |
124 | |
125 QuicStreamFrame frame2(kTestStreamId, true, offset, StringPiece()); | |
126 EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR)); | |
127 stream_->OnStreamFrame(frame2); | |
128 } | |
129 | |
130 TEST_P(QuicReliableClientStreamTest, OnDataAvailableBeforeHeaders) { | |
131 EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR)); | |
132 | |
133 EXPECT_CALL(delegate_, OnDataAvailable()).Times(0); | |
134 stream_->OnDataAvailable(); | |
135 } | |
136 | |
137 TEST_P(QuicReliableClientStreamTest, OnDataAvailable) { | |
138 InitializeHeaders(); | |
139 std::string uncompressed_headers = | |
140 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
141 stream_->OnStreamHeaders(uncompressed_headers); | |
142 stream_->OnStreamHeadersComplete(false, uncompressed_headers.length()); | |
143 | |
144 EXPECT_CALL(delegate_, | |
145 OnHeadersAvailable(headers_, uncompressed_headers.length())); | |
146 base::MessageLoop::current()->RunUntilIdle(); | |
147 EXPECT_TRUE(stream_->decompressed_headers().empty()); | |
148 | |
149 const char data[] = "hello world!"; | |
150 stream_->OnStreamFrame(QuicStreamFrame(kTestStreamId, /*fin=*/false, | |
151 /*offset=*/0, data)); | |
152 | |
153 EXPECT_CALL(delegate_, OnDataAvailable()) | |
154 .WillOnce(testing::Invoke( | |
155 CreateFunctor(this, &QuicReliableClientStreamTest::ReadData, | |
156 StringPiece(data, arraysize(data) - 1)))); | |
157 base::MessageLoop::current()->RunUntilIdle(); | |
158 | |
159 EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR)); | |
160 } | |
161 | |
162 TEST_P(QuicReliableClientStreamTest, ProcessHeadersWithError) { | |
163 std::string bad_headers = "..."; | |
164 stream_->OnStreamHeaders(StringPiece(bad_headers)); | |
165 stream_->OnStreamHeadersComplete(false, bad_headers.length()); | |
166 | |
167 EXPECT_CALL(session_, | |
168 SendRstStream(kTestStreamId, QUIC_BAD_APPLICATION_PAYLOAD, 0)); | |
169 base::MessageLoop::current()->RunUntilIdle(); | |
170 | |
171 EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR)); | |
172 } | |
173 | |
174 TEST_P(QuicReliableClientStreamTest, OnDataAvailableWithError) { | |
175 InitializeHeaders(); | |
176 std::string uncompressed_headers = | |
177 SpdyUtils::SerializeUncompressedHeaders(headers_); | |
178 stream_->OnStreamHeaders(uncompressed_headers); | |
179 stream_->OnStreamHeadersComplete(false, uncompressed_headers.length()); | |
180 | |
181 EXPECT_CALL(delegate_, | |
182 OnHeadersAvailable(headers_, uncompressed_headers.length())); | |
183 base::MessageLoop::current()->RunUntilIdle(); | |
184 EXPECT_TRUE(stream_->decompressed_headers().empty()); | |
185 | |
186 const char data[] = "hello world!"; | |
187 stream_->OnStreamFrame(QuicStreamFrame(kTestStreamId, /*fin=*/false, | |
188 /*offset=*/0, data)); | |
189 EXPECT_CALL(delegate_, OnDataAvailable()) | |
190 .WillOnce(testing::Invoke(CreateFunctor( | |
191 stream_, &QuicReliableClientStream::Reset, QUIC_STREAM_CANCELLED))); | |
192 base::MessageLoop::current()->RunUntilIdle(); | |
193 | |
194 EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR)); | |
195 } | |
196 | |
197 TEST_P(QuicReliableClientStreamTest, OnError) { | |
198 EXPECT_CALL(delegate_, OnError(ERR_INTERNET_DISCONNECTED)); | |
199 | |
200 stream_->OnError(ERR_INTERNET_DISCONNECTED); | |
201 EXPECT_FALSE(stream_->GetDelegate()); | |
202 } | |
203 | |
204 TEST_P(QuicReliableClientStreamTest, WriteStreamData) { | |
205 EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR)); | |
206 | |
207 const char kData1[] = "hello world"; | |
208 const size_t kDataLen = arraysize(kData1); | |
209 | |
210 // All data written. | |
211 EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)) | |
212 .WillOnce(Return(QuicConsumedData(kDataLen, true))); | |
213 TestCompletionCallback callback; | |
214 EXPECT_EQ(OK, stream_->WriteStreamData(base::StringPiece(kData1, kDataLen), | |
215 true, callback.callback())); | |
216 } | |
217 | |
218 TEST_P(QuicReliableClientStreamTest, WriteStreamDataAsync) { | |
219 EXPECT_CALL(delegate_, HasSendHeadersComplete()).Times(AnyNumber()); | |
220 EXPECT_CALL(delegate_, OnClose(QUIC_NO_ERROR)); | |
221 | |
222 const char kData1[] = "hello world"; | |
223 const size_t kDataLen = arraysize(kData1); | |
224 | |
225 // No data written. | |
226 EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)) | |
227 .WillOnce(Return(QuicConsumedData(0, false))); | |
228 TestCompletionCallback callback; | |
229 EXPECT_EQ(ERR_IO_PENDING, | |
230 stream_->WriteStreamData(base::StringPiece(kData1, kDataLen), true, | |
231 callback.callback())); | |
232 ASSERT_FALSE(callback.have_result()); | |
233 | |
234 // All data written. | |
235 EXPECT_CALL(session_, WritevData(stream_->id(), _, _, _, _, _)) | |
236 .WillOnce(Return(QuicConsumedData(kDataLen, true))); | |
237 stream_->OnCanWrite(); | |
238 ASSERT_TRUE(callback.have_result()); | |
239 EXPECT_EQ(OK, callback.WaitForResult()); | |
240 } | |
241 | |
242 } // namespace | |
243 } // namespace test | |
244 } // namespace net | |
OLD | NEW |