blob: e5f5db14e4d9611504e96a05fbb8bf7fc343f459 [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:
23 void CreateRequest(QuicString host,
24 QuicString path,
25 spdy::SpdyHeaderBlock* headers) {
26 (*headers)[":method"] = "GET";
27 (*headers)[":path"] = path;
28 (*headers)[":authority"] = host;
29 (*headers)[":scheme"] = "https";
30 }
31
32 QuicString CacheDirectory() { return QuicGetTestMemoryCachePath(); }
33
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) {
44 QuicString response_body("hello response");
45 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) {
57 const QuicString kRequestHost = "www.foo.com";
58 const QuicString kRequestPath = "/";
59 const QuicString kResponseBody("hello response");
60
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) {
154 QuicString request_host = "www.foo.com";
155 QuicString response_body("hello response");
156 const size_t kNumResources = 5;
157 int NumResources = 5;
158 std::list<ServerPushInfo> push_resources;
159 QuicString scheme = "http";
160 for (int i = 0; i < NumResources; ++i) {
161 QuicString path = "/server_push_src" + QuicTextUtils::Uint64ToString(i);
162 QuicString url = scheme + "://" + request_host + path;
163 QuicUrl resource_url(url);
164 QuicString body =
165 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
178 QuicString request_url = request_host + "/";
179 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) {
192 QuicString request_host = "www.foo.com";
193 QuicString response_body("hello response");
194 const size_t kNumResources = 4;
195 int NumResources = 4;
196 QuicString scheme = "http";
197 QuicString push_response_status[kNumResources] = {"200", "200", "301", "404"};
198 std::list<ServerPushInfo> push_resources;
199 for (int i = 0; i < NumResources; ++i) {
200 QuicString path = "/server_push_src" + QuicTextUtils::Uint64ToString(i);
201 QuicString url = scheme + "://" + request_host + path;
202 QuicUrl resource_url(url);
203 QuicString body = "This is server push response body for " + path;
204 spdy::SpdyHeaderBlock response_headers;
205 response_headers[":version"] = "HTTP/1.1";
206 response_headers[":status"] = push_response_status[i];
207 response_headers["content-length"] =
208 QuicTextUtils::Uint64ToString(body.size());
209 push_resources.push_back(
210 ServerPushInfo(resource_url, response_headers.Clone(), i, body));
211 }
212 cache_.AddSimpleResponseWithServerPushResources(
213 request_host, "/", 200, response_body, push_resources);
214 QuicString request_url = request_host + "/";
215 std::list<ServerPushInfo> resources =
216 cache_.GetServerPushResources(request_url);
217 ASSERT_EQ(kNumResources, resources.size());
218 int i = 0;
219 for (const auto& push_resource : push_resources) {
220 QuicUrl url = resources.front().request_url;
221 QuicString host = url.host();
222 QuicString path = url.path();
223 const Response* response = cache_.GetResponse(host, path);
224 ASSERT_TRUE(response);
225 ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
226 EXPECT_EQ(push_response_status[i++],
227 response->headers().find(":status")->second);
228 EXPECT_EQ(push_resource.body, response->body());
229 resources.pop_front();
230 }
231}
232
233} // namespace test
234} // namespace quic