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

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

Issue 1746803003: Add 3 Quic e2e tests of server push. No behavior change. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@115218980
Patch Set: Created 4 years, 10 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 | « no previous file | net/tools/quic/test_tools/quic_test_client.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/tools/quic/end_to_end_test.cc
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index ff07c60277a2e1026b8d71a68bc7d54acf0892fd..97e0c1f5364efdb7dc6e6937e6e1626281734b47 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -2180,8 +2180,55 @@ TEST_P(EndToEndTest, Trailers) {
EXPECT_EQ(trailers, client_->response_trailers());
}
-TEST_P(EndToEndTest, ServerPush) {
- FLAGS_quic_supports_push_promise = true;
+class EndToEndTestServerPush : public EndToEndTest {
+ protected:
+ const size_t kNumMaxStreams = 10;
+
+ EndToEndTestServerPush() : EndToEndTest() {
+ FLAGS_quic_supports_push_promise = true;
+ FLAGS_quic_different_max_num_open_streams = true;
+ client_config_.SetMaxStreamsPerConnection(kNumMaxStreams, kNumMaxStreams);
+ }
+
+ // Add a request with its response and |num_resources| push resources into
+ // cache.
+ // If |resource_size| == 0, response body of push resources use default string
+ // concatenating with resource url. Otherwise, generate a string of
+ // |resource_size| as body.
+ void AddRequestAndResponseWithServerPush(string host,
+ string path,
+ string response_body,
+ string* push_urls,
+ const size_t num_resources,
+ const size_t resource_size) {
+ bool use_large_response = resource_size != 0;
+ string large_resource;
+ if (use_large_response) {
+ // Generate a response common body larger than flow control window for
+ // push response.
+ test::GenerateBody(&large_resource, resource_size);
+ }
+ list<QuicInMemoryCache::ServerPushInfo> push_resources;
+ for (size_t i = 0; i < num_resources; ++i) {
+ string url = push_urls[i];
+ GURL resource_url(url);
+ string body = use_large_response
+ ? large_resource
+ : "This is server push response body for " + url;
+ SpdyHeaderBlock response_headers;
+ response_headers[":version"] = "HTTP/1.1";
+ response_headers[":status"] = "200";
+ response_headers["content-length"] = IntToString(body.size());
+ push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
+ resource_url, response_headers, kV3LowestPriority, body));
+ }
+
+ QuicInMemoryCache::GetInstance()->AddSimpleResponseWithServerPushResources(
+ host, path, 200, response_body, push_resources);
+ }
+};
+
+TEST_P(EndToEndTestServerPush, ServerPush) {
ASSERT_TRUE(Initialize());
client_->client()->WaitForCryptoHandshakeConfirmed();
@@ -2189,41 +2236,198 @@ TEST_P(EndToEndTest, ServerPush) {
SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
SetReorderPercentage(30);
- // Add a response with headers, body, and trailers.
+ // Add a response with headers, body, and push resources.
const string kBody = "body content";
-
- list<QuicInMemoryCache::ServerPushInfo> push_resources;
-
+ size_t kNumResources = 4;
string push_urls[] = {
"https://google.com/font.woff", "https://google.com/script.js",
"https://fonts.google.com/font.woff", "https://google.com/logo-hires.jpg",
};
+ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
+ push_urls, kNumResources, 0);
+
+ client_->client()->set_response_listener(new TestResponseListener);
+
+ DVLOG(1) << "send request for /push_example";
+ EXPECT_EQ(kBody, client_->SendSynchronousRequest(
+ "https://example.com/push_example"));
for (const string& url : push_urls) {
- GURL resource_url(url);
- string body = "This is server push response body for " + url;
- SpdyHeaderBlock response_headers;
- response_headers[":version"] = "HTTP/1.1";
- response_headers[":status"] = "200";
- response_headers["content-length"] = IntToString(body.size());
- push_resources.push_back(QuicInMemoryCache::ServerPushInfo(
- resource_url, response_headers, kV3LowestPriority, body));
+ DVLOG(1) << "send request for pushed stream on url " << url;
+ string expected_body = "This is server push response body for " + url;
+ string response_body = client_->SendSynchronousRequest(url);
+ DVLOG(1) << "response body " << response_body;
+ EXPECT_EQ(expected_body, response_body);
}
+}
+
+TEST_P(EndToEndTestServerPush, ServerPushUnderLimit) {
+ // Tests that sending a request which has 4 push resources will trigger server
+ // to push those 4 resources and client can handle pushed resources and match
+ // them with requests later.
+ ASSERT_TRUE(Initialize());
+
+ client_->client()->WaitForCryptoHandshakeConfirmed();
- QuicInMemoryCache::GetInstance()->AddSimpleResponseWithServerPushResources(
- "google.com", "/push_example", 200, kBody, push_resources);
+ // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(30);
+ // Add a response with headers, body, and push resources.
+ const string kBody = "body content";
+ size_t const kNumResources = 4;
+ string push_urls[] = {
+ "https://example.com/font.woff", "https://example.com/script.js",
+ "https://fonts.example.com/font.woff",
+ "https://example.com/logo-hires.jpg",
+ };
+ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
+ push_urls, kNumResources, 0);
client_->client()->set_response_listener(new TestResponseListener);
- DVLOG(1) << "send request for /push_example";
- EXPECT_EQ(kBody,
- client_->SendSynchronousRequest("https://google.com/push_example"));
- for (const string& url : push_urls) {
+ // Send the first request: this will trigger the server to send all the push
+ // resources associated with this request, and these will be cached by the
+ // client.
+ EXPECT_EQ(kBody, client_->SendSynchronousRequest(
+ "https://example.com/push_example"));
+ EXPECT_EQ(1u + kNumResources, client_->num_responses());
+
+ for (string url : push_urls) {
+ // Sending subsequent requesets will not actually send anything on the wire,
+ // as the responses are already in the client's cache.
DVLOG(1) << "send request for pushed stream on url " << url;
string expected_body = "This is server push response body for " + url;
string response_body = client_->SendSynchronousRequest(url);
DVLOG(1) << "response body " << response_body;
EXPECT_EQ(expected_body, response_body);
}
+ // Expect only original request has been sent and push responses have been
+ // received as normal response.
+ EXPECT_EQ(1u, client_->num_requests());
+}
+
+TEST_P(EndToEndTestServerPush, ServerPushOverLimitNonBlocking) {
+ // Tests that when streams are not blocked by flow control or congestion
+ // control, pushing even more resources than max number of open outgoing
+ // streams should still work because all response streams get closed
+ // immediately after pushing resources.
+ ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+
+ // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(30);
+
+ // Add a response with headers, body, and push resources.
+ const string kBody = "body content";
+
+ // One more resource than max number of outgoing stream of this session.
+ const size_t kNumResources = 1 + kNumMaxStreams; // 11.
+ string push_urls[11];
+ for (uint32_t i = 0; i < kNumResources; ++i) {
+ push_urls[i] = "https://example.com/push_resources" + base::UintToString(i);
+ }
+ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
+ push_urls, kNumResources, 0);
+ client_->client()->set_response_listener(new TestResponseListener);
+
+ // Send the first request: this will trigger the server to send all the push
+ // resources associated with this request, and these will be cached by the
+ // client.
+ EXPECT_EQ(kBody, client_->SendSynchronousRequest(
+ "https://example.com/push_example"));
+ // The responses to the original request and all the promised resources
+ // should have been received.
+ EXPECT_EQ(12u, client_->num_responses());
+
+ for (const string& url : push_urls) {
+ // Sending subsequent requesets will not actually send anything on the wire,
+ // as the responses are already in the client's cache.
+ EXPECT_EQ("This is server push response body for " + url,
+ client_->SendSynchronousRequest(url));
+ }
+
+ // Only 1 request should have been sent.
+ EXPECT_EQ(1u, client_->num_requests());
+}
+
+TEST_P(EndToEndTestServerPush, ServerPushOverLimitWithBlocking) {
+ // Tests that when server tries to send more large resources(large enough to
+ // be blocked by flow control window or congestion control window) than max
+ // open outgoing streams , server can open upto max number of outgoing
+ // streams for them, and the rest will be queued up.
+
+ // Reset flow control windows.
+ size_t kFlowControlWnd = 20 * 1024; // 20KB.
+ // Response body is larger than 1 flow controlblock window.
+ size_t kBodySize = kFlowControlWnd * 2;
+ set_client_initial_stream_flow_control_receive_window(kFlowControlWnd);
+ // Make sure conntection level flow control window is large enough not to
+ // block data being sent out though they will be blocked by stream level one.
+ set_client_initial_session_flow_control_receive_window(
+ kBodySize * kNumMaxStreams + 1024);
+
+ ASSERT_TRUE(Initialize());
+ client_->client()->WaitForCryptoHandshakeConfirmed();
+
+ // Set reordering to ensure that body arriving before PUSH_PROMISE is ok.
+ SetPacketSendDelay(QuicTime::Delta::FromMilliseconds(2));
+ SetReorderPercentage(30);
+
+ // Add a response with headers, body, and push resources.
+ const string kBody = "body content";
+
+ const size_t kNumResources = kNumMaxStreams + 1;
+ string push_urls[11];
+ for (uint32_t i = 0; i < kNumResources; ++i) {
+ push_urls[i] = "http://example.com/push_resources" + base::UintToString(i);
+ }
+ AddRequestAndResponseWithServerPush("example.com", "/push_example", kBody,
+ push_urls, kNumResources, kBodySize);
+
+ client_->client()->set_response_listener(new TestResponseListener);
+
+ client_->SendRequest("https://example.com/push_example");
+
+ // Pause after the first response arrives.
+ while (!client_->response_complete()) {
+ // Because of priority, the first response arrived should be to original
+ // request.
+ client_->WaitForResponse();
+ }
+
+ // Check server session to see if it has max number of outgoing streams opened
+ // though more resources need to be pushed.
+ server_thread_->Pause();
+ QuicDispatcher* dispatcher =
+ QuicServerPeer::GetDispatcher(server_thread_->server());
+ ASSERT_EQ(1u, dispatcher->session_map().size());
+ QuicSession* session = dispatcher->session_map().begin()->second;
+ EXPECT_EQ(kNumMaxStreams, session->GetNumOpenOutgoingStreams());
+ server_thread_->Resume();
+
+ EXPECT_EQ(1u, client_->num_requests());
+ EXPECT_EQ(1u, client_->num_responses());
+ EXPECT_EQ(kBody, client_->response_body());
+
+ // "Send" request for a promised resources will not really send out it because
+ // its response is being pushed(but blocked). And the following ack and
+ // flow control behavior of SendSynchronousRequests()
+ // will unblock the stream to finish receiving response.
+ client_->SendSynchronousRequest(push_urls[0]);
+ EXPECT_EQ(1u, client_->num_requests());
+ EXPECT_EQ(2u, client_->num_responses());
+
+ // Do same thing for the rest 10 resources.
+ for (uint32_t i = 1; i < kNumResources; ++i) {
+ client_->SendSynchronousRequest(push_urls[i]);
+ }
+
+ // Because of server push, client gets all pushed resources without actually
+ // sending requests for them.
+ EXPECT_EQ(1u, client_->num_requests());
+ // Including response to original request, 12 responses in total were
+ // recieved.
+ EXPECT_EQ(12u, client_->num_responses());
}
} // namespace
« no previous file with comments | « no previous file | net/tools/quic/test_tools/quic_test_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698