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);
39 scoped_ptr
<SdchManager
> sdch_manager_
;
42 //------------------------------------------------------------------------------
43 static std::string
NewSdchDictionary(const std::string
& domain
) {
44 std::string dictionary
;
45 if (!domain
.empty()) {
46 dictionary
.append("Domain: ");
47 dictionary
.append(domain
);
48 dictionary
.append("\n");
50 dictionary
.append("\n");
51 dictionary
.append(kTestVcdiffDictionary
, sizeof(kTestVcdiffDictionary
) - 1);
55 TEST_F(SdchManagerTest
, DomainSupported
) {
56 GURL
google_url("http://www.google.com");
58 SdchManager::EnableSdchSupport(false);
59 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(google_url
));
60 SdchManager::EnableSdchSupport(true);
61 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(google_url
));
64 TEST_F(SdchManagerTest
, DomainBlacklisting
) {
65 GURL
test_url("http://www.test.com");
66 GURL
google_url("http://www.google.com");
68 sdch_manager()->BlacklistDomain(test_url
, SdchManager::MIN_PROBLEM_CODE
);
69 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(test_url
));
70 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(google_url
));
72 sdch_manager()->BlacklistDomain(google_url
, SdchManager::MIN_PROBLEM_CODE
);
73 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(google_url
));
76 TEST_F(SdchManagerTest
, DomainBlacklistingCaseSensitivity
) {
77 GURL
test_url("http://www.TesT.com");
78 GURL
test2_url("http://www.tEst.com");
80 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(test_url
));
81 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(test2_url
));
82 sdch_manager()->BlacklistDomain(test_url
, SdchManager::MIN_PROBLEM_CODE
);
83 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(test2_url
));
86 TEST_F(SdchManagerTest
, BlacklistingReset
) {
87 GURL
gurl("http://mytest.DoMain.com");
88 std::string
domain(gurl
.host());
90 sdch_manager()->ClearBlacklistings();
91 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), 0);
92 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain
), 0);
93 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl
));
96 TEST_F(SdchManagerTest
, BlacklistingSingleBlacklist
) {
97 GURL
gurl("http://mytest.DoMain.com");
98 std::string
domain(gurl
.host());
99 sdch_manager()->ClearBlacklistings();
101 sdch_manager()->BlacklistDomain(gurl
, SdchManager::MIN_PROBLEM_CODE
);
102 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), 1);
103 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain
), 1);
105 // Check that any domain lookup reduces the blacklist counter.
106 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(gurl
));
107 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), 0);
108 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl
));
111 TEST_F(SdchManagerTest
, BlacklistingExponential
) {
112 GURL
gurl("http://mytest.DoMain.com");
113 std::string
domain(gurl
.host());
114 sdch_manager()->ClearBlacklistings();
117 for (int i
= 1; i
< 100; ++i
) {
118 sdch_manager()->BlacklistDomain(gurl
, SdchManager::MIN_PROBLEM_CODE
);
119 EXPECT_EQ(sdch_manager()->BlacklistDomainExponential(domain
), exponential
);
121 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), exponential
);
122 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(gurl
));
123 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), exponential
- 1);
125 // Simulate a large number of domain checks (which eventually remove the
127 sdch_manager()->ClearDomainBlacklisting(domain
);
128 EXPECT_EQ(sdch_manager()->BlackListDomainCount(domain
), 0);
129 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(gurl
));
131 // Predict what exponential backoff will be.
132 exponential
= 1 + 2 * exponential
;
134 exponential
= INT_MAX
; // We don't wrap.
138 TEST_F(SdchManagerTest
, CanSetExactMatchDictionary
) {
139 std::string
dictionary_domain("x.y.z.google.com");
140 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
142 // Perfect match should work.
143 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text
,
144 GURL("http://" + dictionary_domain
)));
147 TEST_F(SdchManagerTest
, CanAdvertiseDictionaryOverHTTP
) {
148 std::string
dictionary_domain("x.y.z.google.com");
149 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
151 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text
,
152 GURL("http://" + dictionary_domain
)));
154 std::string dictionary_list
;
155 // HTTP target URL can advertise dictionary.
156 sdch_manager()->GetAvailDictionaryList(
157 GURL("http://" + dictionary_domain
+ "/test"),
159 EXPECT_FALSE(dictionary_list
.empty());
162 TEST_F(SdchManagerTest
, CanNotAdvertiseDictionaryOverHTTPS
) {
163 std::string
dictionary_domain("x.y.z.google.com");
164 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
166 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text
,
167 GURL("http://" + dictionary_domain
)));
169 std::string dictionary_list
;
170 // HTTPS target URL should NOT advertise dictionary.
171 sdch_manager()->GetAvailDictionaryList(
172 GURL("https://" + dictionary_domain
+ "/test"),
174 EXPECT_TRUE(dictionary_list
.empty());
177 TEST_F(SdchManagerTest
, CanUseHTTPSDictionaryOverHTTPSIfEnabled
) {
178 std::string
dictionary_domain("x.y.z.google.com");
179 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
181 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(
182 dictionary_text
, GURL("https://" + dictionary_domain
)));
183 SdchManager::EnableSecureSchemeSupport(true);
184 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(
185 dictionary_text
, GURL("https://" + dictionary_domain
)));
187 GURL
target_url("https://" + dictionary_domain
+ "/test");
188 std::string dictionary_list
;
189 // HTTPS target URL should advertise dictionary if secure scheme support is
191 sdch_manager()->GetAvailDictionaryList(target_url
, &dictionary_list
);
192 EXPECT_FALSE(dictionary_list
.empty());
194 // Dictionary should be available.
195 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
196 std::string client_hash
;
197 std::string server_hash
;
198 sdch_manager()->GenerateHash(dictionary_text
, &client_hash
, &server_hash
);
199 sdch_manager()->GetVcdiffDictionary(server_hash
, target_url
, &dictionary
);
200 EXPECT_TRUE(dictionary
.get() != NULL
);
203 TEST_F(SdchManagerTest
, CanNotUseHTTPDictionaryOverHTTPS
) {
204 std::string
dictionary_domain("x.y.z.google.com");
205 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
207 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text
,
208 GURL("http://" + dictionary_domain
)));
210 GURL
target_url("https://" + dictionary_domain
+ "/test");
211 std::string dictionary_list
;
212 // HTTPS target URL should not advertise dictionary acquired over HTTP even if
213 // secure scheme support is enabled.
214 SdchManager::EnableSecureSchemeSupport(true);
215 sdch_manager()->GetAvailDictionaryList(target_url
, &dictionary_list
);
216 EXPECT_TRUE(dictionary_list
.empty());
218 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
219 std::string client_hash
;
220 std::string server_hash
;
221 sdch_manager()->GenerateHash(dictionary_text
, &client_hash
, &server_hash
);
222 sdch_manager()->GetVcdiffDictionary(server_hash
, target_url
, &dictionary
);
223 EXPECT_TRUE(dictionary
.get() == NULL
);
226 TEST_F(SdchManagerTest
, CanNotUseHTTPSDictionaryOverHTTP
) {
227 std::string
dictionary_domain("x.y.z.google.com");
228 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
230 SdchManager::EnableSecureSchemeSupport(true);
231 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text
,
232 GURL("https://" + dictionary_domain
)));
234 GURL
target_url("http://" + dictionary_domain
+ "/test");
235 std::string dictionary_list
;
236 // HTTP target URL should not advertise dictionary acquired over HTTPS even if
237 // secure scheme support is enabled.
238 sdch_manager()->GetAvailDictionaryList(target_url
, &dictionary_list
);
239 EXPECT_TRUE(dictionary_list
.empty());
241 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
242 std::string client_hash
;
243 std::string server_hash
;
244 sdch_manager()->GenerateHash(dictionary_text
, &client_hash
, &server_hash
);
245 sdch_manager()->GetVcdiffDictionary(server_hash
, target_url
, &dictionary
);
246 EXPECT_TRUE(dictionary
.get() == NULL
);
249 TEST_F(SdchManagerTest
, FailToSetDomainMismatchDictionary
) {
250 std::string
dictionary_domain("x.y.z.google.com");
251 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
253 // Fail the "domain match" requirement.
254 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text
,
255 GURL("http://y.z.google.com")));
258 TEST_F(SdchManagerTest
, FailToSetDotHostPrefixDomainDictionary
) {
259 std::string
dictionary_domain("x.y.z.google.com");
260 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
262 // Fail the HD with D being the domain and H having a dot requirement.
263 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text
,
264 GURL("http://w.x.y.z.google.com")));
267 TEST_F(SdchManagerTest
, FailToSetRepeatPrefixWithDotDictionary
) {
268 // Make sure that a prefix that matches the domain postfix won't confuse
269 // the validation checks.
270 std::string
dictionary_domain("www.google.com");
271 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
273 // Fail the HD with D being the domain and H having a dot requirement.
274 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text
,
275 GURL("http://www.google.com.www.google.com")));
278 TEST_F(SdchManagerTest
, CanSetLeadingDotDomainDictionary
) {
279 // Make sure that a prefix that matches the domain postfix won't confuse
280 // the validation checks.
281 std::string
dictionary_domain(".google.com");
282 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
284 // Verify that a leading dot in the domain is acceptable, as long as the host
285 // name does not contain any dots preceding the matched domain name.
286 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text
,
287 GURL("http://www.google.com")));
290 // Make sure the order of the tests is not helping us or confusing things.
291 // See test CanSetExactMatchDictionary above for first try.
292 TEST_F(SdchManagerTest
, CanStillSetExactMatchDictionary
) {
293 std::string
dictionary_domain("x.y.z.google.com");
294 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
296 // Perfect match should *STILL* work.
297 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text
,
298 GURL("http://" + dictionary_domain
)));
301 // Make sure the DOS protection precludes the addition of too many dictionaries.
302 TEST_F(SdchManagerTest
, TooManyDictionaries
) {
303 std::string
dictionary_domain(".google.com");
304 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
307 while (count
<= SdchManager::kMaxDictionaryCount
+ 1) {
308 if (!sdch_manager()->AddSdchDictionary(dictionary_text
,
309 GURL("http://www.google.com")))
312 dictionary_text
+= " "; // Create dictionary with different SHA signature.
315 EXPECT_EQ(SdchManager::kMaxDictionaryCount
, count
);
318 TEST_F(SdchManagerTest
, DictionaryNotTooLarge
) {
319 std::string
dictionary_domain(".google.com");
320 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
322 dictionary_text
.append(
323 SdchManager::kMaxDictionarySize
- dictionary_text
.size(), ' ');
324 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(dictionary_text
,
325 GURL("http://" + dictionary_domain
)));
328 TEST_F(SdchManagerTest
, DictionaryTooLarge
) {
329 std::string
dictionary_domain(".google.com");
330 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
332 dictionary_text
.append(
333 SdchManager::kMaxDictionarySize
+ 1 - dictionary_text
.size(), ' ');
334 EXPECT_FALSE(sdch_manager()->AddSdchDictionary(dictionary_text
,
335 GURL("http://" + dictionary_domain
)));
338 TEST_F(SdchManagerTest
, PathMatch
) {
339 bool (*PathMatch
)(const std::string
& path
, const std::string
& restriction
) =
340 SdchManager::Dictionary::PathMatch
;
341 // Perfect match is supported.
342 EXPECT_TRUE(PathMatch("/search", "/search"));
343 EXPECT_TRUE(PathMatch("/search/", "/search/"));
345 // Prefix only works if last character of restriction is a slash, or first
346 // character in path after a match is a slash. Validate each case separately.
348 // Rely on the slash in the path (not at the end of the restriction).
349 EXPECT_TRUE(PathMatch("/search/something", "/search"));
350 EXPECT_TRUE(PathMatch("/search/s", "/search"));
351 EXPECT_TRUE(PathMatch("/search/other", "/search"));
352 EXPECT_TRUE(PathMatch("/search/something", "/search"));
354 // Rely on the slash at the end of the restriction.
355 EXPECT_TRUE(PathMatch("/search/something", "/search/"));
356 EXPECT_TRUE(PathMatch("/search/s", "/search/"));
357 EXPECT_TRUE(PathMatch("/search/other", "/search/"));
358 EXPECT_TRUE(PathMatch("/search/something", "/search/"));
360 // Make sure less that sufficient prefix match is false.
361 EXPECT_FALSE(PathMatch("/sear", "/search"));
362 EXPECT_FALSE(PathMatch("/", "/search"));
363 EXPECT_FALSE(PathMatch(std::string(), "/search"));
365 // Add examples with several levels of direcories in the restriction.
366 EXPECT_FALSE(PathMatch("/search/something", "search/s"));
367 EXPECT_FALSE(PathMatch("/search/", "/search/s"));
369 // Make sure adding characters to path will also fail.
370 EXPECT_FALSE(PathMatch("/searching", "/search/"));
371 EXPECT_FALSE(PathMatch("/searching", "/search"));
373 // Make sure we're case sensitive.
374 EXPECT_FALSE(PathMatch("/ABC", "/abc"));
375 EXPECT_FALSE(PathMatch("/abc", "/ABC"));
378 // The following are only applicable while we have a latency test in the code,
379 // and can be removed when that functionality is stripped.
380 TEST_F(SdchManagerTest
, LatencyTestControls
) {
381 GURL
url("http://www.google.com");
382 GURL
url2("http://www.google2.com");
384 // First make sure we default to false.
385 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url
));
386 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2
));
388 // That we can set each to true.
389 sdch_manager()->SetAllowLatencyExperiment(url
, true);
390 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url
));
391 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2
));
393 sdch_manager()->SetAllowLatencyExperiment(url2
, true);
394 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url
));
395 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url2
));
397 // And can reset them to false.
398 sdch_manager()->SetAllowLatencyExperiment(url
, false);
399 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url
));
400 EXPECT_TRUE(sdch_manager()->AllowLatencyExperiment(url2
));
402 sdch_manager()->SetAllowLatencyExperiment(url2
, false);
403 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url
));
404 EXPECT_FALSE(sdch_manager()->AllowLatencyExperiment(url2
));
407 TEST_F(SdchManagerTest
, CanUseMultipleManagers
) {
408 SdchManager second_manager
;
410 std::string
dictionary_domain_1("x.y.z.google.com");
411 std::string
dictionary_domain_2("x.y.z.chromium.org");
413 std::string
dictionary_text_1(NewSdchDictionary(dictionary_domain_1
));
414 std::string
dictionary_text_2(NewSdchDictionary(dictionary_domain_2
));
416 std::string tmp_hash
;
417 std::string server_hash_1
;
418 std::string server_hash_2
;
420 SdchManager::GenerateHash(dictionary_text_1
, &tmp_hash
, &server_hash_1
);
421 SdchManager::GenerateHash(dictionary_text_2
, &tmp_hash
, &server_hash_2
);
423 // Confirm that if you add directories to one manager, you
424 // can't get them from the other.
425 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(
426 dictionary_text_1
, GURL("http://" + dictionary_domain_1
)));
427 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
428 sdch_manager()->GetVcdiffDictionary(
430 GURL("http://" + dictionary_domain_1
+ "/random_url"),
432 EXPECT_TRUE(dictionary
.get());
434 EXPECT_TRUE(second_manager
.AddSdchDictionary(
435 dictionary_text_2
, GURL("http://" + dictionary_domain_2
)));
436 second_manager
.GetVcdiffDictionary(
438 GURL("http://" + dictionary_domain_2
+ "/random_url"),
440 EXPECT_TRUE(dictionary
.get());
442 sdch_manager()->GetVcdiffDictionary(
444 GURL("http://" + dictionary_domain_2
+ "/random_url"),
446 EXPECT_FALSE(dictionary
.get());
448 second_manager
.GetVcdiffDictionary(
450 GURL("http://" + dictionary_domain_1
+ "/random_url"),
452 EXPECT_FALSE(dictionary
.get());
455 TEST_F(SdchManagerTest
, HttpsCorrectlySupported
) {
456 GURL
url("http://www.google.com");
457 GURL
secure_url("https://www.google.com");
459 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(url
));
460 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(secure_url
));
462 SdchManager::EnableSecureSchemeSupport(true);
463 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(url
));
464 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(secure_url
));
467 TEST_F(SdchManagerTest
, ClearDictionaryData
) {
468 std::string
dictionary_domain("x.y.z.google.com");
469 GURL
blacklist_url("http://bad.chromium.org");
471 std::string
dictionary_text(NewSdchDictionary(dictionary_domain
));
472 std::string tmp_hash
;
473 std::string server_hash
;
475 SdchManager::GenerateHash(dictionary_text
, &tmp_hash
, &server_hash
);
477 EXPECT_TRUE(sdch_manager()->AddSdchDictionary(
478 dictionary_text
, GURL("http://" + dictionary_domain
)));
479 scoped_refptr
<SdchManager::Dictionary
> dictionary
;
480 sdch_manager()->GetVcdiffDictionary(
482 GURL("http://" + dictionary_domain
+ "/random_url"),
484 EXPECT_TRUE(dictionary
.get());
486 sdch_manager()->BlacklistDomain(GURL(blacklist_url
),
487 SdchManager::MIN_PROBLEM_CODE
);
488 EXPECT_FALSE(sdch_manager()->IsInSupportedDomain(blacklist_url
));
490 sdch_manager()->ClearData();
493 sdch_manager()->GetVcdiffDictionary(
495 GURL("http://" + dictionary_domain
+ "/random_url"),
497 EXPECT_FALSE(dictionary
.get());
498 EXPECT_TRUE(sdch_manager()->IsInSupportedDomain(blacklist_url
));