blob: 80b1b29320649064ba3dee71542b08813886028c [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.h"
6
7#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
8#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
9#include "net/third_party/quiche/src/quic/platform/api/quic_test.h"
10#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
11#include "net/third_party/quiche/src/quic/tools/quic_backend_response.h"
12
13namespace quic {
14namespace test {
15
16namespace {
17typedef QuicBackendResponse Response;
18typedef QuicBackendResponse::ServerPushInfo ServerPushInfo;
19} // namespace
20
21class QuicMemoryCacheBackendTest : public QuicTest {
22 protected:
vasilvvc48c8712019-03-11 13:38:16 -070023 void CreateRequest(std::string host,
24 std::string path,
QUICHE teama6ef0a62019-03-07 20:34:33 -050025 spdy::SpdyHeaderBlock* headers) {
26 (*headers)[":method"] = "GET";
27 (*headers)[":path"] = path;
28 (*headers)[":authority"] = host;
29 (*headers)[":scheme"] = "https";
30 }
31
vasilvvc48c8712019-03-11 13:38:16 -070032 std::string CacheDirectory() { return QuicGetTestMemoryCachePath(); }
QUICHE teama6ef0a62019-03-07 20:34:33 -050033
34 QuicMemoryCacheBackend cache_;
35};
36
37TEST_F(QuicMemoryCacheBackendTest, GetResponseNoMatch) {
38 const Response* response =
39 cache_.GetResponse("mail.google.com", "/index.html");
40 ASSERT_FALSE(response);
41}
42
43TEST_F(QuicMemoryCacheBackendTest, AddSimpleResponseGetResponse) {
vasilvvc48c8712019-03-11 13:38:16 -070044 std::string response_body("hello response");
QUICHE teama6ef0a62019-03-07 20:34:33 -050045 cache_.AddSimpleResponse("www.google.com", "/", 200, response_body);
46
47 spdy::SpdyHeaderBlock request_headers;
48 CreateRequest("www.google.com", "/", &request_headers);
49 const Response* response = cache_.GetResponse("www.google.com", "/");
50 ASSERT_TRUE(response);
51 ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
52 EXPECT_EQ("200", response->headers().find(":status")->second);
53 EXPECT_EQ(response_body.size(), response->body().length());
54}
55
56TEST_F(QuicMemoryCacheBackendTest, AddResponse) {
vasilvvc48c8712019-03-11 13:38:16 -070057 const std::string kRequestHost = "www.foo.com";
58 const std::string kRequestPath = "/";
59 const std::string kResponseBody("hello response");
QUICHE teama6ef0a62019-03-07 20:34:33 -050060
61 spdy::SpdyHeaderBlock response_headers;
62 response_headers[":version"] = "HTTP/1.1";
63 response_headers[":status"] = "200";
64 response_headers["content-length"] =
65 QuicTextUtils::Uint64ToString(kResponseBody.size());
66
67 spdy::SpdyHeaderBlock response_trailers;
68 response_trailers["key-1"] = "value-1";
69 response_trailers["key-2"] = "value-2";
70 response_trailers["key-3"] = "value-3";
71
72 cache_.AddResponse(kRequestHost, "/", response_headers.Clone(), kResponseBody,
73 response_trailers.Clone());
74
75 const Response* response = cache_.GetResponse(kRequestHost, kRequestPath);
76 EXPECT_EQ(response->headers(), response_headers);
77 EXPECT_EQ(response->body(), kResponseBody);
78 EXPECT_EQ(response->trailers(), response_trailers);
79}
80
81TEST_F(QuicMemoryCacheBackendTest, ReadsCacheDir) {
82 cache_.InitializeBackend(CacheDirectory());
83 const Response* response =
84 cache_.GetResponse("test.example.com", "/index.html");
85 ASSERT_TRUE(response);
86 ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
87 EXPECT_EQ("200", response->headers().find(":status")->second);
88 // Connection headers are not valid in HTTP/2.
89 EXPECT_FALSE(QuicContainsKey(response->headers(), "connection"));
90 EXPECT_LT(0U, response->body().length());
91}
92
93TEST_F(QuicMemoryCacheBackendTest, ReadsCacheDirWithServerPushResource) {
94 cache_.InitializeBackend(CacheDirectory() + "_with_push");
95 std::list<ServerPushInfo> resources =
96 cache_.GetServerPushResources("test.example.com/");
97 ASSERT_EQ(1UL, resources.size());
98}
99
100TEST_F(QuicMemoryCacheBackendTest, ReadsCacheDirWithServerPushResources) {
101 cache_.InitializeBackend(CacheDirectory() + "_with_push");
102 std::list<ServerPushInfo> resources =
103 cache_.GetServerPushResources("test.example.com/index2.html");
104 ASSERT_EQ(2UL, resources.size());
105}
106
107TEST_F(QuicMemoryCacheBackendTest, UsesOriginalUrl) {
108 cache_.InitializeBackend(CacheDirectory());
109 const Response* response =
110 cache_.GetResponse("test.example.com", "/site_map.html");
111 ASSERT_TRUE(response);
112 ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
113 EXPECT_EQ("200", response->headers().find(":status")->second);
114 // Connection headers are not valid in HTTP/2.
115 EXPECT_FALSE(QuicContainsKey(response->headers(), "connection"));
116 EXPECT_LT(0U, response->body().length());
117}
118
119TEST_F(QuicMemoryCacheBackendTest, DefaultResponse) {
120 // Verify GetResponse returns nullptr when no default is set.
121 const Response* response = cache_.GetResponse("www.google.com", "/");
122 ASSERT_FALSE(response);
123
124 // Add a default response.
125 spdy::SpdyHeaderBlock response_headers;
126 response_headers[":version"] = "HTTP/1.1";
127 response_headers[":status"] = "200";
128 response_headers["content-length"] = "0";
129 Response* default_response = new Response;
130 default_response->set_headers(std::move(response_headers));
131 cache_.AddDefaultResponse(default_response);
132
133 // Now we should get the default response for the original request.
134 response = cache_.GetResponse("www.google.com", "/");
135 ASSERT_TRUE(response);
136 ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
137 EXPECT_EQ("200", response->headers().find(":status")->second);
138
139 // Now add a set response for / and make sure it is returned
140 cache_.AddSimpleResponse("www.google.com", "/", 302, "");
141 response = cache_.GetResponse("www.google.com", "/");
142 ASSERT_TRUE(response);
143 ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
144 EXPECT_EQ("302", response->headers().find(":status")->second);
145
146 // We should get the default response for other requests.
147 response = cache_.GetResponse("www.google.com", "/asd");
148 ASSERT_TRUE(response);
149 ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
150 EXPECT_EQ("200", response->headers().find(":status")->second);
151}
152
153TEST_F(QuicMemoryCacheBackendTest, AddSimpleResponseWithServerPushResources) {
vasilvvc48c8712019-03-11 13:38:16 -0700154 std::string request_host = "www.foo.com";
155 std::string response_body("hello response");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500156 const size_t kNumResources = 5;
157 int NumResources = 5;
158 std::list<ServerPushInfo> push_resources;
vasilvvc48c8712019-03-11 13:38:16 -0700159 std::string scheme = "http";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 for (int i = 0; i < NumResources; ++i) {
vasilvvc48c8712019-03-11 13:38:16 -0700161 std::string path = "/server_push_src" + QuicTextUtils::Uint64ToString(i);
162 std::string url = scheme + "://" + request_host + path;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500163 QuicUrl resource_url(url);
vasilvvc48c8712019-03-11 13:38:16 -0700164 std::string body =
QUICHE teama6ef0a62019-03-07 20:34:33 -0500165 QuicStrCat("This is server push response body for ", path);
166 spdy::SpdyHeaderBlock response_headers;
167 response_headers[":version"] = "HTTP/1.1";
168 response_headers[":status"] = "200";
169 response_headers["content-length"] =
170 QuicTextUtils::Uint64ToString(body.size());
171 push_resources.push_back(
172 ServerPushInfo(resource_url, response_headers.Clone(), i, body));
173 }
174
175 cache_.AddSimpleResponseWithServerPushResources(
176 request_host, "/", 200, response_body, push_resources);
177
vasilvvc48c8712019-03-11 13:38:16 -0700178 std::string request_url = request_host + "/";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500179 std::list<ServerPushInfo> resources =
180 cache_.GetServerPushResources(request_url);
181 ASSERT_EQ(kNumResources, resources.size());
182 for (const auto& push_resource : push_resources) {
183 ServerPushInfo resource = resources.front();
184 EXPECT_EQ(resource.request_url.ToString(),
185 push_resource.request_url.ToString());
186 EXPECT_EQ(resource.priority, push_resource.priority);
187 resources.pop_front();
188 }
189}
190
191TEST_F(QuicMemoryCacheBackendTest, GetServerPushResourcesAndPushResponses) {
vasilvvc48c8712019-03-11 13:38:16 -0700192 std::string request_host = "www.foo.com";
193 std::string response_body("hello response");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194 const size_t kNumResources = 4;
195 int NumResources = 4;
vasilvvc48c8712019-03-11 13:38:16 -0700196 std::string scheme = "http";
197 std::string push_response_status[kNumResources] = {"200", "200", "301",
198 "404"};
QUICHE teama6ef0a62019-03-07 20:34:33 -0500199 std::list<ServerPushInfo> push_resources;
200 for (int i = 0; i < NumResources; ++i) {
vasilvvc48c8712019-03-11 13:38:16 -0700201 std::string path = "/server_push_src" + QuicTextUtils::Uint64ToString(i);
202 std::string url = scheme + "://" + request_host + path;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500203 QuicUrl resource_url(url);
vasilvvc48c8712019-03-11 13:38:16 -0700204 std::string body = "This is server push response body for " + path;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500205 spdy::SpdyHeaderBlock response_headers;
206 response_headers[":version"] = "HTTP/1.1";
207 response_headers[":status"] = push_response_status[i];
208 response_headers["content-length"] =
209 QuicTextUtils::Uint64ToString(body.size());
210 push_resources.push_back(
211 ServerPushInfo(resource_url, response_headers.Clone(), i, body));
212 }
213 cache_.AddSimpleResponseWithServerPushResources(
214 request_host, "/", 200, response_body, push_resources);
vasilvvc48c8712019-03-11 13:38:16 -0700215 std::string request_url = request_host + "/";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500216 std::list<ServerPushInfo> resources =
217 cache_.GetServerPushResources(request_url);
218 ASSERT_EQ(kNumResources, resources.size());
219 int i = 0;
220 for (const auto& push_resource : push_resources) {
221 QuicUrl url = resources.front().request_url;
vasilvvc48c8712019-03-11 13:38:16 -0700222 std::string host = url.host();
223 std::string path = url.path();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500224 const Response* response = cache_.GetResponse(host, path);
225 ASSERT_TRUE(response);
226 ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
227 EXPECT_EQ(push_response_status[i++],
228 response->headers().find(":status")->second);
229 EXPECT_EQ(push_resource.body, response->body());
230 resources.pop_front();
231 }
232}
233
234} // namespace test
235} // namespace quic