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

Unified Diff: net/tools/quic/quic_simple_server_session_test.cc

Issue 1570343005: relnote: Implement server push methods in QuicSimpleServerSession. Only modify toy Quic server, not… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@0044_CL_111708360
Patch Set: rebase to chain after fix Created 4 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/tools/quic/quic_simple_server_session.cc ('k') | net/tools/quic/quic_simple_server_stream.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/tools/quic/quic_simple_server_session_test.cc
diff --git a/net/tools/quic/quic_simple_server_session_test.cc b/net/tools/quic/quic_simple_server_session_test.cc
index f2e451d7d68bc9a5f4de9d20f691efca7dc1075c..47c3d5fdc91282ff2b05c15238938949aa2a1c9a 100644
--- a/net/tools/quic/quic_simple_server_session_test.cc
+++ b/net/tools/quic/quic_simple_server_session_test.cc
@@ -4,7 +4,10 @@
#include "net/tools/quic/quic_simple_server_session.h"
+#include <algorithm>
+
#include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
#include "net/quic/crypto/quic_crypto_server_config.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/proto/cached_network_parameters.pb.h"
@@ -23,6 +26,7 @@
#include "net/test/gtest_util.h"
#include "net/tools/quic/quic_simple_server_stream.h"
#include "net/tools/quic/test_tools/mock_quic_server_session_visitor.h"
+#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -47,10 +51,69 @@ using net::test::kInitialStreamFlowControlWindowForTest;
using std::string;
using testing::StrictMock;
using testing::_;
+using testing::InSequence;
+using testing::Return;
namespace net {
namespace tools {
namespace test {
+namespace {
+typedef QuicSimpleServerSession::PromisedStreamInfo PromisedStreamInfo;
+} // namespace
+
+class MockQuicHeadersStream : public QuicHeadersStream {
+ public:
+ explicit MockQuicHeadersStream(QuicSpdySession* session)
+ : QuicHeadersStream(session) {}
+
+ MOCK_METHOD4(WritePushPromise,
+ size_t(QuicStreamId original_stream_id,
+ QuicStreamId promised_stream_id,
+ const SpdyHeaderBlock& headers,
+ QuicAckListenerInterface* ack_listener));
+
+ MOCK_METHOD5(WriteHeaders,
+ size_t(QuicStreamId stream_id,
+ const SpdyHeaderBlock& headers,
+ bool fin,
+ SpdyPriority priority,
+ QuicAckListenerInterface* ack_listener));
+};
+
+class MockQuicCryptoServerStream : public QuicCryptoServerStream {
+ public:
+ explicit MockQuicCryptoServerStream(
+ const QuicCryptoServerConfig* crypto_config,
+ QuicSession* session)
+ : QuicCryptoServerStream(crypto_config, session) {}
+ ~MockQuicCryptoServerStream() override {}
+
+ MOCK_METHOD1(SendServerConfigUpdate,
+ void(const CachedNetworkParameters* cached_network_parameters));
+
+ void set_encryption_established(bool has_established) {
+ encryption_established_ = has_established;
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
+};
+
+class MockConnectionWithSendStreamData : public MockConnection {
+ public:
+ MockConnectionWithSendStreamData(MockConnectionHelper* helper,
+ Perspective perspective,
+ const QuicVersionVector& supported_versions)
+ : MockConnection(helper, perspective, supported_versions) {}
+
+ MOCK_METHOD6(SendStreamData,
+ QuicConsumedData(QuicStreamId id,
+ QuicIOVector iov,
+ QuicStreamOffset offset,
+ bool fin,
+ FecProtection fec_protection,
+ QuicAckListenerInterface* listern));
+};
class QuicSimpleServerSessionPeer {
public:
@@ -70,6 +133,15 @@ class QuicSimpleServerSessionPeer {
SpdyPriority priority) {
return s->CreateOutgoingDynamicStream(priority);
}
+
+ static std::deque<PromisedStreamInfo>* promised_streams(
+ QuicSimpleServerSession* s) {
+ return &(s->promised_streams_);
+ }
+
+ static QuicStreamId hightest_promised_stream_id(QuicSimpleServerSession* s) {
+ return s->highest_promised_stream_id_;
+ }
};
namespace {
@@ -89,7 +161,7 @@ class QuicSimpleServerSessionTest
config_.SetInitialSessionFlowControlWindowToSend(
kInitialSessionFlowControlWindowForTest);
- connection_ = new StrictMock<MockConnection>(
+ connection_ = new StrictMock<MockConnectionWithSendStreamData>(
&helper_, Perspective::IS_SERVER, SupportedVersions(GetParam()));
session_.reset(new QuicSimpleServerSession(config_, connection_, &owner_,
&crypto_config_));
@@ -99,16 +171,67 @@ class QuicSimpleServerSessionTest
QuicCryptoServerConfig::ConfigOptions()));
session_->Initialize();
visitor_ = QuicConnectionPeer::GetVisitor(connection_);
+ headers_stream_ = new MockQuicHeadersStream(session_.get());
+ QuicSpdySessionPeer::SetHeadersStream(session_.get(), headers_stream_);
+ }
+
+ // Given |num_resources|, create this number of fake push resources and push
+ // them by sending PUSH_PROMISE for all and sending push responses for as much
+ // as possible(limited by kMaxStreamsForTest).
+ // If |num_resources| > kMaxStreamsForTest, the left over will be queued.
+ void PromisePushResources(size_t num_resources) {
+ // Assume encryption already established.
+ MockQuicCryptoServerStream* crypto_stream =
+ new MockQuicCryptoServerStream(&crypto_config_, session_.get());
+ crypto_stream->set_encryption_established(true);
+ QuicSimpleServerSessionPeer::SetCryptoStream(session_.get(), crypto_stream);
+
+ QuicInMemoryCachePeer::ResetForTests();
+
+ string request_url = "mail.google.com/";
+ SpdyHeaderBlock request_headers;
+ string resource_host = "www.google.com";
+ string partial_push_resource_path = "/server_push_src";
+ string partial_push_response_body =
+ "Push resource body " + partial_push_resource_path;
+ list<QuicInMemoryCache::ServerPushInfo> push_resources;
+ string scheme = "http";
+ for (unsigned int i = 1; i <= num_resources; ++i) {
+ string path = partial_push_resource_path + base::UintToString(i);
+ string url = scheme + "://" + resource_host + "/" + path;
+ GURL resource_url = GURL(url);
+ string body = partial_push_response_body + base::UintToString(i);
+ SpdyHeaderBlock response_headers;
+ QuicInMemoryCache::GetInstance()->AddSimpleResponse(resource_host, path,
+ 200, body);
+ push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
+ resource_url, response_headers, kDefaultPriority, body));
+ // PUSH_PROMISED are sent for all the resources.
+ EXPECT_CALL(*headers_stream_,
+ WritePushPromise(kClientDataStreamId1, i * 2, _, nullptr));
+ if (i <= kMaxStreamsForTest) {
+ // |kMaxStreamsForTest| promised responses should be sent.
+ EXPECT_CALL(*headers_stream_,
+ WriteHeaders(i * 2, _, false, kDefaultPriority, nullptr));
+ // Mock that SendStreamData() returns less than supposed to send to keep
+ // the stream open.
+ EXPECT_CALL(*connection_, SendStreamData(i * 2, _, 0, true, _, nullptr))
+ .WillOnce(Return(QuicConsumedData(0, false)));
+ }
+ }
+ session_->PromisePushResources(request_url, push_resources,
+ kClientDataStreamId1, request_headers);
}
StrictMock<MockQuicServerSessionVisitor> owner_;
MockConnectionHelper helper_;
- StrictMock<MockConnection>* connection_;
+ StrictMock<MockConnectionWithSendStreamData>* connection_;
QuicConfig config_;
QuicCryptoServerConfig crypto_config_;
scoped_ptr<QuicSimpleServerSession> session_;
scoped_ptr<CryptoHandshakeMessage> handshake_message_;
QuicConnectionVisitorInterface* visitor_;
+ MockQuicHeadersStream* headers_stream_;
};
INSTANTIATE_TEST_CASE_P(Tests,
@@ -122,7 +245,7 @@ TEST_P(QuicSimpleServerSessionTest, CloseStreamDueToReset) {
session_->OnStreamFrame(data1);
EXPECT_EQ(1u, session_->GetNumOpenIncomingStreams());
- // Send a reset (and expect the peer to send a RST in response).
+ // Receive a reset (and send a RST in response).
QuicRstStreamFrame rst1(kClientDataStreamId1, QUIC_ERROR_PROCESSING_STREAM,
0);
EXPECT_CALL(*connection_,
@@ -212,25 +335,6 @@ TEST_P(QuicSimpleServerSessionTest, CreateIncomingDynamicStream) {
EXPECT_EQ(kClientDataStreamId1, stream->id());
}
-class MockQuicCryptoServerStream : public QuicCryptoServerStream {
- public:
- explicit MockQuicCryptoServerStream(
- const QuicCryptoServerConfig* crypto_config,
- QuicSession* session)
- : QuicCryptoServerStream(crypto_config, session) {}
- ~MockQuicCryptoServerStream() override {}
-
- MOCK_METHOD1(SendServerConfigUpdate,
- void(const CachedNetworkParameters* cached_network_parameters));
-
- void set_encryption_established(bool has_established) {
- encryption_established_ = has_established;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockQuicCryptoServerStream);
-};
-
TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamDisconnected) {
// Tests that outgoing stream creation fails when connection is not connected.
size_t initial_num_open_stream = session_->GetNumOpenOutgoingStreams();
@@ -290,6 +394,110 @@ TEST_P(QuicSimpleServerSessionTest, CreateOutgoingDynamicStreamUptoLimit) {
EXPECT_EQ(2u, session_->GetNumOpenIncomingStreams());
}
+TEST_P(QuicSimpleServerSessionTest, OnStreamFrameWithEvenStreamId) {
+ QuicStreamFrame frame(2, false, 0, StringPiece());
+ EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(
+ QUIC_INVALID_STREAM_ID,
+ "Client sent data on server push stream"));
+ session_->OnStreamFrame(frame);
+}
+
+TEST_P(QuicSimpleServerSessionTest, TestPromisePushResources) {
+ // Tests that given more than kMaxOpenStreamForTest resources, all their
+ // PUSH_PROMISE's will be sent out and only |kMaxOpenStreamForTest| streams
+ // will be opened and send push response.
+ size_t num_resources = kMaxStreamsForTest + 5;
+ PromisePushResources(num_resources);
+ EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
+}
+
+TEST_P(QuicSimpleServerSessionTest,
+ HandlePromisedPushRequestsAfterStreamDraining) {
+ // Tests that after promised stream queued up, when an opened stream is marked
+ // draining, a queued promised stream will become open and send push response.
+ size_t num_resources = kMaxStreamsForTest + 1;
+ PromisePushResources(num_resources);
+ QuicStreamId next_out_going_stream_id = num_resources * 2;
+
+ // After an open stream is marked draining, a new stream is expected to be
+ // created and a response sent on the stream.
+ EXPECT_CALL(*headers_stream_, WriteHeaders(next_out_going_stream_id, _, false,
+ kDefaultPriority, nullptr));
+ EXPECT_CALL(*connection_,
+ SendStreamData(next_out_going_stream_id, _, 0, true, _, nullptr))
+ .WillOnce(Return(QuicConsumedData(0, false)));
+ session_->StreamDraining(2);
+ // Number of open outgoing streams should still be the same, because a new
+ // stream is opened. And the queue should be empty.
+ EXPECT_EQ(kMaxStreamsForTest, session_->GetNumOpenOutgoingStreams());
+}
+
+TEST_P(QuicSimpleServerSessionTest, GetEvenIncomingError) {
+ // Tests that calling GetOrCreateDynamicStream() on an outgoing stream not
+ // promised yet should result close connection.
+ EXPECT_CALL(*connection_,
+ SendConnectionCloseWithDetails(QUIC_INVALID_STREAM_ID,
+ "Data for nonexistent stream"));
+ EXPECT_EQ(nullptr,
+ QuicSessionPeer::GetOrCreateDynamicStream(session_.get(), 4));
+}
+
+TEST_P(QuicSimpleServerSessionTest, ResetPromisedStreamToCancelServerPush) {
+ // Tests that after all resources are promised, a RST frame from client can
+ // prevent a promised resource to be send out.
+
+ // Having two extra resources to be send later. One of them will be reset, so
+ // when opened stream become close, only one will become open.
+ size_t num_resources = kMaxStreamsForTest + 2;
+ PromisePushResources(num_resources);
+
+ // Reset the last stream in the queue. It should be marked cancelled.
+ QuicStreamId stream_got_reset = num_resources * 2;
+ QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0);
+ EXPECT_CALL(*connection_,
+ SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, 0));
+ visitor_->OnRstStream(rst);
+
+ // When the first 2 streams becomes draining, the two queued up stream could
+ // be created. But since one of them was marked cancelled due to RST frame,
+ // only one queued resource will be sent out.
+ QuicStreamId stream_not_reset = (kMaxStreamsForTest + 1) * 2;
+ InSequence s;
+ EXPECT_CALL(*headers_stream_, WriteHeaders(stream_not_reset, _, false,
+ kDefaultPriority, nullptr));
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_not_reset, _, 0, true, _, nullptr))
+ .WillOnce(Return(QuicConsumedData(0, false)));
+ EXPECT_CALL(*headers_stream_, WriteHeaders(stream_got_reset, _, false,
+ kDefaultPriority, nullptr))
+ .Times(0);
+
+ session_->StreamDraining(2);
+ session_->StreamDraining(4);
+}
+
+TEST_P(QuicSimpleServerSessionTest, CloseStreamToHandleMorePromisedStream) {
+ // Tests that closing a open outgoing stream can trigger a promised resource
+ // in the queue to be send out.
+ size_t num_resources = kMaxStreamsForTest + 1;
+ PromisePushResources(num_resources);
+ QuicStreamId stream_to_open = num_resources * 2;
+
+ // Resetting 1st open stream will close the stream and give space for extra
+ // stream to be opened.
+ QuicStreamId stream_got_reset = 2;
+ EXPECT_CALL(*connection_,
+ SendRstStream(stream_got_reset, QUIC_RST_ACKNOWLEDGEMENT, _));
+ EXPECT_CALL(*headers_stream_, WriteHeaders(stream_to_open, _, false,
+ kDefaultPriority, nullptr));
+ EXPECT_CALL(*connection_,
+ SendStreamData(stream_to_open, _, 0, true, _, nullptr))
+ .WillOnce(Return(QuicConsumedData(0, false)));
+
+ QuicRstStreamFrame rst(stream_got_reset, QUIC_STREAM_CANCELLED, 0);
+ visitor_->OnRstStream(rst);
+}
+
} // namespace
} // namespace test
} // namespace tools
« no previous file with comments | « net/tools/quic/quic_simple_server_session.cc ('k') | net/tools/quic/quic_simple_server_stream.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698