| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/http/http_network_transaction.h" | 5 #include "net/http/http_network_transaction.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 protected: | 40 protected: |
| 41 | 41 |
| 42 virtual void SetUp() { | 42 virtual void SetUp() { |
| 43 SpdySession::set_default_protocol(kProtoSPDY3); | 43 SpdySession::set_default_protocol(kProtoSPDY3); |
| 44 google_get_request_initialized_ = false; | 44 google_get_request_initialized_ = false; |
| 45 google_post_request_initialized_ = false; | 45 google_post_request_initialized_ = false; |
| 46 google_chunked_post_request_initialized_ = false; | 46 google_chunked_post_request_initialized_ = false; |
| 47 } | 47 } |
| 48 | 48 |
| 49 virtual void TearDown() { | 49 virtual void TearDown() { |
| 50 UploadDataStream::ResetMergeChunks(); |
| 50 // Empty the current queue. | 51 // Empty the current queue. |
| 51 MessageLoop::current()->RunAllPending(); | 52 MessageLoop::current()->RunAllPending(); |
| 52 } | 53 } |
| 53 | 54 |
| 55 void set_merge_chunks(bool merge) { |
| 56 UploadDataStream::set_merge_chunks(merge); |
| 57 } |
| 58 |
| 54 struct TransactionHelperResult { | 59 struct TransactionHelperResult { |
| 55 int rv; | 60 int rv; |
| 56 std::string status_line; | 61 std::string status_line; |
| 57 std::string response_data; | 62 std::string response_data; |
| 58 HttpResponseInfo response_info; | 63 HttpResponseInfo response_info; |
| 59 }; | 64 }; |
| 60 | 65 |
| 61 // A helper class that handles all the initial npn/ssl setup. | 66 // A helper class that handles all the initial npn/ssl setup. |
| 62 class NormalSpdyTransactionHelper { | 67 class NormalSpdyTransactionHelper { |
| 63 public: | 68 public: |
| (...skipping 14 matching lines...) Expand all Loading... |
| 78 case SPDYNOSSL: | 83 case SPDYNOSSL: |
| 79 case SPDYSSL: | 84 case SPDYSSL: |
| 80 port_ = 80; | 85 port_ = 80; |
| 81 break; | 86 break; |
| 82 case SPDYNPN: | 87 case SPDYNPN: |
| 83 port_ = 443; | 88 port_ = 443; |
| 84 break; | 89 break; |
| 85 default: | 90 default: |
| 86 NOTREACHED(); | 91 NOTREACHED(); |
| 87 } | 92 } |
| 88 } | 93 } |
| 89 | |
| 90 | 94 |
| 91 ~NormalSpdyTransactionHelper() { | 95 ~NormalSpdyTransactionHelper() { |
| 92 // Any test which doesn't close the socket by sending it an EOF will | 96 // Any test which doesn't close the socket by sending it an EOF will |
| 93 // have a valid session left open, which leaks the entire session pool. | 97 // have a valid session left open, which leaks the entire session pool. |
| 94 // This is just fine - in fact, some of our tests intentionally do this | 98 // This is just fine - in fact, some of our tests intentionally do this |
| 95 // so that we can check consistency of the SpdySessionPool as the test | 99 // so that we can check consistency of the SpdySessionPool as the test |
| 96 // finishes. If we had put an EOF on the socket, the SpdySession would | 100 // finishes. If we had put an EOF on the socket, the SpdySession would |
| 97 // have closed and we wouldn't be able to check the consistency. | 101 // have closed and we wouldn't be able to check the consistency. |
| 98 | 102 |
| 99 // Forcefully close existing sessions here. | 103 // Forcefully close existing sessions here. |
| (...skipping 1488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1588 BoundNetLog(), GetParam(), NULL); | 1592 BoundNetLog(), GetParam(), NULL); |
| 1589 helper.RunToCompletion(data.get()); | 1593 helper.RunToCompletion(data.get()); |
| 1590 TransactionHelperResult out = helper.output(); | 1594 TransactionHelperResult out = helper.output(); |
| 1591 EXPECT_EQ(OK, out.rv); | 1595 EXPECT_EQ(OK, out.rv); |
| 1592 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); | 1596 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line); |
| 1593 EXPECT_EQ("hello!", out.response_data); | 1597 EXPECT_EQ("hello!", out.response_data); |
| 1594 } | 1598 } |
| 1595 | 1599 |
| 1596 // Test that a chunked POST works. | 1600 // Test that a chunked POST works. |
| 1597 TEST_P(SpdyNetworkTransactionSpdy3Test, ChunkedPost) { | 1601 TEST_P(SpdyNetworkTransactionSpdy3Test, ChunkedPost) { |
| 1598 UploadDataStream::set_merge_chunks(false); | 1602 set_merge_chunks(false); |
| 1603 |
| 1599 scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); | 1604 scoped_ptr<SpdyFrame> req(ConstructChunkedSpdyPost(NULL, 0)); |
| 1600 scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false)); | 1605 scoped_ptr<SpdyFrame> chunk1(ConstructSpdyBodyFrame(1, false)); |
| 1601 scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true)); | 1606 scoped_ptr<SpdyFrame> chunk2(ConstructSpdyBodyFrame(1, true)); |
| 1602 MockWrite writes[] = { | 1607 MockWrite writes[] = { |
| 1603 CreateMockWrite(*req), | 1608 CreateMockWrite(*req), |
| 1604 CreateMockWrite(*chunk1), | 1609 CreateMockWrite(*chunk1), |
| 1605 CreateMockWrite(*chunk2), | 1610 CreateMockWrite(*chunk2), |
| 1606 }; | 1611 }; |
| 1607 | 1612 |
| 1608 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); | 1613 scoped_ptr<SpdyFrame> resp(ConstructSpdyPostSynReply(NULL, 0)); |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2023 // Force write of WINDOW_UPDATE which was scheduled during the above | 2028 // Force write of WINDOW_UPDATE which was scheduled during the above |
| 2024 // read. | 2029 // read. |
| 2025 MessageLoop::current()->RunAllPending(); | 2030 MessageLoop::current()->RunAllPending(); |
| 2026 | 2031 |
| 2027 // Read EOF. | 2032 // Read EOF. |
| 2028 data->CompleteRead(); | 2033 data->CompleteRead(); |
| 2029 | 2034 |
| 2030 helper.VerifyDataConsumed(); | 2035 helper.VerifyDataConsumed(); |
| 2031 } | 2036 } |
| 2032 | 2037 |
| 2033 // Test that WINDOW_UPDATE frame causing overflow is handled correctly. We | 2038 // Test that WINDOW_UPDATE frame causing overflow is handled correctly. |
| 2034 // use the same trick as in the above test to enforce our scenario. | |
| 2035 TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateOverflow) { | 2039 TEST_P(SpdyNetworkTransactionSpdy3Test, WindowUpdateOverflow) { |
| 2036 // number of full frames we hope to write (but will not, used to | 2040 // Number of full frames we hope to write (but will not, used to |
| 2037 // set content-length header correctly) | 2041 // set content-length header correctly) |
| 2038 static int kFrameCount = 3; | 2042 static int kFrameCount = 3; |
| 2039 | 2043 |
| 2040 scoped_ptr<std::string> content( | 2044 scoped_ptr<std::string> content( |
| 2041 new std::string(kMaxSpdyFrameChunkSize, 'a')); | 2045 new std::string(kMaxSpdyFrameChunkSize, 'a')); |
| 2042 scoped_ptr<SpdyFrame> req(ConstructSpdyPost( | 2046 scoped_ptr<SpdyFrame> req(ConstructSpdyPost( |
| 2043 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0)); | 2047 kMaxSpdyFrameChunkSize * kFrameCount, NULL, 0)); |
| 2044 scoped_ptr<SpdyFrame> body( | 2048 scoped_ptr<SpdyFrame> body( |
| 2045 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false)); | 2049 ConstructSpdyBodyFrame(1, content->c_str(), content->size(), false)); |
| 2046 scoped_ptr<SpdyFrame> rst( | 2050 scoped_ptr<SpdyFrame> rst( |
| 2047 ConstructSpdyRstStream(1, FLOW_CONTROL_ERROR)); | 2051 ConstructSpdyRstStream(1, FLOW_CONTROL_ERROR)); |
| 2048 | 2052 |
| 2049 // We're not going to write a data frame with FIN, we'll receive a bad | 2053 // We're not going to write a data frame with FIN, we'll receive a bad |
| 2050 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame. | 2054 // WINDOW_UPDATE while sending a request and will send a RST_STREAM frame. |
| 2051 MockWrite writes[] = { | 2055 MockWrite writes[] = { |
| 2052 CreateMockWrite(*req), | 2056 CreateMockWrite(*req, 0), |
| 2053 CreateMockWrite(*body), | 2057 CreateMockWrite(*body, 2), |
| 2054 CreateMockWrite(*rst), | 2058 CreateMockWrite(*rst, 3), |
| 2055 }; | 2059 }; |
| 2056 | 2060 |
| 2057 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow | 2061 static const int32 kDeltaWindowSize = 0x7fffffff; // cause an overflow |
| 2058 scoped_ptr<SpdyFrame> window_update( | 2062 scoped_ptr<SpdyFrame> window_update( |
| 2059 ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); | 2063 ConstructSpdyWindowUpdate(1, kDeltaWindowSize)); |
| 2060 scoped_ptr<SpdyFrame> window_update2( | |
| 2061 ConstructSpdyWindowUpdate(2, kDeltaWindowSize)); | |
| 2062 scoped_ptr<SpdyFrame> reply(ConstructSpdyPostSynReply(NULL, 0)); | |
| 2063 | |
| 2064 MockRead reads[] = { | 2064 MockRead reads[] = { |
| 2065 CreateMockRead(*window_update2), | 2065 CreateMockRead(*window_update, 1), |
| 2066 CreateMockRead(*window_update2), | 2066 MockRead(ASYNC, 0, 4) // EOF |
| 2067 CreateMockRead(*window_update), | |
| 2068 CreateMockRead(*window_update), | |
| 2069 CreateMockRead(*window_update), | |
| 2070 MockRead(ASYNC, ERR_IO_PENDING, 0), // Wait for the RST to be written. | |
| 2071 MockRead(ASYNC, 0, 0) // EOF | |
| 2072 }; | 2067 }; |
| 2073 | 2068 |
| 2074 scoped_ptr<DelayedSocketData> data( | 2069 scoped_ptr<DeterministicSocketData> data( |
| 2075 new DelayedSocketData(0, reads, arraysize(reads), | 2070 new DeterministicSocketData(reads, arraysize(reads), |
| 2076 writes, arraysize(writes))); | 2071 writes, arraysize(writes))); |
| 2077 | 2072 |
| 2078 // Setup the request | 2073 // Setup the request |
| 2079 HttpRequestInfo request; | 2074 HttpRequestInfo request; |
| 2080 request.method = "POST"; | 2075 request.method = "POST"; |
| 2081 request.url = GURL("http://www.google.com/"); | 2076 request.url = GURL("http://www.google.com/"); |
| 2082 request.upload_data = new UploadData(); | 2077 request.upload_data = new UploadData(); |
| 2083 for (int i = 0; i < kFrameCount; ++i) | 2078 for (int i = 0; i < kFrameCount; ++i) |
| 2084 request.upload_data->AppendBytes(content->c_str(), content->size()); | 2079 request.upload_data->AppendBytes(content->c_str(), content->size()); |
| 2085 | 2080 |
| 2086 NormalSpdyTransactionHelper helper(request, | 2081 NormalSpdyTransactionHelper helper(request, |
| 2087 BoundNetLog(), GetParam(), NULL); | 2082 BoundNetLog(), GetParam(), NULL); |
| 2088 helper.AddData(data.get()); | 2083 helper.SetDeterministic(); |
| 2089 helper.RunPreTestSetup(); | 2084 helper.RunPreTestSetup(); |
| 2090 | 2085 helper.AddDeterministicData(data.get()); |
| 2091 HttpNetworkTransaction* trans = helper.trans(); | 2086 HttpNetworkTransaction* trans = helper.trans(); |
| 2092 | 2087 |
| 2093 TestCompletionCallback callback; | 2088 TestCompletionCallback callback; |
| 2094 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); | 2089 int rv = trans->Start(&helper.request(), callback.callback(), BoundNetLog()); |
| 2090 ASSERT_EQ(ERR_IO_PENDING, rv); |
| 2095 | 2091 |
| 2096 EXPECT_EQ(ERR_IO_PENDING, rv); | 2092 data->RunFor(5); |
| 2097 rv = callback.WaitForResult(); | 2093 ASSERT_TRUE(callback.have_result()); |
| 2098 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, rv); | 2094 EXPECT_EQ(ERR_SPDY_PROTOCOL_ERROR, callback.WaitForResult()); |
| 2099 | |
| 2100 data->CompleteRead(); | |
| 2101 | |
| 2102 ASSERT_TRUE(helper.session() != NULL); | |
| 2103 ASSERT_TRUE(helper.session()->spdy_session_pool() != NULL); | |
| 2104 helper.session()->spdy_session_pool()->CloseAllSessions(); | |
| 2105 helper.VerifyDataConsumed(); | 2095 helper.VerifyDataConsumed(); |
| 2106 } | 2096 } |
| 2107 | 2097 |
| 2108 // Test that after hitting a send window size of 0, the write process | 2098 // Test that after hitting a send window size of 0, the write process |
| 2109 // stalls and upon receiving WINDOW_UPDATE frame write resumes. | 2099 // stalls and upon receiving WINDOW_UPDATE frame write resumes. |
| 2110 | 2100 |
| 2111 // This test constructs a POST request followed by enough data frames | 2101 // This test constructs a POST request followed by enough data frames |
| 2112 // containing 'a' that would make the window size 0, followed by another | 2102 // containing 'a' that would make the window size 0, followed by another |
| 2113 // data frame containing default content (which is "hello!") and this frame | 2103 // data frame containing default content (which is "hello!") and this frame |
| 2114 // also contains a FIN flag. DelayedSocketData is used to enforce all | 2104 // also contains a FIN flag. DelayedSocketData is used to enforce all |
| (...skipping 4092 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6207 // And now we can allow everything else to run to completion. | 6197 // And now we can allow everything else to run to completion. |
| 6208 data->SetStop(10); | 6198 data->SetStop(10); |
| 6209 data->Run(); | 6199 data->Run(); |
| 6210 EXPECT_EQ(OK, callback2.WaitForResult()); | 6200 EXPECT_EQ(OK, callback2.WaitForResult()); |
| 6211 EXPECT_EQ(OK, callback3.WaitForResult()); | 6201 EXPECT_EQ(OK, callback3.WaitForResult()); |
| 6212 | 6202 |
| 6213 helper.VerifyDataConsumed(); | 6203 helper.VerifyDataConsumed(); |
| 6214 } | 6204 } |
| 6215 | 6205 |
| 6216 } // namespace net | 6206 } // namespace net |
| OLD | NEW |