OLD | NEW |
| (Empty) |
1 // Copyright 2013 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/tools/flip_server/http_interface.h" | |
6 | |
7 #include <list> | |
8 #include <memory> | |
9 | |
10 #include "base/stl_util.h" | |
11 #include "base/strings/string_piece.h" | |
12 #include "net/tools/balsa/balsa_enums.h" | |
13 #include "net/tools/balsa/balsa_frame.h" | |
14 #include "net/tools/balsa/balsa_headers.h" | |
15 #include "net/tools/flip_server/flip_config.h" | |
16 #include "net/tools/flip_server/flip_test_utils.h" | |
17 #include "net/tools/flip_server/mem_cache.h" | |
18 #include "testing/gmock/include/gmock/gmock.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 namespace net { | |
22 | |
23 using ::base::StringPiece; | |
24 using ::testing::_; | |
25 using ::testing::InSequence; | |
26 | |
27 namespace { | |
28 | |
29 class MockSMConnection : public SMConnection { | |
30 public: | |
31 MockSMConnection(EpollServer* epoll_server, | |
32 SSLState* ssl_state, | |
33 MemoryCache* memory_cache, | |
34 FlipAcceptor* acceptor, | |
35 std::string log_prefix) | |
36 : SMConnection(epoll_server, | |
37 ssl_state, | |
38 memory_cache, | |
39 acceptor, | |
40 log_prefix) {} | |
41 | |
42 MOCK_METHOD0(Cleanup, void()); | |
43 MOCK_METHOD8(InitSMConnection, | |
44 void(SMConnectionPoolInterface*, | |
45 SMInterface*, | |
46 EpollServer*, | |
47 int, | |
48 std::string, | |
49 std::string, | |
50 std::string, | |
51 bool)); | |
52 }; | |
53 | |
54 class FlipHttpSMTest : public ::testing::Test { | |
55 public: | |
56 explicit FlipHttpSMTest(FlipHandlerType type = FLIP_HANDLER_PROXY) { | |
57 SSLState* ssl_state = NULL; | |
58 mock_another_interface_.reset(new MockSMInterface); | |
59 memory_cache_.reset(new MemoryCache); | |
60 acceptor_.reset(new FlipAcceptor(type, | |
61 "127.0.0.1", | |
62 "8941", | |
63 "ssl_cert_filename", | |
64 "ssl_key_filename", | |
65 "127.0.0.1", | |
66 "8942", | |
67 "127.0.0.1", | |
68 "8943", | |
69 1, | |
70 0, | |
71 true, | |
72 1, | |
73 false, | |
74 true, | |
75 NULL)); | |
76 epoll_server_.reset(new EpollServer); | |
77 connection_.reset(new MockSMConnection(epoll_server_.get(), | |
78 ssl_state, | |
79 memory_cache_.get(), | |
80 acceptor_.get(), | |
81 "log_prefix")); | |
82 | |
83 interface_.reset(new HttpSM(connection_.get(), | |
84 mock_another_interface_.get(), | |
85 memory_cache_.get(), | |
86 acceptor_.get())); | |
87 } | |
88 | |
89 void TearDown() override { | |
90 if (acceptor_->listen_fd_ >= 0) { | |
91 epoll_server_->UnregisterFD(acceptor_->listen_fd_); | |
92 close(acceptor_->listen_fd_); | |
93 acceptor_->listen_fd_ = -1; | |
94 } | |
95 STLDeleteElements(connection_->output_list()); | |
96 } | |
97 | |
98 bool HasStream(uint32_t stream_id) { | |
99 return interface_->output_ordering().ExistsInPriorityMaps(stream_id); | |
100 } | |
101 | |
102 protected: | |
103 std::unique_ptr<MockSMInterface> mock_another_interface_; | |
104 std::unique_ptr<MemoryCache> memory_cache_; | |
105 std::unique_ptr<FlipAcceptor> acceptor_; | |
106 std::unique_ptr<EpollServer> epoll_server_; | |
107 std::unique_ptr<MockSMConnection> connection_; | |
108 std::unique_ptr<HttpSM> interface_; | |
109 }; | |
110 | |
111 class FlipHttpSMProxyTest : public FlipHttpSMTest { | |
112 public: | |
113 FlipHttpSMProxyTest() : FlipHttpSMTest(FLIP_HANDLER_PROXY) {} | |
114 ~FlipHttpSMProxyTest() override {} | |
115 }; | |
116 | |
117 class FlipHttpSMHttpTest : public FlipHttpSMTest { | |
118 public: | |
119 FlipHttpSMHttpTest() : FlipHttpSMTest(FLIP_HANDLER_HTTP_SERVER) {} | |
120 ~FlipHttpSMHttpTest() override {} | |
121 }; | |
122 | |
123 class FlipHttpSMSpdyTest : public FlipHttpSMTest { | |
124 public: | |
125 FlipHttpSMSpdyTest() : FlipHttpSMTest(FLIP_HANDLER_SPDY_SERVER) {} | |
126 ~FlipHttpSMSpdyTest() override {} | |
127 }; | |
128 | |
129 TEST_F(FlipHttpSMTest, Construct) { | |
130 ASSERT_FALSE(interface_->spdy_framer()->is_request()); | |
131 } | |
132 | |
133 TEST_F(FlipHttpSMTest, AddToOutputOrder) { | |
134 uint32_t stream_id = 13; | |
135 MemCacheIter mci; | |
136 mci.stream_id = stream_id; | |
137 | |
138 { | |
139 BalsaHeaders headers; | |
140 std::string filename = "foobar"; | |
141 memory_cache_->InsertFile(&headers, filename, ""); | |
142 mci.file_data = memory_cache_->GetFileData(filename); | |
143 } | |
144 | |
145 interface_->AddToOutputOrder(mci); | |
146 ASSERT_TRUE(HasStream(stream_id)); | |
147 } | |
148 | |
149 TEST_F(FlipHttpSMTest, InitSMInterface) { | |
150 std::unique_ptr<MockSMInterface> mock(new MockSMInterface); | |
151 { | |
152 InSequence s; | |
153 EXPECT_CALL(*mock_another_interface_, SendEOF(_)); | |
154 EXPECT_CALL(*mock_another_interface_, ResetForNewInterface(_)); | |
155 EXPECT_CALL(*mock, SendEOF(_)); | |
156 EXPECT_CALL(*mock, ResetForNewInterface(_)); | |
157 } | |
158 | |
159 interface_->ResetForNewConnection(); | |
160 interface_->InitSMInterface(mock.get(), 0); | |
161 interface_->ResetForNewConnection(); | |
162 } | |
163 | |
164 TEST_F(FlipHttpSMTest, InitSMConnection) { | |
165 EXPECT_CALL(*connection_, InitSMConnection(_, _, _, _, _, _, _, _)); | |
166 | |
167 interface_->InitSMConnection(NULL, NULL, NULL, 0, "", "", "", false); | |
168 } | |
169 | |
170 TEST_F(FlipHttpSMTest, ProcessReadInput) { | |
171 std::string data = | |
172 "HTTP/1.1 200 OK\r\n" | |
173 "Content-Length: 14\r\n\r\n" | |
174 "hello, world\r\n"; | |
175 testing::MockFunction<void(int)> checkpoint; // NOLINT | |
176 { | |
177 InSequence s; | |
178 EXPECT_CALL(*mock_another_interface_, SendSynReply(_, _)); | |
179 EXPECT_CALL(checkpoint, Call(0)); | |
180 EXPECT_CALL(*mock_another_interface_, SendDataFrame(_, _, _, _, _)); | |
181 EXPECT_CALL(*mock_another_interface_, SendEOF(_)); | |
182 } | |
183 | |
184 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
185 interface_->spdy_framer()->ParseState()); | |
186 | |
187 size_t read = interface_->ProcessReadInput(data.data(), data.size()); | |
188 ASSERT_EQ(39u, read); | |
189 checkpoint.Call(0); | |
190 read += interface_->ProcessReadInput(&data.data()[read], data.size() - read); | |
191 ASSERT_EQ(data.size(), read); | |
192 ASSERT_EQ(BalsaFrameEnums::MESSAGE_FULLY_READ, | |
193 interface_->spdy_framer()->ParseState()); | |
194 ASSERT_TRUE(interface_->MessageFullyRead()); | |
195 } | |
196 | |
197 TEST_F(FlipHttpSMTest, ProcessWriteInput) { | |
198 std::string data = "hello, world"; | |
199 interface_->ProcessWriteInput(data.data(), data.size()); | |
200 | |
201 ASSERT_EQ(1u, connection_->output_list()->size()); | |
202 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
203 DataFrame* df = *i++; | |
204 ASSERT_EQ(data, StringPiece(df->data, df->size)); | |
205 ASSERT_EQ(connection_->output_list()->end(), i); | |
206 } | |
207 | |
208 TEST_F(FlipHttpSMTest, Reset) { | |
209 std::string data = "HTTP/1.1 200 OK\r\n\r\n"; | |
210 testing::MockFunction<void(int)> checkpoint; // NOLINT | |
211 { | |
212 InSequence s; | |
213 EXPECT_CALL(*mock_another_interface_, SendSynReply(_, _)); | |
214 EXPECT_CALL(checkpoint, Call(0)); | |
215 } | |
216 | |
217 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
218 interface_->spdy_framer()->ParseState()); | |
219 | |
220 interface_->ProcessReadInput(data.data(), data.size()); | |
221 checkpoint.Call(0); | |
222 ASSERT_FALSE(interface_->MessageFullyRead()); | |
223 ASSERT_EQ(BalsaFrameEnums::READING_UNTIL_CLOSE, | |
224 interface_->spdy_framer()->ParseState()); | |
225 | |
226 interface_->Reset(); | |
227 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
228 interface_->spdy_framer()->ParseState()); | |
229 } | |
230 | |
231 TEST_F(FlipHttpSMTest, ResetForNewConnection) { | |
232 std::string data = "HTTP/1.1 200 OK\r\n\r\n"; | |
233 testing::MockFunction<void(int)> checkpoint; // NOLINT | |
234 { | |
235 InSequence s; | |
236 EXPECT_CALL(*mock_another_interface_, SendSynReply(_, _)); | |
237 EXPECT_CALL(checkpoint, Call(0)); | |
238 EXPECT_CALL(*mock_another_interface_, SendEOF(_)); | |
239 EXPECT_CALL(*mock_another_interface_, ResetForNewInterface(_)); | |
240 } | |
241 | |
242 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
243 interface_->spdy_framer()->ParseState()); | |
244 | |
245 interface_->ProcessReadInput(data.data(), data.size()); | |
246 checkpoint.Call(0); | |
247 ASSERT_FALSE(interface_->MessageFullyRead()); | |
248 ASSERT_EQ(BalsaFrameEnums::READING_UNTIL_CLOSE, | |
249 interface_->spdy_framer()->ParseState()); | |
250 | |
251 interface_->ResetForNewConnection(); | |
252 ASSERT_EQ(BalsaFrameEnums::READING_HEADER_AND_FIRSTLINE, | |
253 interface_->spdy_framer()->ParseState()); | |
254 } | |
255 | |
256 TEST_F(FlipHttpSMTest, NewStream) { | |
257 uint32_t stream_id = 4; | |
258 { | |
259 BalsaHeaders headers; | |
260 std::string filename = "foobar"; | |
261 memory_cache_->InsertFile(&headers, filename, ""); | |
262 } | |
263 | |
264 interface_->NewStream(stream_id, 1, "foobar"); | |
265 ASSERT_TRUE(HasStream(stream_id)); | |
266 } | |
267 | |
268 TEST_F(FlipHttpSMTest, NewStreamError) { | |
269 std::string syn_reply = | |
270 "HTTP/1.1 404 Not Found\r\n" | |
271 "transfer-encoding: chunked\r\n\r\n"; | |
272 std::string body = "e\r\npage not found\r\n"; | |
273 uint32_t stream_id = 4; | |
274 | |
275 ASSERT_FALSE(HasStream(stream_id)); | |
276 interface_->NewStream(stream_id, 1, "foobar"); | |
277 | |
278 ASSERT_EQ(3u, connection_->output_list()->size()); | |
279 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
280 DataFrame* df = *i++; | |
281 ASSERT_EQ(syn_reply, StringPiece(df->data, df->size)); | |
282 df = *i++; | |
283 ASSERT_EQ(body, StringPiece(df->data, df->size)); | |
284 df = *i++; | |
285 ASSERT_EQ("0\r\n\r\n", StringPiece(df->data, df->size)); | |
286 ASSERT_FALSE(HasStream(stream_id)); | |
287 } | |
288 | |
289 TEST_F(FlipHttpSMTest, SendErrorNotFound) { | |
290 std::string syn_reply = | |
291 "HTTP/1.1 404 Not Found\r\n" | |
292 "transfer-encoding: chunked\r\n\r\n"; | |
293 std::string body = "e\r\npage not found\r\n"; | |
294 uint32_t stream_id = 13; | |
295 MemCacheIter mci; | |
296 mci.stream_id = stream_id; | |
297 | |
298 { | |
299 BalsaHeaders headers; | |
300 std::string filename = "foobar"; | |
301 memory_cache_->InsertFile(&headers, filename, ""); | |
302 mci.file_data = memory_cache_->GetFileData(filename); | |
303 } | |
304 | |
305 interface_->AddToOutputOrder(mci); | |
306 ASSERT_TRUE(HasStream(stream_id)); | |
307 interface_->SendErrorNotFound(stream_id); | |
308 | |
309 ASSERT_EQ(3u, connection_->output_list()->size()); | |
310 std::list<DataFrame*>::const_iterator i = connection_->output_list()->begin(); | |
311 DataFrame* df = *i++; | |
312 ASSERT_EQ(syn_reply, StringPiece(df->data, df->size)); | |
313 df = *i++; | |
314 ASSERT_EQ(body, StringPiece(df->data, df->size)); | |
315 df = *i++; | |
316 ASSERT_EQ("0\r\n\r\n", StringPiece(df->data, df->size)); | |
317 ASSERT_FALSE(HasStream(stream_id)); | |
318 } | |
319 | |
320 TEST_F(FlipHttpSMTest, SendSynStream) { | |
321 std::string expected = | |
322 "GET / HTTP/1.0\r\n" | |
323 "key1: value1\r\n\r\n"; | |
324 BalsaHeaders headers; | |
325 headers.SetResponseFirstlineFromStringPieces("GET", "/path", "HTTP/1.0"); | |
326 headers.AppendHeader("key1", "value1"); | |
327 interface_->SendSynStream(18, headers); | |
328 | |
329 // TODO(yhirano): Is this behavior correct? | |
330 ASSERT_EQ(0u, connection_->output_list()->size()); | |
331 } | |
332 | |
333 TEST_F(FlipHttpSMTest, SendSynReply) { | |
334 std::string expected = | |
335 "HTTP/1.1 200 OK\r\n" | |
336 "key1: value1\r\n\r\n"; | |
337 BalsaHeaders headers; | |
338 headers.SetResponseFirstlineFromStringPieces("HTTP/1.1", "200", "OK"); | |
339 headers.AppendHeader("key1", "value1"); | |
340 interface_->SendSynReply(18, headers); | |
341 | |
342 ASSERT_EQ(1u, connection_->output_list()->size()); | |
343 DataFrame* df = connection_->output_list()->front(); | |
344 ASSERT_EQ(expected, StringPiece(df->data, df->size)); | |
345 } | |
346 | |
347 TEST_F(FlipHttpSMTest, SendDataFrame) { | |
348 std::string data = "foo bar baz"; | |
349 interface_->SendDataFrame(12, data.data(), data.size(), 0, false); | |
350 | |
351 ASSERT_EQ(1u, connection_->output_list()->size()); | |
352 DataFrame* df = connection_->output_list()->front(); | |
353 ASSERT_EQ("b\r\nfoo bar baz\r\n", StringPiece(df->data, df->size)); | |
354 } | |
355 | |
356 TEST_F(FlipHttpSMProxyTest, ProcessBodyData) { | |
357 BalsaVisitorInterface* visitor = interface_.get(); | |
358 std::string data = "hello, world"; | |
359 { | |
360 InSequence s; | |
361 EXPECT_CALL(*mock_another_interface_, | |
362 SendDataFrame(0, data.data(), data.size(), 0, false)); | |
363 } | |
364 visitor->ProcessBodyData(data.data(), data.size()); | |
365 } | |
366 | |
367 // -- | |
368 // FlipHttpSMProxyTest | |
369 | |
370 TEST_F(FlipHttpSMProxyTest, ProcessHeaders) { | |
371 BalsaVisitorInterface* visitor = interface_.get(); | |
372 { | |
373 InSequence s; | |
374 EXPECT_CALL(*mock_another_interface_, SendSynReply(0, _)); | |
375 } | |
376 BalsaHeaders headers; | |
377 visitor->ProcessHeaders(headers); | |
378 } | |
379 | |
380 TEST_F(FlipHttpSMProxyTest, MessageDone) { | |
381 BalsaVisitorInterface* visitor = interface_.get(); | |
382 { | |
383 InSequence s; | |
384 EXPECT_CALL(*mock_another_interface_, SendEOF(0)); | |
385 } | |
386 visitor->MessageDone(); | |
387 } | |
388 | |
389 TEST_F(FlipHttpSMProxyTest, Cleanup) { | |
390 EXPECT_CALL(*connection_, Cleanup()).Times(0); | |
391 interface_->Cleanup(); | |
392 } | |
393 | |
394 TEST_F(FlipHttpSMProxyTest, SendEOF) { | |
395 { | |
396 InSequence s; | |
397 EXPECT_CALL(*mock_another_interface_, ResetForNewInterface(_)); | |
398 } | |
399 interface_->SendEOF(32); | |
400 ASSERT_EQ(1u, connection_->output_list()->size()); | |
401 DataFrame* df = connection_->output_list()->front(); | |
402 ASSERT_EQ("0\r\n\r\n", StringPiece(df->data, df->size)); | |
403 } | |
404 | |
405 // -- | |
406 // FlipHttpSMHttpTest | |
407 | |
408 TEST_F(FlipHttpSMHttpTest, ProcessHeaders) { | |
409 BalsaVisitorInterface* visitor = interface_.get(); | |
410 { | |
411 BalsaHeaders headers; | |
412 std::string filename = "GET_/path/file"; | |
413 memory_cache_->InsertFile(&headers, filename, ""); | |
414 } | |
415 | |
416 BalsaHeaders headers; | |
417 headers.AppendHeader("Host", "example.com"); | |
418 headers.SetRequestFirstlineFromStringPieces("GET", "/path/file", "HTTP/1.0"); | |
419 uint32_t stream_id = 133; | |
420 interface_->SetStreamID(stream_id); | |
421 ASSERT_FALSE(HasStream(stream_id)); | |
422 visitor->ProcessHeaders(headers); | |
423 ASSERT_TRUE(HasStream(stream_id)); | |
424 } | |
425 | |
426 TEST_F(FlipHttpSMHttpTest, MessageDone) { | |
427 BalsaVisitorInterface* visitor = interface_.get(); | |
428 { | |
429 InSequence s; | |
430 EXPECT_CALL(*mock_another_interface_, SendEOF(0)).Times(0); | |
431 } | |
432 visitor->MessageDone(); | |
433 } | |
434 | |
435 TEST_F(FlipHttpSMHttpTest, Cleanup) { | |
436 EXPECT_CALL(*connection_, Cleanup()).Times(0); | |
437 interface_->Cleanup(); | |
438 } | |
439 | |
440 TEST_F(FlipHttpSMHttpTest, SendEOF) { | |
441 { | |
442 InSequence s; | |
443 EXPECT_CALL(*mock_another_interface_, ResetForNewInterface(_)).Times(0); | |
444 } | |
445 interface_->SendEOF(32); | |
446 ASSERT_EQ(1u, connection_->output_list()->size()); | |
447 DataFrame* df = connection_->output_list()->front(); | |
448 ASSERT_EQ("0\r\n\r\n", StringPiece(df->data, df->size)); | |
449 } | |
450 | |
451 // -- | |
452 // FlipHttpSMSpdyTest | |
453 | |
454 TEST_F(FlipHttpSMSpdyTest, ProcessHeaders) { | |
455 BalsaVisitorInterface* visitor = interface_.get(); | |
456 { | |
457 InSequence s; | |
458 EXPECT_CALL(*mock_another_interface_, SendSynReply(0, _)); | |
459 } | |
460 BalsaHeaders headers; | |
461 visitor->ProcessHeaders(headers); | |
462 } | |
463 | |
464 TEST_F(FlipHttpSMSpdyTest, MessageDone) { | |
465 BalsaVisitorInterface* visitor = interface_.get(); | |
466 { | |
467 InSequence s; | |
468 EXPECT_CALL(*mock_another_interface_, SendEOF(0)).Times(0); | |
469 } | |
470 visitor->MessageDone(); | |
471 } | |
472 | |
473 TEST_F(FlipHttpSMSpdyTest, Cleanup) { | |
474 EXPECT_CALL(*connection_, Cleanup()).Times(0); | |
475 interface_->Cleanup(); | |
476 } | |
477 | |
478 TEST_F(FlipHttpSMSpdyTest, SendEOF) { | |
479 { | |
480 InSequence s; | |
481 EXPECT_CALL(*mock_another_interface_, ResetForNewInterface(_)).Times(0); | |
482 } | |
483 interface_->SendEOF(32); | |
484 ASSERT_EQ(1u, connection_->output_list()->size()); | |
485 DataFrame* df = connection_->output_list()->front(); | |
486 ASSERT_EQ("0\r\n\r\n", StringPiece(df->data, df->size)); | |
487 } | |
488 | |
489 } // namespace | |
490 | |
491 } // namespace net | |
OLD | NEW |