Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(229)

Side by Side Diff: net/spdy/spdy_http_stream_unittest.cc

Issue 2022053002: Introduce error handling in SpdyHttpStream on UploadDataStream::Read() failure. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« net/spdy/spdy_http_stream.cc ('K') | « net/spdy/spdy_http_stream.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/spdy/spdy_http_stream.h" 5 #include "net/spdy/spdy_http_stream.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info)); 68 EXPECT_TRUE(stream.GetLoadTimingInfo(&load_timing_info));
69 69
70 EXPECT_FALSE(load_timing_info.socket_reused); 70 EXPECT_FALSE(load_timing_info.socket_reused);
71 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id); 71 EXPECT_NE(NetLog::Source::kInvalidId, load_timing_info.socket_log_id);
72 72
73 ExpectConnectTimingHasTimes(load_timing_info.connect_timing, 73 ExpectConnectTimingHasTimes(load_timing_info.connect_timing,
74 CONNECT_TIMING_HAS_DNS_TIMES); 74 CONNECT_TIMING_HAS_DNS_TIMES);
75 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info); 75 ExpectLoadTimingHasOnlyConnectionTimes(load_timing_info);
76 } 76 }
77 77
78 class ReadErrorUploadDataStream : public UploadDataStream {
79 public:
80 enum class FailureMode { SYNC, ASYNC };
81
82 explicit ReadErrorUploadDataStream(FailureMode mode)
83 : UploadDataStream(true, 0), async_(mode), weak_factory_(this) {}
84
85 private:
86 void CompleteRead() { UploadDataStream::OnReadCompleted(ERR_FAILED); }
87
88 // UploadDataStream implementation:
89 int InitInternal() override { return OK; }
90
91 int ReadInternal(IOBuffer* buf, int buf_len) override {
92 if (async_ == FailureMode::ASYNC) {
93 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
94 FROM_HERE, base::Bind(&ReadErrorUploadDataStream::CompleteRead,
95 weak_factory_.GetWeakPtr()),
96 base::TimeDelta::FromSeconds(1));
97 return ERR_IO_PENDING;
98 }
99 return ERR_FAILED;
100 }
101
102 void ResetInternal() override {}
103
104 const FailureMode async_;
105
106 base::WeakPtrFactory<ReadErrorUploadDataStream> weak_factory_;
107
108 DISALLOW_COPY_AND_ASSIGN(ReadErrorUploadDataStream);
109 };
110
78 } // namespace 111 } // namespace
79 112
80 class SpdyHttpStreamTest : public testing::Test, 113 class SpdyHttpStreamTest : public testing::Test,
81 public testing::WithParamInterface<TestCase> { 114 public testing::WithParamInterface<TestCase> {
82 public: 115 public:
83 SpdyHttpStreamTest() 116 SpdyHttpStreamTest()
84 : spdy_util_(GetProtocol(), GetDependenciesFromPriority()), 117 : spdy_util_(GetProtocol(), GetDependenciesFromPriority()),
85 session_deps_(GetProtocol()) { 118 session_deps_(GetProtocol()) {
86 session_deps_.enable_priority_dependencies = GetDependenciesFromPriority(); 119 session_deps_.enable_priority_dependencies = GetDependenciesFromPriority();
87 session_deps_.net_log = &net_log_; 120 session_deps_.net_log = &net_log_;
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 HttpRequestHeaders headers; 464 HttpRequestHeaders headers;
432 BoundNetLog net_log; 465 BoundNetLog net_log;
433 SpdyHttpStream http_stream(session_, true); 466 SpdyHttpStream http_stream(session_, true);
434 ASSERT_EQ(OK, http_stream.InitializeStream(&request, DEFAULT_PRIORITY, 467 ASSERT_EQ(OK, http_stream.InitializeStream(&request, DEFAULT_PRIORITY,
435 net_log, CompletionCallback())); 468 net_log, CompletionCallback()));
436 469
437 EXPECT_EQ(ERR_IO_PENDING, 470 EXPECT_EQ(ERR_IO_PENDING,
438 http_stream.SendRequest(headers, &response, callback.callback())); 471 http_stream.SendRequest(headers, &response, callback.callback()));
439 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key)); 472 EXPECT_TRUE(HasSpdySession(http_session_->spdy_session_pool(), key));
440 473
441 EXPECT_EQ(OK, callback.WaitForResult()); 474 // Server closes the connection. Thus, callback now returns
475 // "CONNECTION_CLOSED" error.
476 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
442 477
443 EXPECT_EQ(static_cast<int64_t>(req->size() + body->size()), 478 EXPECT_EQ(static_cast<int64_t>(req->size() + body->size()),
444 http_stream.GetTotalSentBytes()); 479 http_stream.GetTotalSentBytes());
445 EXPECT_EQ(0, http_stream.GetTotalReceivedBytes()); 480 EXPECT_EQ(0, http_stream.GetTotalReceivedBytes());
446 481
447 // Because the server closed the connection, we there shouldn't be a session 482 // Because the server closed the connection, we there shouldn't be a session
448 // in the pool anymore. 483 // in the pool anymore.
449 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key)); 484 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key));
450 485
451 // Appending a second chunk now should not result in a crash. 486 // Appending a second chunk now should not result in a crash.
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize)); 916 scoped_refptr<IOBuffer> buf1(new IOBuffer(kUploadDataSize));
882 ASSERT_EQ(kUploadDataSize, 917 ASSERT_EQ(kUploadDataSize,
883 http_stream->ReadResponseBody( 918 http_stream->ReadResponseBody(
884 buf1.get(), kUploadDataSize, callback.callback())); 919 buf1.get(), kUploadDataSize, callback.callback()));
885 EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize)); 920 EXPECT_EQ(kUploadData, std::string(buf1->data(), kUploadDataSize));
886 921
887 ASSERT_TRUE(response.headers.get()); 922 ASSERT_TRUE(response.headers.get());
888 ASSERT_EQ(200, response.headers->response_code()); 923 ASSERT_EQ(200, response.headers->response_code());
889 } 924 }
890 925
926 TEST_P(SpdyHttpStreamTest, DataReadErrorSynchronous) {
927 BufferedSpdyFramer framer(spdy_util_.spdy_version());
928
929 std::unique_ptr<SpdySerializedFrame> req(
930 spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
mmenke 2016/06/01 17:24:07 Note that my comments apply to both test. nit: n
931 std::unique_ptr<SpdySerializedFrame> rst_frame(
932 framer.CreateRstStream(1, RST_STREAM_INTERNAL_ERROR));
mmenke 2016/06/01 17:24:07 This should probably use spdy_util_.ConstructSpdyF
maksims (do not use this acc) 2016/06/03 11:39:08 spdy_util_.ConstructSpdyRstStream does the great j
933 MockWrite writes[] = {
934 CreateMockWrite(*req, 0, SYNCHRONOUS), // request
935 CreateMockWrite(*rst_frame, 1, SYNCHRONOUS) // POST upload frame
936 };
937
938 std::unique_ptr<SpdySerializedFrame> resp(
939 spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
940 MockRead reads[] = {
941 CreateMockRead(*resp, 2), CreateMockRead(*rst_frame, 3),
mmenke 2016/06/01 17:24:07 Are these frames needed?
maksims (do not use this acc) 2016/06/02 12:43:12 Otherwise I got !AllReadDataConsumed failures.
mmenke 2016/06/02 15:02:10 Even if you just have the "MockRead(SYNCHRONOUS, 0
maksims (do not use this acc) 2016/06/03 11:39:08 Oh, I got it. the resp frame is needed, but the rs
942 MockRead(SYNCHRONOUS, 0, 4),
943 };
944
945 HostPortPair host_port_pair("www.example.org", 80);
946 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
947 PRIVACY_MODE_DISABLED);
948 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
949 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
950 ReadErrorUploadDataStream upload_data_stream(
951 ReadErrorUploadDataStream::FailureMode::SYNC);
952 ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback()));
953
954 HttpRequestInfo request;
955 request.method = "POST";
956 request.url = GURL("http://www.example.org/");
957 request.upload_data_stream = &upload_data_stream;
958
959 TestCompletionCallback callback;
960 HttpResponseInfo response;
961 HttpRequestHeaders headers;
962 BoundNetLog net_log;
963 SpdyHttpStream http_stream(session_, true);
964 ASSERT_EQ(OK, http_stream.InitializeStream(&request, DEFAULT_PRIORITY,
965 net_log, CompletionCallback()));
966
967 int result = http_stream.SendRequest(headers, &response, callback.callback());
968 EXPECT_EQ(ERR_FAILED, callback.GetResult(result));
969
970 // Because the server has not closed the connection yet, there shouldn't be
971 // a stream but a session in the pool
972 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key));
973 }
974
975 TEST_P(SpdyHttpStreamTest, DataReadErrorAsynchronous) {
976 BufferedSpdyFramer framer(spdy_util_.spdy_version());
977
978 std::unique_ptr<SpdySerializedFrame> req(
979 spdy_util_.ConstructChunkedSpdyPost(NULL, 0));
980
981 // Server receives RST_STREAM_INTERNAL_ERROR on clients an internal failure.
982 // The failure is reading error in this case cause by
983 // UploadDataStream::Read()
984 std::unique_ptr<SpdySerializedFrame> rst_frame(
985 framer.CreateRstStream(1, RST_STREAM_INTERNAL_ERROR));
986 MockWrite writes[] = {
987 CreateMockWrite(*req, 0), // Request
988 CreateMockWrite(*rst_frame, 1) // Reset frame
989 };
990
991 std::unique_ptr<SpdySerializedFrame> resp(
992 spdy_util_.ConstructSpdyPostSynReply(NULL, 0));
993 MockRead reads[] = {
994 CreateMockRead(*resp, 2),
995 CreateMockRead(*rst_frame, 3),
996 MockRead(ASYNC, 0, 4),
997 };
998
999 HostPortPair host_port_pair("www.example.org", 80);
1000 SpdySessionKey key(host_port_pair, ProxyServer::Direct(),
1001 PRIVACY_MODE_DISABLED);
1002 InitSession(reads, arraysize(reads), writes, arraysize(writes), key);
1003 EXPECT_EQ(spdy_util_.spdy_version(), session_->GetProtocolVersion());
1004
1005 ReadErrorUploadDataStream upload_data_stream(
1006 ReadErrorUploadDataStream::FailureMode::ASYNC);
1007 ASSERT_EQ(OK, upload_data_stream.Init(TestCompletionCallback().callback()));
1008
1009 HttpRequestInfo request;
1010 request.method = "POST";
1011 request.url = GURL("http://www.example.org/");
1012 request.upload_data_stream = &upload_data_stream;
1013
1014 TestCompletionCallback callback;
1015 HttpResponseInfo response;
1016 HttpRequestHeaders headers;
1017 BoundNetLog net_log;
1018 SpdyHttpStream http_stream(session_, true);
1019 ASSERT_EQ(OK, http_stream.InitializeStream(&request, DEFAULT_PRIORITY,
1020 net_log, CompletionCallback()));
1021
1022 int result = http_stream.SendRequest(headers, &response, callback.callback());
1023 EXPECT_EQ(ERR_IO_PENDING, result);
1024
1025 // Headers sent
1026 EXPECT_EQ(OK, callback.GetResult(result));
1027
1028 // Body read failed
1029 EXPECT_EQ(ERR_FAILED, callback.GetResult(result));
1030
1031 // Because the server has closed the connection, there shouldn't be a session
1032 // in the pool anymore.
1033 EXPECT_FALSE(HasSpdySession(http_session_->spdy_session_pool(), key));
1034 }
1035
891 // TODO(willchan): Write a longer test for SpdyStream that exercises all 1036 // TODO(willchan): Write a longer test for SpdyStream that exercises all
892 // methods. 1037 // methods.
893 1038
894 } // namespace net 1039 } // namespace net
OLDNEW
« net/spdy/spdy_http_stream.cc ('K') | « net/spdy/spdy_http_stream.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698