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.
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "net/base/sdch_manager.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 //------------------------------------------------------------------------------
17 // Provide sample data and compression results with a sample VCDIFF dictionary.
18 // Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary.
19 static const char kTestVcdiffDictionary
[] = "DictionaryFor"
20 "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n";
22 //------------------------------------------------------------------------------
24 class SdchManagerTest
: public testing::Test
{
27 : sdch_manager_(new SdchManager
) {
30 SdchManager
* sdch_manager() { return sdch_manager_
.get(); }
32 // Reset globals back to default state.
33 virtual void TearDown() {
34 SdchManager::EnableSdchSupport(true);
35 SdchManager::EnableSecureSchemeSupport(false);
38 // Attempt to add a dictionary to the manager and probe for success or
40 bool AddSdchDictionary(const std::string
& dictionary_text
,
43 sdch_manager_
->GetAvailDictionaryList(gurl
, &list
);
44 sdch_manager_
->AddSdchDictionary(dictionary_text
, gurl
);
46 sdch_manager_
->GetAvailDictionaryList(gurl
, &list2
);
48 // The list of hashes should change iff the addition succeeds.
49 return (list
!= list2
);
53 scoped_ptr
<SdchManager
> sdch_manager_
;
56 //------------------------------------------------------------------------------
57 static std::string
NewSdchDictionary(const std::string
& domain
) {
58 std::string dictionary
;
59 if (!domain
.empty()) {
60 dictionary
.append("Domain: ");
61 dictionary
.append(domain
);
62 dictionary
.append("\n");
64 dictionary
.append("\n");
65 dictionary
.append(kTestVcdiffDictionary
, sizeof(kTestVcdiffDictionary
) - 1);
69 TEST_F(SdchManagerTest
, DomainSupported
) {
70 GURL
google_url("http://www.google.com");
72 SdchManager::EnableSdchSupport(false);
73 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(google_url
));
74 SdchManager::EnableSdchSupport(true);
75 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(google_url
));
78 TEST_F(SdchManagerTest
, DomainBlacklisting
) {
79 GURL
test_url("http://www.test.com");
80 GURL
google_url("http://www.google.com");
82 sdch_manager()->BlacklistDomain(test_url
, SdchManager::MIN_PROBLEM_CODE
);
83 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(test_url
));
84 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(google_url
));
86 sdch_manager()->BlacklistDomain(google_url
, SdchManager::MIN_PROBLEM_CODE
);
87 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(google_url
));
90 TEST_F(SdchManagerTest
, DomainBlacklistingCaseSensitivity
) {
91 GURL
test_url("http://www.TesT.com");
92 GURL
test2_url("http://www.tEst.com");
94 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(test_url
));
95 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(test2_url
));
96 sdch_manager()->BlacklistDomain(test_url
, SdchManager::MIN_PROBLEM_CODE
);
97 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(test2_url
));
100 TEST_F(SdchManagerTest
, BlacklistingReset
) {
101 GURL
gurl("http://mytest.DoMain.com");
102 std::string
domain(gurl
.host());
104 sdch_manager()->ClearBlacklistings();
105 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), 0);
106 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain
), 0);
107 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl
));
110 TEST_F(SdchManagerTest
, BlacklistingSingleBlacklist
) {
111 GURL
gurl("http://mytest.DoMain.com");
112 std::string
domain(gurl
.host());
113 sdch_manager()->ClearBlacklistings();
115 sdch_manager()->BlacklistDomain(gurl
, SdchManager::MIN_PROBLEM_CODE
);
116 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), 1);
117 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain
), 1);
119 // Check that any domain lookup reduces the blacklist counter.
120 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(gurl
));
121 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), 0);
122 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl
));
125 TEST_F(SdchManagerTest
, BlacklistingExponential
) {
126 GURL
gurl("http://mytest.DoMain.com");
127 std::string
domain(gurl
.host());
128 sdch_manager()->ClearBlacklistings();
131 for (int i
= 1; i
< 100; ++i
) {
132 sdch_manager()->BlacklistDomain(gurl
, SdchManager::MIN_PROBLEM_CODE
);
133 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain
), exponential
);
135 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), exponential
);
136 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(gurl
));
137 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), exponential
- 1);
139 // Simulate a large number of domain checks (which eventually remove the
141 sdch_manager()->ClearDomainBlacklisting(domain
);
142 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), 0);
143 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl
));
145 // Predict what exponential backoff will be.
146 exponential
= 1 + 2 * exponential
;
148 exponential
= INT_MAX
; // We don't wrap.
152 TEST_F(SdchManagerTest
, CanSetExactMatchDictionary
) {
153 std::string
dictionary_domain("x.y.z.google.com");
154 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
156 // Perfect match should work.
157 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
158 GURL("http://" + dictionary_domain
)));
161 TEST_F(SdchManagerTest
, CanAdvertiseDictionaryOverHTTP
) {
162 std::string
dictionary_domain("x.y.z.google.com");
163 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
165 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
166 GURL("http://" + dictionary_domain
)));
168 std::string dictionary_list
;
169 // HTTP target URL can advertise dictionary.
170 sdch_manager()->GetAvailDictionaryList(
171 GURL("http://" + dictionary_domain
+ "/test"),
173 EXPECT_FALSE(dictionary_list
.empty());
176 TEST_F(SdchManagerTest
, CanNotAdvertiseDictionaryOverHTTPS
) {
177 std::string
dictionary_domain("x.y.z.google.com");
178 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
180 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
181 GURL("http://" + dictionary_domain
)));
183 std::string dictionary_list
;
184 // HTTPS target URL should NOT advertise dictionary.
185 sdch_manager()->GetAvailDictionaryList(
186 GURL("https://" + dictionary_domain
+ "/test"),
188 EXPECT_TRUE(dictionary_list
.empty());
191 TEST_F(SdchManagerTest
, CanUseHTTPSDictionaryOverHTTPSIfEnabled
) {
192 std::string
dictionary_domain("x.y.z.google.com");
193 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
195 EXPECT_FALSE(AddSdchDictionary(dictionary_text
,
196 GURL("https://" + dictionary_domain
)));
197 SdchManager::EnableSecureSchemeSupport(true);
198 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
199 GURL("https://" + dictionary_domain
)));
201 GURL
target_url("https://" + dictionary_domain
+ "/test");
202 std::string dictionary_list
;
203 // HTTPS target URL should advertise dictionary if secure scheme support is
205 sdch_manager()->GetAvailDictionaryList(target_url
, &dictionary_list
);
206 EXPECT_FALSE(dictionary_list
.empty());
208 // Dictionary should be available.
209 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
210 std::string client_hash
;
211 std::string server_hash
;
212 sdch_manager()->GenerateHash(dictionary_text
, &client_hash
, &server_hash
);
213 sdch_manager()->GetVcdiffDictionary(server_hash
, target_url
, &dictionary
);
214 EXPECT_TRUE(dictionary
.get() != NULL
);
217 TEST_F(SdchManagerTest
, CanNotUseHTTPDictionaryOverHTTPS
) {
218 std::string
dictionary_domain("x.y.z.google.com");
219 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
221 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
222 GURL("http://" + dictionary_domain
)));
224 GURL
target_url("https://" + dictionary_domain
+ "/test");
225 std::string dictionary_list
;
226 // HTTPS target URL should not advertise dictionary acquired over HTTP even if
227 // secure scheme support is enabled.
228 SdchManager::EnableSecureSchemeSupport(true);
229 sdch_manager()->GetAvailDictionaryList(target_url
, &dictionary_list
);
230 EXPECT_TRUE(dictionary_list
.empty());
232 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
233 std::string client_hash
;
234 std::string server_hash
;
235 sdch_manager()->GenerateHash(dictionary_text
, &client_hash
, &server_hash
);
236 sdch_manager()->GetVcdiffDictionary(server_hash
, target_url
, &dictionary
);
237 EXPECT_TRUE(dictionary
.get() == NULL
);
240 TEST_F(SdchManagerTest
, CanNotUseHTTPSDictionaryOverHTTP
) {
241 std::string
dictionary_domain("x.y.z.google.com");
242 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
244 SdchManager::EnableSecureSchemeSupport(true);
245 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
246 GURL("https://" + dictionary_domain
)));
248 GURL
target_url("http://" + dictionary_domain
+ "/test");
249 std::string dictionary_list
;
250 // HTTP target URL should not advertise dictionary acquired over HTTPS even if
251 // secure scheme support is enabled.
252 sdch_manager()->GetAvailDictionaryList(target_url
, &dictionary_list
);
253 EXPECT_TRUE(dictionary_list
.empty());
255 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
256 std::string client_hash
;
257 std::string server_hash
;
258 sdch_manager()->GenerateHash(dictionary_text
, &client_hash
, &server_hash
);
259 sdch_manager()->GetVcdiffDictionary(server_hash
, target_url
, &dictionary
);
260 EXPECT_TRUE(dictionary
.get() == NULL
);
263 TEST_F(SdchManagerTest
, FailToSetDomainMismatchDictionary
) {
264 std::string
dictionary_domain("x.y.z.google.com");
265 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
267 // Fail the "domain match" requirement.
268 EXPECT_FALSE(AddSdchDictionary(dictionary_text
,
269 GURL("http://y.z.google.com")));
272 TEST_F(SdchManagerTest
, FailToSetDotHostPrefixDomainDictionary
) {
273 std::string
dictionary_domain("x.y.z.google.com");
274 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
276 // Fail the HD with D being the domain and H having a dot requirement.
277 EXPECT_FALSE(AddSdchDictionary(dictionary_text
,
278 GURL("http://w.x.y.z.google.com")));
281 TEST_F(SdchManagerTest
, FailToSetRepeatPrefixWithDotDictionary
) {
282 // Make sure that a prefix that matches the domain postfix won't confuse
283 // the validation checks.
284 std::string
dictionary_domain("www.google.com");
285 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
287 // Fail the HD with D being the domain and H having a dot requirement.
288 EXPECT_FALSE(AddSdchDictionary(dictionary_text
,
289 GURL("http://www.google.com.www.google.com")));
292 TEST_F(SdchManagerTest
, CanSetLeadingDotDomainDictionary
) {
293 // Make sure that a prefix that matches the domain postfix won't confuse
294 // the validation checks.
295 std::string
dictionary_domain(".google.com");
296 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
298 // Verify that a leading dot in the domain is acceptable, as long as the host
299 // name does not contain any dots preceding the matched domain name.
300 EXPECT_TRUE(AddSdchDictionary(dictionary_text
, GURL("http://www.google.com")));
303 // Make sure the order of the tests is not helping us or confusing things.
304 // See test CanSetExactMatchDictionary above for first try.
305 TEST_F(SdchManagerTest
, CanStillSetExactMatchDictionary
) {
306 std::string
dictionary_domain("x.y.z.google.com");
307 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
309 // Perfect match should *STILL* work.
310 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
311 GURL("http://" + dictionary_domain
)));
314 // Make sure the DOS protection precludes the addition of too many dictionaries.
315 TEST_F(SdchManagerTest
, TooManyDictionaries
) {
316 std::string
dictionary_domain(".google.com");
317 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
319 for (size_t count
= 0; count
< SdchManager::kMaxDictionaryCount
; ++count
) {
320 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
321 GURL("http://www.google.com")));
322 dictionary_text
+= " "; // Create dictionary with different SHA signature.
325 AddSdchDictionary(dictionary_text
, GURL("http://www.google.com")));
328 TEST_F(SdchManagerTest
, DictionaryNotTooLarge
) {
329 std::string
dictionary_domain(".google.com");
330 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
332 dictionary_text
.append(
333 SdchManager::kMaxDictionarySize
- dictionary_text
.size(), ' ');
334 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
335 GURL("http://" + dictionary_domain
)));
338 TEST_F(SdchManagerTest
, DictionaryTooLarge
) {
339 std::string
dictionary_domain(".google.com");
340 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
342 dictionary_text
.append(
343 SdchManager::kMaxDictionarySize
+ 1 - dictionary_text
.size(), ' ');
344 EXPECT_FALSE(AddSdchDictionary(dictionary_text
,
345 GURL("http://" + dictionary_domain
)));
348 TEST_F(SdchManagerTest
, PathMatch
) {
349 bool (*PathMatch
)(const std::string
& path
, const std::string
& restriction
) =
350 SdchManager::Dictionary::PathMatch
;
351 // Perfect match is supported.
352 EXPECT_TRUE(PathMatch("/search", "/search"));
353 EXPECT_TRUE(PathMatch("/search/", "/search/"));
355 // Prefix only works if last character of restriction is a slash, or first
356 // character in path after a match is a slash. Validate each case separately.
358 // Rely on the slash in the path (not at the end of the restriction).
359 EXPECT_TRUE(PathMatch("/search/something", "/search"));
360 EXPECT_TRUE(PathMatch("/search/s", "/search"));
361 EXPECT_TRUE(PathMatch("/search/other", "/search"));
362 EXPECT_TRUE(PathMatch("/search/something", "/search"));
364 // Rely on the slash at the end of the restriction.
365 EXPECT_TRUE(PathMatch("/search/something", "/search/"));
366 EXPECT_TRUE(PathMatch("/search/s", "/search/"));
367 EXPECT_TRUE(PathMatch("/search/other", "/search/"));
368 EXPECT_TRUE(PathMatch("/search/something", "/search/"));
370 // Make sure less that sufficient prefix match is false.
371 EXPECT_FALSE(PathMatch("/sear", "/search"));
372 EXPECT_FALSE(PathMatch("/", "/search"));
373 EXPECT_FALSE(PathMatch(std::string(), "/search"));
375 // Add examples with several levels of direcories in the restriction.
376 EXPECT_FALSE(PathMatch("/search/something", "search/s"));
377 EXPECT_FALSE(PathMatch("/search/", "/search/s"));
379 // Make sure adding characters to path will also fail.
380 EXPECT_FALSE(PathMatch("/searching", "/search/"));
381 EXPECT_FALSE(PathMatch("/searching", "/search"));
383 // Make sure we're case sensitive.
384 EXPECT_FALSE(PathMatch("/ABC", "/abc"));
385 EXPECT_FALSE(PathMatch("/abc", "/ABC"));
388 // The following are only applicable while we have a latency test in the code,
389 // and can be removed when that functionality is stripped.
390 TEST_F(SdchManagerTest
, LatencyTestControls
) {
391 GURL
url("http://www.google.com");
392 GURL
url2("http://www.google2.com");
394 // First make sure we default to false.
395 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url
));
396 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2
));
398 // That we can set each to true.
399 sdch_manager()->SetAllowLatencyExperiment(url
, true);
400 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url
));
401 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2
));
403 sdch_manager()->SetAllowLatencyExperiment(url2
, true);
404 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url
));
405 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url2
));
407 // And can reset them to false.
408 sdch_manager()->SetAllowLatencyExperiment(url
, false);
409 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url
));
410 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url2
));
412 sdch_manager()->SetAllowLatencyExperiment(url2
, false);
413 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url
));
414 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2
));
417 TEST_F(SdchManagerTest
, CanUseMultipleManagers
) {
418 SdchManager second_manager
;
420 std::string
dictionary_domain_1("x.y.z.google.com");
421 std::string
dictionary_domain_2("x.y.z.chromium.org");
423 std::string
dictionary_text_1(NewSdchDictionary(dictionary_domain_1
));
424 std::string
dictionary_text_2(NewSdchDictionary(dictionary_domain_2
));
426 std::string tmp_hash
;
427 std::string server_hash_1
;
428 std::string server_hash_2
;
430 SdchManager::GenerateHash(dictionary_text_1
, &tmp_hash
, &server_hash_1
);
431 SdchManager::GenerateHash(dictionary_text_2
, &tmp_hash
, &server_hash_2
);
433 // Confirm that if you add directories to one manager, you
434 // can't get them from the other.
435 EXPECT_TRUE(AddSdchDictionary(dictionary_text_1
,
436 GURL("http://" + dictionary_domain_1
)));
437 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
438 sdch_manager()->GetVcdiffDictionary(
440 GURL("http://" + dictionary_domain_1
+ "/random_url"),
442 EXPECT_TRUE(dictionary
.get());
444 second_manager
.AddSdchDictionary(
445 dictionary_text_2
, GURL("http://" + dictionary_domain_2
));
446 second_manager
.GetVcdiffDictionary(
448 GURL("http://" + dictionary_domain_2
+ "/random_url"),
450 EXPECT_TRUE(dictionary
.get());
452 sdch_manager()->GetVcdiffDictionary(
454 GURL("http://" + dictionary_domain_2
+ "/random_url"),
456 EXPECT_FALSE(dictionary
.get());
458 second_manager
.GetVcdiffDictionary(
460 GURL("http://" + dictionary_domain_1
+ "/random_url"),
462 EXPECT_FALSE(dictionary
.get());
465 TEST_F(SdchManagerTest
, HttpsCorrectlySupported
) {
466 GURL
url("http://www.google.com");
467 GURL
secure_url("https://www.google.com");
469 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(url
));
470 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(secure_url
));
472 SdchManager::EnableSecureSchemeSupport(true);
473 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(url
));
474 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(secure_url
));
477 TEST_F(SdchManagerTest
, ClearDictionaryData
) {
478 std::string
dictionary_domain("x.y.z.google.com");
479 GURL
blacklist_url("http://bad.chromium.org");
481 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
482 std::string tmp_hash
;
483 std::string server_hash
;
485 SdchManager::GenerateHash(dictionary_text
, &tmp_hash
, &server_hash
);
487 EXPECT_TRUE(AddSdchDictionary(dictionary_text
,
488 GURL("http://" + dictionary_domain
)));
489 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
490 sdch_manager()->GetVcdiffDictionary(
492 GURL("http://" + dictionary_domain
+ "/random_url"),
494 EXPECT_TRUE(dictionary
.get());
496 sdch_manager()->BlacklistDomain(GURL(blacklist_url
),
497 SdchManager::MIN_PROBLEM_CODE
);
498 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(blacklist_url
));
500 sdch_manager()->ClearData();
503 sdch_manager()->GetVcdiffDictionary(
505 GURL("http://" + dictionary_domain
+ "/random_url"),
507 EXPECT_FALSE(dictionary
.get());
508 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(blacklist_url
));