1 // Copyright 2014 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 "components/data_reduction_proxy/common/data_reduction_proxy_headers.h"
6
7 #include "net/http/http_response_headers.h"
8 #include "net/proxy/proxy_service.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 namespace {
12
13 // Transform "normal"-looking headers (\n-separated) to the appropriate
14 // input format for ParseRawHeaders (\0-separated).
HeadersToRaw(std::string * headers)15 void HeadersToRaw(std::string* headers) {
16 std::replace(headers->begin(), headers->end(), '\n', '\0');
17 if (!headers->empty())
18 *headers += '\0';
19 }
20
21 } // namespace
22
23 namespace data_reduction_proxy {
24
25 class DataReductionProxyHeadersTest : public testing::Test {};
26
TEST_F(DataReductionProxyHeadersTest,GetProxyBypassInfo)27 TEST_F(DataReductionProxyHeadersTest, GetProxyBypassInfo) {
28 const struct {
29 const char* headers;
30 bool expected_result;
31 int64 expected_retry_delay;
32 bool expected_bypass_all;
33 } tests[] = {
34 { "HTTP/1.1 200 OK\n"
35 "Content-Length: 999\n",
36 false,
37 0,
38 false,
39 },
40 { "HTTP/1.1 200 OK\n"
41 "connection: keep-alive\n"
42 "Content-Length: 999\n",
43 false,
44 0,
45 false,
46 },
47 { "HTTP/1.1 200 OK\n"
48 "connection: keep-alive\n"
49 "Chrome-Proxy: bypass=86400\n"
50 "Content-Length: 999\n",
51 true,
52 86400,
53 false,
54 },
55 { "HTTP/1.1 200 OK\n"
56 "connection: keep-alive\n"
57 "Chrome-Proxy: bypass=0\n"
58 "Content-Length: 999\n",
59 true,
60 0,
61 false,
62 },
63 { "HTTP/1.1 200 OK\n"
64 "connection: keep-alive\n"
65 "Chrome-Proxy: bypass=-1\n"
66 "Content-Length: 999\n",
67 false,
68 0,
69 false,
70 },
71 { "HTTP/1.1 200 OK\n"
72 "connection: keep-alive\n"
73 "Chrome-Proxy: bypass=xyz\n"
74 "Content-Length: 999\n",
75 false,
76 0,
77 false,
78 },
79 { "HTTP/1.1 200 OK\n"
80 "connection: keep-alive\n"
81 "Chrome-Proxy: bypass\n"
82 "Content-Length: 999\n",
83 false,
84 0,
85 false,
86 },
87 { "HTTP/1.1 200 OK\n"
88 "connection: keep-alive\n"
89 "Chrome-Proxy: foo=abc, bypass=86400\n"
90 "Content-Length: 999\n",
91 true,
92 86400,
93 false,
94 },
95 { "HTTP/1.1 200 OK\n"
96 "connection: keep-alive\n"
97 "Chrome-Proxy: bypass=86400, bar=abc\n"
98 "Content-Length: 999\n",
99 true,
100 86400,
101 false,
102 },
103 { "HTTP/1.1 200 OK\n"
104 "connection: keep-alive\n"
105 "Chrome-Proxy: bypass=3600\n"
106 "Chrome-Proxy: bypass=86400\n"
107 "Content-Length: 999\n",
108 true,
109 3600,
110 false,
111 },
112 { "HTTP/1.1 200 OK\n"
113 "connection: keep-alive\n"
114 "Chrome-Proxy: bypass=3600, bypass=86400\n"
115 "Content-Length: 999\n",
116 true,
117 3600,
118 false,
119 },
120 { "HTTP/1.1 200 OK\n"
121 "connection: keep-alive\n"
122 "Chrome-Proxy: bypass=, bypass=86400\n"
123 "Content-Length: 999\n",
124 true,
125 86400,
126 false,
127 },
128 { "HTTP/1.1 200 OK\n"
129 "connection: keep-alive\n"
130 "Chrome-Proxy: bypass\n"
131 "Chrome-Proxy: bypass=86400\n"
132 "Content-Length: 999\n",
133 true,
134 86400,
135 false,
136 },
137 { "HTTP/1.1 200 OK\n"
138 "connection: keep-alive\n"
139 "Chrome-Proxy: block=, block=3600\n"
140 "Content-Length: 999\n",
141 true,
142 3600,
143 true,
144 },
145 { "HTTP/1.1 200 OK\n"
146 "connection: keep-alive\n"
147 "Chrome-Proxy: bypass=86400, block=3600\n"
148 "Content-Length: 999\n",
149 true,
150 3600,
151 true,
152 },
153 { "HTTP/1.1 200 OK\n"
154 "connection: proxy-bypass\n"
155 "Chrome-Proxy: block=, bypass=86400\n"
156 "Content-Length: 999\n",
157 true,
158 86400,
159 false,
160 },
161 { "HTTP/1.1 200 OK\n"
162 "connection: proxy-bypass\n"
163 "Chrome-Proxy: block=-1\n"
164 "Content-Length: 999\n",
165 false,
166 0,
167 false,
168 },
169 { "HTTP/1.1 200 OK\n"
170 "connection: proxy-bypass\n"
171 "Chrome-Proxy: block=99999999999999999999\n"
172 "Content-Length: 999\n",
173 false,
174 0,
175 false,
176 },
177 };
178 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
179 std::string headers(tests[i].headers);
180 HeadersToRaw(&headers);
181 scoped_refptr<net::HttpResponseHeaders> parsed(
182 new net::HttpResponseHeaders(headers));
183
184 DataReductionProxyInfo data_reduction_proxy_info;
185 EXPECT_EQ(tests[i].expected_result,
186 GetDataReductionProxyInfo(parsed, &data_reduction_proxy_info));
187 EXPECT_EQ(tests[i].expected_retry_delay,
188 data_reduction_proxy_info.bypass_duration.InSeconds());
189 EXPECT_EQ(tests[i].expected_bypass_all,
190 data_reduction_proxy_info.bypass_all);
191 }
192 }
193
TEST_F(DataReductionProxyHeadersTest,HasDataReductionProxyViaHeader)194 TEST_F(DataReductionProxyHeadersTest, HasDataReductionProxyViaHeader) {
195 const struct {
196 const char* headers;
197 bool expected_result;
198 } tests[] = {
199 { "HTTP/1.1 200 OK\n"
200 "Via: 1.1 Chrome-Proxy\n",
201 false,
202 },
203 { "HTTP/1.1 200 OK\n"
204 "Via: 1\n",
205 false,
206 },
207 { "HTTP/1.1 200 OK\n"
208 "Via: 1.1 Chrome-Compression-Proxy\n",
209 true,
210 },
211 { "HTTP/1.1 200 OK\n"
212 "Via: 1.0 Chrome-Compression-Proxy\n",
213 true,
214 },
215 { "HTTP/1.1 200 OK\n"
216 "Via: 1.1 Foo-Bar, 1.1 Chrome-Compression-Proxy\n",
217 true,
218 },
219 { "HTTP/1.1 200 OK\n"
220 "Via: 1.1 Chrome-Compression-Proxy, 1.1 Bar-Foo\n",
221 true,
222 },
223 { "HTTP/1.1 200 OK\n"
224 "Via: 1.1 chrome-compression-proxy\n",
225 false,
226 },
227 { "HTTP/1.1 200 OK\n"
228 "Via: 1.1 Foo-Bar\n"
229 "Via: 1.1 Chrome-Compression-Proxy\n",
230 true,
231 },
232 { "HTTP/1.1 200 OK\n"
233 "Via: 1.1 Chrome-Proxy\n",
234 false,
235 },
236 { "HTTP/1.1 200 OK\n"
237 "Via: 1.1 Chrome Compression Proxy\n",
238 true,
239 },
240 { "HTTP/1.1 200 OK\n"
241 "Via: 1.1 Foo-Bar, 1.1 Chrome Compression Proxy\n",
242 true,
243 },
244 { "HTTP/1.1 200 OK\n"
245 "Via: 1.1 Chrome Compression Proxy, 1.1 Bar-Foo\n",
246 true,
247 },
248 { "HTTP/1.1 200 OK\n"
249 "Via: 1.1 chrome compression proxy\n",
250 false,
251 },
252 { "HTTP/1.1 200 OK\n"
253 "Via: 1.1 Foo-Bar\n"
254 "Via: 1.1 Chrome Compression Proxy\n",
255 true,
256 },
257 };
258 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
259 std::string headers(tests[i].headers);
260 HeadersToRaw(&headers);
261 scoped_refptr<net::HttpResponseHeaders> parsed(
262 new net::HttpResponseHeaders(headers));
263
264 EXPECT_EQ(tests[i].expected_result,
265 HasDataReductionProxyViaHeader(parsed));
266 }
267 }
268
TEST_F(DataReductionProxyHeadersTest,GetDataReductionProxyBypassEventType)269 TEST_F(DataReductionProxyHeadersTest, GetDataReductionProxyBypassEventType) {
270 const struct {
271 const char* headers;
272 net::ProxyService::DataReductionProxyBypassEventType expected_result;
273 } tests[] = {
274 { "HTTP/1.1 200 OK\n"
275 "Chrome-Proxy: bypass=0\n"
276 "Via: 1.1 Chrome-Compression-Proxy\n",
277 net::ProxyService::SHORT_BYPASS,
278 },
279 { "HTTP/1.1 200 OK\n"
280 "Chrome-Proxy: bypass=1799\n"
281 "Via: 1.1 Chrome-Compression-Proxy\n",
282 net::ProxyService::SHORT_BYPASS,
283 },
284 { "HTTP/1.1 200 OK\n"
285 "Chrome-Proxy: bypass=1800\n"
286 "Via: 1.1 Chrome-Compression-Proxy\n",
287 net::ProxyService::LONG_BYPASS,
288 },
289 { "HTTP/1.1 500 Internal Server Error\n"
290 "Via: 1.1 Chrome-Compression-Proxy\n",
291 net::ProxyService::INTERNAL_SERVER_ERROR_BYPASS,
292 },
293 { "HTTP/1.1 501 Not Implemented\n"
294 "Via: 1.1 Chrome-Compression-Proxy\n",
295 net::ProxyService::BYPASS_EVENT_TYPE_MAX,
296 },
297 { "HTTP/1.1 502 Bad Gateway\n"
298 "Via: 1.1 Chrome-Compression-Proxy\n",
299 net::ProxyService::INTERNAL_SERVER_ERROR_BYPASS,
300 },
301 { "HTTP/1.1 503 Service Unavailable\n"
302 "Via: 1.1 Chrome-Compression-Proxy\n",
303 net::ProxyService::INTERNAL_SERVER_ERROR_BYPASS,
304 },
305 { "HTTP/1.1 504 Gateway Timeout\n"
306 "Via: 1.1 Chrome-Compression-Proxy\n",
307 net::ProxyService::BYPASS_EVENT_TYPE_MAX,
308 },
309 { "HTTP/1.1 505 HTTP Version Not Supported\n"
310 "Via: 1.1 Chrome-Compression-Proxy\n",
311 net::ProxyService::BYPASS_EVENT_TYPE_MAX,
312 },
313 { "HTTP/1.1 304 Not Modified\n",
314 net::ProxyService::BYPASS_EVENT_TYPE_MAX,
315 },
316 { "HTTP/1.1 200 OK\n",
317 net::ProxyService::MISSING_VIA_HEADER,
318 },
319 { "HTTP/1.1 200 OK\n"
320 "Chrome-Proxy: bypass=1799\n",
321 net::ProxyService::SHORT_BYPASS,
322 },
323 { "HTTP/1.1 502 Bad Gateway\n",
324 net::ProxyService::INTERNAL_SERVER_ERROR_BYPASS,
325 },
326 { "HTTP/1.1 502 Bad Gateway\n"
327 "Chrome-Proxy: bypass=1799\n",
328 net::ProxyService::SHORT_BYPASS,
329 },
330 { "HTTP/1.1 502 Bad Gateway\n"
331 "Chrome-Proxy: bypass=1799\n",
332 net::ProxyService::SHORT_BYPASS,
333 },
334 { "HTTP/1.1 414 Request-URI Too Long\n",
335 net::ProxyService::PROXY_4XX_BYPASS,
336 },
337 { "HTTP/1.1 414 Request-URI Too Long\n"
338 "Via: 1.1 Chrome-Compression-Proxy\n",
339 net::ProxyService::BYPASS_EVENT_TYPE_MAX,
340 },
341 { "HTTP/1.1 407 Proxy Authentication Required\n",
342 net::ProxyService::MALFORMED_407_BYPASS,
343 },
344 { "HTTP/1.1 407 Proxy Authentication Required\n"
345 "Proxy-Authenticate: Basic\n"
346 "Via: 1.1 Chrome-Compression-Proxy\n",
347 net::ProxyService::BYPASS_EVENT_TYPE_MAX,
348 }
349 };
350 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
351 std::string headers(tests[i].headers);
352 HeadersToRaw(&headers);
353 scoped_refptr<net::HttpResponseHeaders> parsed(
354 new net::HttpResponseHeaders(headers));
355 DataReductionProxyInfo chrome_proxy_info;
356 EXPECT_EQ(tests[i].expected_result,
357 GetDataReductionProxyBypassEventType(parsed, &chrome_proxy_info));
358 }
359 }
360 } // namespace data_reduction_proxy
361