| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/tools/quic/quic_spdy_client_stream.h" | 5 #include "net/tools/quic/quic_spdy_client_stream.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 | 8 |
| 9 #include "base/macros.h" | 9 #include "base/macros.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "net/quic/core/quic_utils.h" | 11 #include "net/quic/core/quic_utils.h" |
| 12 #include "net/quic/core/spdy_utils.h" | 12 #include "net/quic/core/spdy_utils.h" |
| 13 #include "net/quic/test_tools/crypto_test_utils.h" | 13 #include "net/quic/test_tools/crypto_test_utils.h" |
| 14 #include "net/quic/test_tools/quic_test_utils.h" | 14 #include "net/quic/test_tools/quic_test_utils.h" |
| 15 #include "net/tools/quic/quic_client_session.h" | 15 #include "net/tools/quic/quic_client_session.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" | 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 | 18 |
| 19 using base::IntToString; |
| 19 using net::test::CryptoTestUtils; | 20 using net::test::CryptoTestUtils; |
| 20 using net::test::DefaultQuicConfig; | 21 using net::test::DefaultQuicConfig; |
| 21 using net::test::MockQuicConnection; | 22 using net::test::MockQuicConnection; |
| 22 using net::test::MockQuicConnectionHelper; | 23 using net::test::MockQuicConnectionHelper; |
| 23 using net::test::SupportedVersions; | 24 using net::test::SupportedVersions; |
| 24 using net::test::kClientDataStreamId1; | 25 using net::test::kClientDataStreamId1; |
| 25 using net::test::kServerDataStreamId1; | 26 using net::test::kServerDataStreamId1; |
| 26 using net::test::kInitialSessionFlowControlWindowForTest; | 27 using net::test::kInitialSessionFlowControlWindowForTest; |
| 27 using net::test::kInitialStreamFlowControlWindowForTest; | 28 using net::test::kInitialStreamFlowControlWindowForTest; |
| 28 | 29 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 QuicSpdyClientStreamTest() | 64 QuicSpdyClientStreamTest() |
| 64 : connection_(new StrictMock<MockQuicConnection>(&helper_, | 65 : connection_(new StrictMock<MockQuicConnection>(&helper_, |
| 65 &alarm_factory_, | 66 &alarm_factory_, |
| 66 Perspective::IS_CLIENT)), | 67 Perspective::IS_CLIENT)), |
| 67 session_(connection_, &push_promise_index_), | 68 session_(connection_, &push_promise_index_), |
| 68 body_("hello world") { | 69 body_("hello world") { |
| 69 session_.Initialize(); | 70 session_.Initialize(); |
| 70 | 71 |
| 71 headers_[":status"] = "200"; | 72 headers_[":status"] = "200"; |
| 72 headers_["content-length"] = "11"; | 73 headers_["content-length"] = "11"; |
| 73 headers_string_ = SpdyUtils::SerializeUncompressedHeaders(headers_); | |
| 74 | 74 |
| 75 stream_.reset(new QuicSpdyClientStream(kClientDataStreamId1, &session_)); | 75 stream_.reset(new QuicSpdyClientStream(kClientDataStreamId1, &session_)); |
| 76 stream_visitor_.reset(new StreamVisitor()); | 76 stream_visitor_.reset(new StreamVisitor()); |
| 77 stream_->set_visitor(stream_visitor_.get()); | 77 stream_->set_visitor(stream_visitor_.get()); |
| 78 } | 78 } |
| 79 | 79 |
| 80 class StreamVisitor : public QuicSpdyClientStream::Visitor { | 80 class StreamVisitor : public QuicSpdyClientStream::Visitor { |
| 81 void OnClose(QuicSpdyStream* stream) override { | 81 void OnClose(QuicSpdyStream* stream) override { |
| 82 DVLOG(1) << "stream " << stream->id(); | 82 DVLOG(1) << "stream " << stream->id(); |
| 83 } | 83 } |
| 84 }; | 84 }; |
| 85 | 85 |
| 86 MockQuicConnectionHelper helper_; | 86 MockQuicConnectionHelper helper_; |
| 87 MockAlarmFactory alarm_factory_; | 87 MockAlarmFactory alarm_factory_; |
| 88 StrictMock<MockQuicConnection>* connection_; | 88 StrictMock<MockQuicConnection>* connection_; |
| 89 QuicClientPushPromiseIndex push_promise_index_; | 89 QuicClientPushPromiseIndex push_promise_index_; |
| 90 | 90 |
| 91 MockQuicClientSession session_; | 91 MockQuicClientSession session_; |
| 92 std::unique_ptr<QuicSpdyClientStream> stream_; | 92 std::unique_ptr<QuicSpdyClientStream> stream_; |
| 93 std::unique_ptr<StreamVisitor> stream_visitor_; | 93 std::unique_ptr<StreamVisitor> stream_visitor_; |
| 94 SpdyHeaderBlock headers_; | 94 SpdyHeaderBlock headers_; |
| 95 string headers_string_; | |
| 96 string body_; | 95 string body_; |
| 97 }; | 96 }; |
| 98 | 97 |
| 99 TEST_F(QuicSpdyClientStreamTest, TestReceivingIllegalResponseStatusCode) { | 98 TEST_F(QuicSpdyClientStreamTest, TestReceivingIllegalResponseStatusCode) { |
| 100 headers_[":status"] = "200 ok"; | 99 headers_[":status"] = "200 ok"; |
| 101 headers_string_ = SpdyUtils::SerializeUncompressedHeaders(headers_); | |
| 102 | 100 |
| 103 stream_->OnStreamHeaders(headers_string_); | |
| 104 EXPECT_CALL(*connection_, | 101 EXPECT_CALL(*connection_, |
| 105 SendRstStream(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD, 0)); | 102 SendRstStream(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD, 0)); |
| 106 stream_->OnStreamHeadersComplete(false, headers_string_.size()); | 103 auto headers = AsHeaderList(headers_); |
| 104 stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 105 headers); |
| 107 EXPECT_EQ(QUIC_BAD_APPLICATION_PAYLOAD, stream_->stream_error()); | 106 EXPECT_EQ(QUIC_BAD_APPLICATION_PAYLOAD, stream_->stream_error()); |
| 108 } | 107 } |
| 109 | 108 |
| 110 TEST_F(QuicSpdyClientStreamTest, TestFraming) { | 109 TEST_F(QuicSpdyClientStreamTest, TestFraming) { |
| 111 stream_->OnStreamHeaders(headers_string_); | 110 auto headers = AsHeaderList(headers_); |
| 112 stream_->OnStreamHeadersComplete(false, headers_string_.size()); | 111 stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 112 headers); |
| 113 stream_->OnStreamFrame( | 113 stream_->OnStreamFrame( |
| 114 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); | 114 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); |
| 115 EXPECT_EQ("200", stream_->response_headers().find(":status")->second); | 115 EXPECT_EQ("200", stream_->response_headers().find(":status")->second); |
| 116 EXPECT_EQ(200, stream_->response_code()); | 116 EXPECT_EQ(200, stream_->response_code()); |
| 117 EXPECT_EQ(body_, stream_->data()); | 117 EXPECT_EQ(body_, stream_->data()); |
| 118 } | 118 } |
| 119 | 119 |
| 120 TEST_F(QuicSpdyClientStreamTest, TestFramingOnePacket) { | 120 TEST_F(QuicSpdyClientStreamTest, TestFramingOnePacket) { |
| 121 stream_->OnStreamHeaders(headers_string_); | 121 auto headers = AsHeaderList(headers_); |
| 122 stream_->OnStreamHeadersComplete(false, headers_string_.size()); | 122 stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 123 headers); |
| 123 stream_->OnStreamFrame( | 124 stream_->OnStreamFrame( |
| 124 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); | 125 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); |
| 125 EXPECT_EQ("200", stream_->response_headers().find(":status")->second); | 126 EXPECT_EQ("200", stream_->response_headers().find(":status")->second); |
| 126 EXPECT_EQ(200, stream_->response_code()); | 127 EXPECT_EQ(200, stream_->response_code()); |
| 127 EXPECT_EQ(body_, stream_->data()); | 128 EXPECT_EQ(body_, stream_->data()); |
| 128 } | 129 } |
| 129 | 130 |
| 130 TEST_F(QuicSpdyClientStreamTest, DISABLED_TestFramingExtraData) { | 131 TEST_F(QuicSpdyClientStreamTest, DISABLED_TestFramingExtraData) { |
| 131 string large_body = "hello world!!!!!!"; | 132 string large_body = "hello world!!!!!!"; |
| 132 | 133 |
| 133 stream_->OnStreamHeaders(headers_string_); | 134 auto headers = AsHeaderList(headers_); |
| 134 stream_->OnStreamHeadersComplete(false, headers_string_.size()); | 135 stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 136 headers); |
| 135 // The headers should parse successfully. | 137 // The headers should parse successfully. |
| 136 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); | 138 EXPECT_EQ(QUIC_STREAM_NO_ERROR, stream_->stream_error()); |
| 137 EXPECT_EQ("200", stream_->response_headers().find(":status")->second); | 139 EXPECT_EQ("200", stream_->response_headers().find(":status")->second); |
| 138 EXPECT_EQ(200, stream_->response_code()); | 140 EXPECT_EQ(200, stream_->response_code()); |
| 139 | 141 |
| 140 EXPECT_CALL(*connection_, | 142 EXPECT_CALL(*connection_, |
| 141 SendRstStream(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD, 0)); | 143 SendRstStream(stream_->id(), QUIC_BAD_APPLICATION_PAYLOAD, 0)); |
| 142 stream_->OnStreamFrame( | 144 stream_->OnStreamFrame( |
| 143 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, large_body)); | 145 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, large_body)); |
| 144 | 146 |
| 145 EXPECT_NE(QUIC_STREAM_NO_ERROR, stream_->stream_error()); | 147 EXPECT_NE(QUIC_STREAM_NO_ERROR, stream_->stream_error()); |
| 146 } | 148 } |
| 147 | 149 |
| 148 TEST_F(QuicSpdyClientStreamTest, TestNoBidirectionalStreaming) { | 150 TEST_F(QuicSpdyClientStreamTest, TestNoBidirectionalStreaming) { |
| 149 QuicStreamFrame frame(kClientDataStreamId1, false, 3, StringPiece("asd")); | 151 QuicStreamFrame frame(kClientDataStreamId1, false, 3, StringPiece("asd")); |
| 150 | 152 |
| 151 EXPECT_FALSE(stream_->write_side_closed()); | 153 EXPECT_FALSE(stream_->write_side_closed()); |
| 152 stream_->OnStreamFrame(frame); | 154 stream_->OnStreamFrame(frame); |
| 153 EXPECT_TRUE(stream_->write_side_closed()); | 155 EXPECT_TRUE(stream_->write_side_closed()); |
| 154 } | 156 } |
| 155 | 157 |
| 156 TEST_F(QuicSpdyClientStreamTest, ReceivingTrailers) { | 158 TEST_F(QuicSpdyClientStreamTest, ReceivingTrailers) { |
| 157 // Test that receiving trailing headers, containing a final offset, results in | 159 // Test that receiving trailing headers, containing a final offset, results in |
| 158 // the stream being closed at that byte offset. | 160 // the stream being closed at that byte offset. |
| 159 // Send headers as usual. | 161 // Send headers as usual. |
| 160 stream_->OnStreamHeaders(headers_string_); | 162 auto headers = AsHeaderList(headers_); |
| 161 stream_->OnStreamHeadersComplete(false, headers_string_.size()); | 163 stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(), |
| 164 headers); |
| 162 | 165 |
| 163 // Send trailers before sending the body. Even though a FIN has been received | 166 // Send trailers before sending the body. Even though a FIN has been received |
| 164 // the stream should not be closed, as it does not yet have all the data bytes | 167 // the stream should not be closed, as it does not yet have all the data bytes |
| 165 // promised by the final offset field. | 168 // promised by the final offset field. |
| 166 SpdyHeaderBlock trailers; | 169 SpdyHeaderBlock trailer_block; |
| 167 trailers["trailer key"] = "trailer value"; | 170 trailer_block["trailer key"] = "trailer value"; |
| 168 trailers[kFinalOffsetHeaderKey] = base::IntToString(body_.size()); | 171 trailer_block[kFinalOffsetHeaderKey] = IntToString(body_.size()); |
| 169 string trailers_string = SpdyUtils::SerializeUncompressedHeaders(trailers); | 172 auto trailers = AsHeaderList(trailer_block); |
| 170 stream_->OnStreamHeaders(trailers_string); | 173 stream_->OnStreamHeaderList(true, trailers.uncompressed_header_bytes(), |
| 171 stream_->OnStreamHeadersComplete(true, trailers_string.size()); | 174 trailers); |
| 172 | 175 |
| 173 // Now send the body, which should close the stream as the FIN has been | 176 // Now send the body, which should close the stream as the FIN has been |
| 174 // received, as well as all data. | 177 // received, as well as all data. |
| 175 EXPECT_CALL(session_, CloseStream(stream_->id())); | 178 EXPECT_CALL(session_, CloseStream(stream_->id())); |
| 176 stream_->OnStreamFrame( | 179 stream_->OnStreamFrame( |
| 177 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); | 180 QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, body_)); |
| 178 } | 181 } |
| 179 | 182 |
| 180 } // namespace | 183 } // namespace |
| 181 } // namespace test | 184 } // namespace test |
| 182 } // namespace net | 185 } // namespace net |
| OLD | NEW |