diff options
Diffstat (limited to 'chromium/net/base/sdch_filter_unittest.cc')
-rw-r--r-- | chromium/net/base/sdch_filter_unittest.cc | 1393 |
1 files changed, 0 insertions, 1393 deletions
diff --git a/chromium/net/base/sdch_filter_unittest.cc b/chromium/net/base/sdch_filter_unittest.cc deleted file mode 100644 index 1cc70cb58be..00000000000 --- a/chromium/net/base/sdch_filter_unittest.cc +++ /dev/null @@ -1,1393 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <limits.h> - -#include <algorithm> -#include <string> -#include <vector> - -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "net/base/filter.h" -#include "net/base/io_buffer.h" -#include "net/base/mock_filter_context.h" -#include "net/base/sdch_filter.h" -#include "net/url_request/url_request_http_job.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/zlib/zlib.h" - -namespace net { - -//------------------------------------------------------------------------------ -// Provide sample data and compression results with a sample VCDIFF dictionary. -// Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary. -static const char kTestVcdiffDictionary[] = "DictionaryFor" - "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n"; -// Pre-compression test data. Note that we pad with a lot of highly gzip -// compressible content to help to exercise the chaining pipeline. That is why -// there are a PILE of zeros at the start and end. -// This will ensure that gzip compressed data can be fed to the chain in one -// gulp, but (with careful selection of intermediate buffers) that it takes -// several sdch buffers worth of data to satisfy the sdch filter. See detailed -// CHECK() calls in FilterChaining test for specifics. -static const char kTestData[] = "0000000000000000000000000000000000000000000000" - "0000000000000000000000000000TestData " - "SdchCompression1SdchCompression2SdchCompression3SdchCompression" - "00000000000000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000\n"; - -// Note SDCH compressed data will include a reference to the SDCH dictionary. -static const char kSdchCompressedTestData[] = - "\326\303\304\0\0\001M\0\201S\202\004\0\201E\006\001" - "00000000000000000000000000000000000000000000000000000000000000000000000000" - "TestData 00000000000000000000000000000000000000000000000000000000000000000" - "000000000000000000000000000000000000000000000000\n\001S\023\077\001r\r"; - -//------------------------------------------------------------------------------ - -class SdchFilterTest : public testing::Test { - protected: - SdchFilterTest() - : test_vcdiff_dictionary_(kTestVcdiffDictionary, - sizeof(kTestVcdiffDictionary) - 1), - vcdiff_compressed_data_(kSdchCompressedTestData, - sizeof(kSdchCompressedTestData) - 1), - expanded_(kTestData, sizeof(kTestData) - 1), - sdch_manager_(new SdchManager) { - } - - std::string NewSdchCompressedData(const std::string dictionary); - - const std::string test_vcdiff_dictionary_; - const std::string vcdiff_compressed_data_; - const std::string expanded_; // Desired final, decompressed data. - - scoped_ptr<SdchManager> sdch_manager_; // A singleton database. -}; - -std::string SdchFilterTest::NewSdchCompressedData( - const std::string dictionary) { - std::string client_hash; - std::string server_hash; - SdchManager::GenerateHash(dictionary, &client_hash, &server_hash); - - // Build compressed data that refers to our dictionary. - std::string compressed(server_hash); - compressed.append("\0", 1); - compressed.append(vcdiff_compressed_data_); - return compressed; -} - -//------------------------------------------------------------------------------ - - -TEST_F(SdchFilterTest, Hashing) { - std::string client_hash, server_hash; - std::string dictionary("test contents"); - SdchManager::GenerateHash(dictionary, &client_hash, &server_hash); - - EXPECT_EQ(client_hash, "lMQBjS3P"); - EXPECT_EQ(server_hash, "MyciMVll"); -} - - -//------------------------------------------------------------------------------ -// Provide a generic helper function for trying to filter data. -// This function repeatedly calls the filter to process data, until the entire -// source is consumed. The return value from the filter is appended to output. -// This allows us to vary input and output block sizes in order to test for edge -// effects (boundary effects?) during the filtering process. -// This function provides data to the filter in blocks of no-more-than the -// specified input_block_length. It allows the filter to fill no more than -// output_buffer_length in any one call to proccess (a.k.a., Read) data, and -// concatenates all these little output blocks into the singular output string. -static bool FilterTestData(const std::string& source, - size_t input_block_length, - const size_t output_buffer_length, - Filter* filter, std::string* output) { - CHECK_GT(input_block_length, 0u); - Filter::FilterStatus status(Filter::FILTER_NEED_MORE_DATA); - size_t source_index = 0; - scoped_ptr<char[]> output_buffer(new char[output_buffer_length]); - size_t input_amount = std::min(input_block_length, - static_cast<size_t>(filter->stream_buffer_size())); - - do { - int copy_amount = std::min(input_amount, source.size() - source_index); - if (copy_amount > 0 && status == Filter::FILTER_NEED_MORE_DATA) { - memcpy(filter->stream_buffer()->data(), source.data() + source_index, - copy_amount); - filter->FlushStreamBuffer(copy_amount); - source_index += copy_amount; - } - int buffer_length = output_buffer_length; - status = filter->ReadData(output_buffer.get(), &buffer_length); - output->append(output_buffer.get(), buffer_length); - if (status == Filter::FILTER_ERROR) - return false; - // Callers assume that FILTER_OK with no output buffer means FILTER_DONE. - if (Filter::FILTER_OK == status && 0 == buffer_length) - return true; - if (copy_amount == 0 && buffer_length == 0) - return true; - } while (1); -} -//------------------------------------------------------------------------------ -static std::string NewSdchDictionary(const std::string& domain) { - std::string dictionary; - if (!domain.empty()) { - dictionary.append("Domain: "); - dictionary.append(domain); - dictionary.append("\n"); - } - dictionary.append("\n"); - dictionary.append(kTestVcdiffDictionary, sizeof(kTestVcdiffDictionary) - 1); - return dictionary; -} - -//------------------------------------------------------------------------------ - -TEST_F(SdchFilterTest, EmptyInputOk) { - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - char output_buffer[20]; - MockFilterContext filter_context; - std::string url_string("http://ignore.com"); - filter_context.SetURL(GURL(url_string)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - - // With no input data, try to read output. - int output_bytes_or_buffer_size = sizeof(output_buffer); - Filter::FilterStatus status = filter->ReadData(output_buffer, - &output_bytes_or_buffer_size); - - EXPECT_EQ(0, output_bytes_or_buffer_size); - EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); -} - -TEST_F(SdchFilterTest, PassThroughWhenTentative) { - std::vector<Filter::FilterType> filter_types; - // Selective a tentative filter (which can fall back to pass through). - filter_types.push_back(Filter::FILTER_TYPE_GZIP_HELPING_SDCH); - char output_buffer[20]; - MockFilterContext filter_context; - // Response code needs to be 200 to allow a pass through. - filter_context.SetResponseCode(200); - std::string url_string("http://ignore.com"); - filter_context.SetURL(GURL(url_string)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - // Supply enough data to force a pass-through mode.. - std::string non_gzip_content("not GZIPed data"); - - char* input_buffer = filter->stream_buffer()->data(); - int input_buffer_size = filter->stream_buffer_size(); - - EXPECT_LT(static_cast<int>(non_gzip_content.size()), - input_buffer_size); - memcpy(input_buffer, non_gzip_content.data(), - non_gzip_content.size()); - filter->FlushStreamBuffer(non_gzip_content.size()); - - // Try to read output. - int output_bytes_or_buffer_size = sizeof(output_buffer); - Filter::FilterStatus status = filter->ReadData(output_buffer, - &output_bytes_or_buffer_size); - - EXPECT_EQ(non_gzip_content.size(), - static_cast<size_t>(output_bytes_or_buffer_size)); - ASSERT_GT(sizeof(output_buffer), - static_cast<size_t>(output_bytes_or_buffer_size)); - output_buffer[output_bytes_or_buffer_size] = '\0'; - EXPECT_TRUE(non_gzip_content == output_buffer); - EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); -} - -TEST_F(SdchFilterTest, RefreshBadReturnCode) { - std::vector<Filter::FilterType> filter_types; - // Selective a tentative filter (which can fall back to pass through). - filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); - char output_buffer[20]; - MockFilterContext filter_context; - // Response code needs to be 200 to allow a pass through. - filter_context.SetResponseCode(403); - // Meta refresh will only appear for html content - filter_context.SetMimeType("text/html"); - std::string url_string("http://ignore.com"); - filter_context.SetURL(GURL(url_string)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - // Supply enough data to force a pass-through mode, which means we have - // provided more than 9 characters that can't be a dictionary hash. - std::string non_sdch_content("This is not SDCH"); - - char* input_buffer = filter->stream_buffer()->data(); - int input_buffer_size = filter->stream_buffer_size(); - - EXPECT_LT(static_cast<int>(non_sdch_content.size()), - input_buffer_size); - memcpy(input_buffer, non_sdch_content.data(), - non_sdch_content.size()); - filter->FlushStreamBuffer(non_sdch_content.size()); - - // Try to read output. - int output_bytes_or_buffer_size = sizeof(output_buffer); - Filter::FilterStatus status = filter->ReadData(output_buffer, - &output_bytes_or_buffer_size); - - // We should have read a long and complicated meta-refresh request. - EXPECT_TRUE(sizeof(output_buffer) == output_bytes_or_buffer_size); - // Check at least the prefix of the return. - EXPECT_EQ(0, strncmp(output_buffer, - "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\"></head>", - sizeof(output_buffer))); - EXPECT_EQ(Filter::FILTER_OK, status); -} - -TEST_F(SdchFilterTest, ErrorOnBadReturnCode) { - std::vector<Filter::FilterType> filter_types; - // Selective a tentative filter (which can fall back to pass through). - filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); - char output_buffer[20]; - MockFilterContext filter_context; - // Response code needs to be 200 to allow a pass through. - filter_context.SetResponseCode(403); - // Meta refresh will only appear for html content, so set to something else - // to induce an error (we can't meta refresh). - filter_context.SetMimeType("anything"); - std::string url_string("http://ignore.com"); - filter_context.SetURL(GURL(url_string)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - // Supply enough data to force a pass-through mode, which means we have - // provided more than 9 characters that can't be a dictionary hash. - std::string non_sdch_content("This is not SDCH"); - - char* input_buffer = filter->stream_buffer()->data(); - int input_buffer_size = filter->stream_buffer_size(); - - EXPECT_LT(static_cast<int>(non_sdch_content.size()), - input_buffer_size); - memcpy(input_buffer, non_sdch_content.data(), - non_sdch_content.size()); - filter->FlushStreamBuffer(non_sdch_content.size()); - - // Try to read output. - int output_bytes_or_buffer_size = sizeof(output_buffer); - Filter::FilterStatus status = filter->ReadData(output_buffer, - &output_bytes_or_buffer_size); - - EXPECT_EQ(0, output_bytes_or_buffer_size); - EXPECT_EQ(Filter::FILTER_ERROR, status); -} - -TEST_F(SdchFilterTest, ErrorOnBadReturnCodeWithHtml) { - std::vector<Filter::FilterType> filter_types; - // Selective a tentative filter (which can fall back to pass through). - filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); - char output_buffer[20]; - MockFilterContext filter_context; - // Response code needs to be 200 to allow a pass through. - filter_context.SetResponseCode(403); - // Meta refresh will only appear for html content - filter_context.SetMimeType("text/html"); - std::string url_string("http://ignore.com"); - filter_context.SetURL(GURL(url_string)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - // Supply enough data to force a pass-through mode, which means we have - // provided more than 9 characters that can't be a dictionary hash. - std::string non_sdch_content("This is not SDCH"); - - char* input_buffer = filter->stream_buffer()->data(); - int input_buffer_size = filter->stream_buffer_size(); - - EXPECT_LT(static_cast<int>(non_sdch_content.size()), - input_buffer_size); - memcpy(input_buffer, non_sdch_content.data(), - non_sdch_content.size()); - filter->FlushStreamBuffer(non_sdch_content.size()); - - // Try to read output. - int output_bytes_or_buffer_size = sizeof(output_buffer); - Filter::FilterStatus status = filter->ReadData(output_buffer, - &output_bytes_or_buffer_size); - - // We should have read a long and complicated meta-refresh request. - EXPECT_EQ(sizeof(output_buffer), - static_cast<size_t>(output_bytes_or_buffer_size)); - // Check at least the prefix of the return. - EXPECT_EQ(0, strncmp(output_buffer, - "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\"></head>", - sizeof(output_buffer))); - EXPECT_EQ(Filter::FILTER_OK, status); -} - -TEST_F(SdchFilterTest, BasicBadDictionary) { - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - char output_buffer[20]; - MockFilterContext filter_context; - std::string url_string("http://ignore.com"); - filter_context.SetURL(GURL(url_string)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - // Supply bogus data (which doesn't yet specify a full dictionary hash). - // Dictionary hash is 8 characters followed by a null. - std::string dictionary_hash_prefix("123"); - - char* input_buffer = filter->stream_buffer()->data(); - int input_buffer_size = filter->stream_buffer_size(); - - EXPECT_LT(static_cast<int>(dictionary_hash_prefix.size()), - input_buffer_size); - memcpy(input_buffer, dictionary_hash_prefix.data(), - dictionary_hash_prefix.size()); - filter->FlushStreamBuffer(dictionary_hash_prefix.size()); - - // With less than a dictionary specifier, try to read output. - int output_bytes_or_buffer_size = sizeof(output_buffer); - Filter::FilterStatus status = filter->ReadData(output_buffer, - &output_bytes_or_buffer_size); - - EXPECT_EQ(0, output_bytes_or_buffer_size); - EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); - - // Provide enough data to complete *a* hash, but it is bogus, and not in our - // list of dictionaries, so the filter should error out immediately. - std::string dictionary_hash_postfix("4abcd\0", 6); - - CHECK_LT(dictionary_hash_postfix.size(), - static_cast<size_t>(input_buffer_size)); - memcpy(input_buffer, dictionary_hash_postfix.data(), - dictionary_hash_postfix.size()); - filter->FlushStreamBuffer(dictionary_hash_postfix.size()); - - // With a non-existant dictionary specifier, try to read output. - output_bytes_or_buffer_size = sizeof(output_buffer); - status = filter->ReadData(output_buffer, &output_bytes_or_buffer_size); - - EXPECT_EQ(0, output_bytes_or_buffer_size); - EXPECT_EQ(Filter::FILTER_ERROR, status); - - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); - SdchManager::ClearBlacklistings(); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); -} - -TEST_F(SdchFilterTest, DictionaryAddOnce) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - // Check we can't add it twice. - EXPECT_FALSE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - const std::string kSampleDomain2 = "sdchtest2.com"; - - // Construct a second SDCH dictionary from a VCDIFF dictionary. - std::string dictionary2(NewSdchDictionary(kSampleDomain2)); - - std::string url_string2 = "http://" + kSampleDomain2; - GURL url2(url_string2); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary2, url2)); -} - -TEST_F(SdchFilterTest, BasicDictionary) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string compressed(NewSdchCompressedData(dictionary)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - MockFilterContext filter_context; - filter_context.SetURL(url); - - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - size_t feed_block_size = 100; - size_t output_block_size = 100; - std::string output; - EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Decode with really small buffers (size 1) to check for edge effects. - filter.reset(Filter::Factory(filter_types, filter_context)); - - feed_block_size = 1; - output_block_size = 1; - output.clear(); - EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); - EXPECT_EQ(output, expanded_); -} - -TEST_F(SdchFilterTest, NoDecodeHttps) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string compressed(NewSdchCompressedData(dictionary)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - MockFilterContext filter_context; - filter_context.SetURL(GURL("https://" + kSampleDomain)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - const size_t feed_block_size(100); - const size_t output_block_size(100); - std::string output; - - EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); -} - -// Current failsafe TODO/hack refuses to decode any content that doesn't use -// http as the scheme (see use of DICTIONARY_SELECTED_FOR_NON_HTTP). -// The following tests this blockage. Note that blacklisting results, so we -// we need separate tests for each of these. -TEST_F(SdchFilterTest, NoDecodeFtp) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string compressed(NewSdchCompressedData(dictionary)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - MockFilterContext filter_context; - filter_context.SetURL(GURL("ftp://" + kSampleDomain)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - const size_t feed_block_size(100); - const size_t output_block_size(100); - std::string output; - - EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); -} - -TEST_F(SdchFilterTest, NoDecodeFileColon) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string compressed(NewSdchCompressedData(dictionary)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - MockFilterContext filter_context; - filter_context.SetURL(GURL("file://" + kSampleDomain)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - const size_t feed_block_size(100); - const size_t output_block_size(100); - std::string output; - - EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); -} - -TEST_F(SdchFilterTest, NoDecodeAboutColon) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string compressed(NewSdchCompressedData(dictionary)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - MockFilterContext filter_context; - filter_context.SetURL(GURL("about://" + kSampleDomain)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - const size_t feed_block_size(100); - const size_t output_block_size(100); - std::string output; - - EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); -} - -TEST_F(SdchFilterTest, NoDecodeJavaScript) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string compressed(NewSdchCompressedData(dictionary)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - MockFilterContext filter_context; - filter_context.SetURL(GURL("javascript://" + kSampleDomain)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - const size_t feed_block_size(100); - const size_t output_block_size(100); - std::string output; - - EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); -} - -TEST_F(SdchFilterTest, CanStillDecodeHttp) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string compressed(NewSdchCompressedData(dictionary)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - MockFilterContext filter_context; - filter_context.SetURL(GURL("http://" + kSampleDomain)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - const size_t feed_block_size(100); - const size_t output_block_size(100); - std::string output; - - EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); -} - -TEST_F(SdchFilterTest, CrossDomainDictionaryUse) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string compressed(NewSdchCompressedData(dictionary)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - // Decode with content arriving from the "wrong" domain. - // This tests SdchManager::CanSet(). - MockFilterContext filter_context; - GURL wrong_domain_url("http://www.wrongdomain.com"); - filter_context.SetURL(wrong_domain_url); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - size_t feed_block_size = 100; - size_t output_block_size = 100; - std::string output; - EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, - filter.get(), &output)); - EXPECT_EQ(output.size(), 0u); // No output written. - - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(wrong_domain_url)); - SdchManager::ClearBlacklistings(); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(wrong_domain_url)); -} - -TEST_F(SdchFilterTest, DictionaryPathValidation) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - // Create a dictionary with a path restriction, by prefixing dictionary. - const std::string path("/special_path/bin"); - std::string dictionary_with_path("Path: " + path + "\n"); - dictionary_with_path.append(dictionary); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_with_path, url)); - - std::string compressed_for_path(NewSdchCompressedData(dictionary_with_path)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - // Test decode the path data, arriving from a valid path. - MockFilterContext filter_context; - filter_context.SetURL(GURL(url_string + path)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - size_t feed_block_size = 100; - size_t output_block_size = 100; - std::string output; - - EXPECT_TRUE(FilterTestData(compressed_for_path, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Test decode the path data, arriving from a invalid path. - filter_context.SetURL(GURL(url_string)); - filter.reset(Filter::Factory(filter_types, filter_context)); - - feed_block_size = 100; - output_block_size = 100; - output.clear(); - EXPECT_FALSE(FilterTestData(compressed_for_path, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output.size(), 0u); // No output written. - - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); - SdchManager::ClearBlacklistings(); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); -} - -TEST_F(SdchFilterTest, DictionaryPortValidation) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - - // Create a dictionary with a port restriction, by prefixing old dictionary. - const std::string port("502"); - std::string dictionary_with_port("Port: " + port + "\n"); - dictionary_with_port.append("Port: 80\n"); // Add default port. - dictionary_with_port.append(dictionary); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_with_port, - GURL(url_string + ":" + port))); - - std::string compressed_for_port(NewSdchCompressedData(dictionary_with_port)); - - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - // Test decode the port data, arriving from a valid port. - MockFilterContext filter_context; - filter_context.SetURL(GURL(url_string + ":" + port)); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - size_t feed_block_size = 100; - size_t output_block_size = 100; - std::string output; - EXPECT_TRUE(FilterTestData(compressed_for_port, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Test decode the port data, arriving from a valid (default) port. - filter_context.SetURL(GURL(url_string)); // Default port. - filter.reset(Filter::Factory(filter_types, filter_context)); - - feed_block_size = 100; - output_block_size = 100; - output.clear(); - EXPECT_TRUE(FilterTestData(compressed_for_port, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Test decode the port data, arriving from a invalid port. - filter_context.SetURL(GURL(url_string + ":" + port + "1")); - filter.reset(Filter::Factory(filter_types, filter_context)); - - feed_block_size = 100; - output_block_size = 100; - output.clear(); - EXPECT_FALSE(FilterTestData(compressed_for_port, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output.size(), 0u); // No output written. - - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); - SdchManager::ClearBlacklistings(); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); -} - -//------------------------------------------------------------------------------ -// Helper function to perform gzip compression of data. - -static std::string gzip_compress(const std::string &input) { - z_stream zlib_stream; - memset(&zlib_stream, 0, sizeof(zlib_stream)); - int code; - - // Initialize zlib - code = deflateInit2(&zlib_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, - -MAX_WBITS, - 8, // DEF_MEM_LEVEL - Z_DEFAULT_STRATEGY); - - CHECK_EQ(Z_OK, code); - - // Fill in zlib control block - zlib_stream.next_in = bit_cast<Bytef*>(input.data()); - zlib_stream.avail_in = input.size(); - - // Assume we can compress into similar buffer (add 100 bytes to be sure). - size_t gzip_compressed_length = zlib_stream.avail_in + 100; - scoped_ptr<char[]> gzip_compressed(new char[gzip_compressed_length]); - zlib_stream.next_out = bit_cast<Bytef*>(gzip_compressed.get()); - zlib_stream.avail_out = gzip_compressed_length; - - // The GZIP header (see RFC 1952): - // +---+---+---+---+---+---+---+---+---+---+ - // |ID1|ID2|CM |FLG| MTIME |XFL|OS | - // +---+---+---+---+---+---+---+---+---+---+ - // ID1 \037 - // ID2 \213 - // CM \010 (compression method == DEFLATE) - // FLG \000 (special flags that we do not support) - // MTIME Unix format modification time (0 means not available) - // XFL 2-4? DEFLATE flags - // OS ???? Operating system indicator (255 means unknown) - // - // Header value we generate: - const char kGZipHeader[] = { '\037', '\213', '\010', '\000', '\000', - '\000', '\000', '\000', '\002', '\377' }; - CHECK_GT(zlib_stream.avail_out, sizeof(kGZipHeader)); - memcpy(zlib_stream.next_out, kGZipHeader, sizeof(kGZipHeader)); - zlib_stream.next_out += sizeof(kGZipHeader); - zlib_stream.avail_out -= sizeof(kGZipHeader); - - // Do deflate - code = deflate(&zlib_stream, Z_FINISH); - gzip_compressed_length -= zlib_stream.avail_out; - std::string compressed(gzip_compressed.get(), gzip_compressed_length); - deflateEnd(&zlib_stream); - return compressed; -} - -//------------------------------------------------------------------------------ - -class SdchFilterChainingTest { - public: - static Filter* Factory(const std::vector<Filter::FilterType>& types, - const FilterContext& context, int size) { - return Filter::FactoryForTests(types, context, size); - } -}; - -// Test that filters can be cascaded (chained) so that the output of one filter -// is processed by the next one. This is most critical for SDCH, which is -// routinely followed by gzip (during encoding). The filter we'll test for will -// do the gzip decoding first, and then decode the SDCH content. -TEST_F(SdchFilterTest, FilterChaining) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string sdch_compressed(NewSdchCompressedData(dictionary)); - - // Use Gzip to compress the sdch sdch_compressed data. - std::string gzip_compressed_sdch = gzip_compress(sdch_compressed); - - // Construct a chained filter. - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - filter_types.push_back(Filter::FILTER_TYPE_GZIP); - - // First try with a large buffer (larger than test input, or compressed data). - const size_t kLargeInputBufferSize(1000); // Used internally in filters. - CHECK_GT(kLargeInputBufferSize, gzip_compressed_sdch.size()); - CHECK_GT(kLargeInputBufferSize, sdch_compressed.size()); - CHECK_GT(kLargeInputBufferSize, expanded_.size()); - MockFilterContext filter_context; - filter_context.SetURL(url); - scoped_ptr<Filter> filter( - SdchFilterChainingTest::Factory(filter_types, filter_context, - kLargeInputBufferSize)); - EXPECT_EQ(static_cast<int>(kLargeInputBufferSize), - filter->stream_buffer_size()); - - // Verify that chained filter is waiting for data. - char tiny_output_buffer[10]; - int tiny_output_size = sizeof(tiny_output_buffer); - EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, - filter->ReadData(tiny_output_buffer, &tiny_output_size)); - - // Make chain process all data. - size_t feed_block_size = kLargeInputBufferSize; - size_t output_block_size = kLargeInputBufferSize; - std::string output; - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Next try with a mid-sized internal buffer size. - const size_t kMidSizedInputBufferSize(100); - // Buffer should be big enough to swallow whole gzip content. - CHECK_GT(kMidSizedInputBufferSize, gzip_compressed_sdch.size()); - // Buffer should be small enough that entire SDCH content can't fit. - // We'll go even further, and force the chain to flush the buffer between the - // two filters more than once (that is why we multiply by 2). - CHECK_LT(kMidSizedInputBufferSize * 2, sdch_compressed.size()); - filter_context.SetURL(url); - filter.reset( - SdchFilterChainingTest::Factory(filter_types, filter_context, - kMidSizedInputBufferSize)); - EXPECT_EQ(static_cast<int>(kMidSizedInputBufferSize), - filter->stream_buffer_size()); - - feed_block_size = kMidSizedInputBufferSize; - output_block_size = kMidSizedInputBufferSize; - output.clear(); - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Next try with a tiny input and output buffer to cover edge effects. - filter.reset(SdchFilterChainingTest::Factory(filter_types, filter_context, - kLargeInputBufferSize)); - EXPECT_EQ(static_cast<int>(kLargeInputBufferSize), - filter->stream_buffer_size()); - - feed_block_size = 1; - output_block_size = 1; - output.clear(); - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); -} - -TEST_F(SdchFilterTest, DefaultGzipIfSdch) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string sdch_compressed(NewSdchCompressedData(dictionary)); - - // Use Gzip to compress the sdch sdch_compressed data. - std::string gzip_compressed_sdch = gzip_compress(sdch_compressed); - - // Only claim to have sdch content, but really use the gzipped sdch content. - // System should automatically add the missing (optional) gzip. - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_SDCH); - - MockFilterContext filter_context; - filter_context.SetMimeType("anything/mime"); - filter_context.SetSdchResponse(true); - Filter::FixupEncodingTypes(filter_context, &filter_types); - ASSERT_EQ(filter_types.size(), 2u); - EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH); - EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); - - // First try with a large buffer (larger than test input, or compressed data). - filter_context.SetURL(url); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - - // Verify that chained filter is waiting for data. - char tiny_output_buffer[10]; - int tiny_output_size = sizeof(tiny_output_buffer); - EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, - filter->ReadData(tiny_output_buffer, &tiny_output_size)); - - size_t feed_block_size = 100; - size_t output_block_size = 100; - std::string output; - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Next try with a tiny buffer to cover edge effects. - filter.reset(Filter::Factory(filter_types, filter_context)); - - feed_block_size = 1; - output_block_size = 1; - output.clear(); - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); -} - -TEST_F(SdchFilterTest, AcceptGzipSdchIfGzip) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string sdch_compressed(NewSdchCompressedData(dictionary)); - - // Use Gzip to compress the sdch sdch_compressed data. - std::string gzip_compressed_sdch = gzip_compress(sdch_compressed); - - // Some proxies strip the content encoding statement down to a mere gzip, but - // pass through the original content (with full sdch,gzip encoding). - // Only claim to have gzip content, but really use the gzipped sdch content. - // System should automatically add the missing (optional) sdch. - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_GZIP); - - MockFilterContext filter_context; - filter_context.SetMimeType("anything/mime"); - filter_context.SetSdchResponse(true); - Filter::FixupEncodingTypes(filter_context, &filter_types); - ASSERT_EQ(filter_types.size(), 3u); - EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); - EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); - EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP); - - // First try with a large buffer (larger than test input, or compressed data). - filter_context.SetURL(url); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - - // Verify that chained filter is waiting for data. - char tiny_output_buffer[10]; - int tiny_output_size = sizeof(tiny_output_buffer); - EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, - filter->ReadData(tiny_output_buffer, &tiny_output_size)); - - size_t feed_block_size = 100; - size_t output_block_size = 100; - std::string output; - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Next try with a tiny buffer to cover edge effects. - filter.reset(Filter::Factory(filter_types, filter_context)); - - feed_block_size = 1; - output_block_size = 1; - output.clear(); - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); -} - -TEST_F(SdchFilterTest, DefaultSdchGzipIfEmpty) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string sdch_compressed(NewSdchCompressedData(dictionary)); - - // Use Gzip to compress the sdch sdch_compressed data. - std::string gzip_compressed_sdch = gzip_compress(sdch_compressed); - - // Only claim to have non-encoded content, but really use the gzipped sdch - // content. - // System should automatically add the missing (optional) sdch,gzip. - std::vector<Filter::FilterType> filter_types; - - MockFilterContext filter_context; - filter_context.SetMimeType("anything/mime"); - filter_context.SetSdchResponse(true); - Filter::FixupEncodingTypes(filter_context, &filter_types); - ASSERT_EQ(filter_types.size(), 2u); - EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); - EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); - - // First try with a large buffer (larger than test input, or compressed data). - filter_context.SetURL(url); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - - // Verify that chained filter is waiting for data. - char tiny_output_buffer[10]; - int tiny_output_size = sizeof(tiny_output_buffer); - EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, - filter->ReadData(tiny_output_buffer, &tiny_output_size)); - - size_t feed_block_size = 100; - size_t output_block_size = 100; - std::string output; - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Next try with a tiny buffer to cover edge effects. - filter.reset(Filter::Factory(filter_types, filter_context)); - - feed_block_size = 1; - output_block_size = 1; - output.clear(); - EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); -} - -TEST_F(SdchFilterTest, AcceptGzipGzipSdchIfGzip) { - // Construct a valid SDCH dictionary from a VCDIFF dictionary. - const std::string kSampleDomain = "sdchtest.com"; - std::string dictionary(NewSdchDictionary(kSampleDomain)); - - std::string url_string = "http://" + kSampleDomain; - - GURL url(url_string); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); - - std::string sdch_compressed(NewSdchCompressedData(dictionary)); - - // Vodaphone (UK) Mobile Broadband provides double gzipped sdch with a content - // encoding of merely gzip (apparently, only listing the extra level of - // wrapper compression they added, but discarding the actual content encoding. - // Use Gzip to double compress the sdch sdch_compressed data. - std::string double_gzip_compressed_sdch = gzip_compress(gzip_compress( - sdch_compressed)); - - // Only claim to have gzip content, but really use the double gzipped sdch - // content. - // System should automatically add the missing (optional) sdch, gzip decoders. - std::vector<Filter::FilterType> filter_types; - filter_types.push_back(Filter::FILTER_TYPE_GZIP); - - MockFilterContext filter_context; - filter_context.SetMimeType("anything/mime"); - filter_context.SetSdchResponse(true); - Filter::FixupEncodingTypes(filter_context, &filter_types); - ASSERT_EQ(filter_types.size(), 3u); - EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); - EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); - EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP); - - // First try with a large buffer (larger than test input, or compressed data). - filter_context.SetURL(url); - scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); - - - // Verify that chained filter is waiting for data. - char tiny_output_buffer[10]; - int tiny_output_size = sizeof(tiny_output_buffer); - EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, - filter->ReadData(tiny_output_buffer, &tiny_output_size)); - - size_t feed_block_size = 100; - size_t output_block_size = 100; - std::string output; - EXPECT_TRUE(FilterTestData(double_gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); - - // Next try with a tiny buffer to cover edge effects. - filter.reset(Filter::Factory(filter_types, filter_context)); - - feed_block_size = 1; - output_block_size = 1; - output.clear(); - EXPECT_TRUE(FilterTestData(double_gzip_compressed_sdch, feed_block_size, - output_block_size, filter.get(), &output)); - EXPECT_EQ(output, expanded_); -} - -TEST_F(SdchFilterTest, DomainSupported) { - GURL google_url("http://www.google.com"); - - net::SdchManager::EnableSdchSupport(false); - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(google_url)); - net::SdchManager::EnableSdchSupport(true); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(google_url)); -} - -TEST_F(SdchFilterTest, DomainBlacklisting) { - GURL test_url("http://www.test.com"); - GURL google_url("http://www.google.com"); - - SdchManager::BlacklistDomain(test_url); - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(test_url)); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(google_url)); - - SdchManager::BlacklistDomain(google_url); - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(google_url)); -} - -TEST_F(SdchFilterTest, DomainBlacklistingCaseSensitivity) { - GURL test_url("http://www.TesT.com"); - GURL test2_url("http://www.tEst.com"); - - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(test_url)); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(test2_url)); - SdchManager::BlacklistDomain(test_url); - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(test2_url)); -} - -TEST_F(SdchFilterTest, BlacklistingReset) { - GURL gurl("http://mytest.DoMain.com"); - std::string domain(gurl.host()); - - SdchManager::ClearBlacklistings(); - EXPECT_EQ(SdchManager::BlackListDomainCount(domain), 0); - EXPECT_EQ(SdchManager::BlacklistDomainExponential(domain), 0); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(gurl)); -} - -TEST_F(SdchFilterTest, BlacklistingSingleBlacklist) { - GURL gurl("http://mytest.DoMain.com"); - std::string domain(gurl.host()); - SdchManager::ClearBlacklistings(); - - SdchManager::Global()->BlacklistDomain(gurl); - EXPECT_EQ(SdchManager::BlackListDomainCount(domain), 1); - EXPECT_EQ(SdchManager::BlacklistDomainExponential(domain), 1); - - // Check that any domain lookup reduces the blacklist counter. - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(gurl)); - EXPECT_EQ(SdchManager::BlackListDomainCount(domain), 0); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(gurl)); -} - -TEST_F(SdchFilterTest, BlacklistingExponential) { - GURL gurl("http://mytest.DoMain.com"); - std::string domain(gurl.host()); - SdchManager::ClearBlacklistings(); - - int exponential = 1; - for (int i = 1; i < 100; ++i) { - SdchManager::Global()->BlacklistDomain(gurl); - EXPECT_EQ(SdchManager::BlacklistDomainExponential(domain), exponential); - - EXPECT_EQ(SdchManager::BlackListDomainCount(domain), exponential); - EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(gurl)); - EXPECT_EQ(SdchManager::BlackListDomainCount(domain), exponential - 1); - - // Simulate a large number of domain checks (which eventually remove the - // blacklisting). - SdchManager::ClearDomainBlacklisting(domain); - EXPECT_EQ(SdchManager::BlackListDomainCount(domain), 0); - EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(gurl)); - - // Predict what exponential backoff will be. - exponential = 1 + 2 * exponential; - if (exponential < 0) - exponential = INT_MAX; // We don't wrap. - } -} - -TEST_F(SdchFilterTest, CanSetExactMatchDictionary) { - std::string dictionary_domain("x.y.z.google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - // Perfect match should work. - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); -} - -TEST_F(SdchFilterTest, FailToSetDomainMismatchDictionary) { - std::string dictionary_domain("x.y.z.google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - // Fail the "domain match" requirement. - EXPECT_FALSE(sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://y.z.google.com"))); -} - -TEST_F(SdchFilterTest, FailToSetDotHostPrefixDomainDictionary) { - std::string dictionary_domain("x.y.z.google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - // Fail the HD with D being the domain and H having a dot requirement. - EXPECT_FALSE(sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://w.x.y.z.google.com"))); -} - -TEST_F(SdchFilterTest, FailToSetRepeatPrefixWithDotDictionary) { - // Make sure that a prefix that matches the domain postfix won't confuse - // the validation checks. - std::string dictionary_domain("www.google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - // Fail the HD with D being the domain and H having a dot requirement. - EXPECT_FALSE(sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://www.google.com.www.google.com"))); -} - -TEST_F(SdchFilterTest, CanSetLeadingDotDomainDictionary) { - // Make sure that a prefix that matches the domain postfix won't confuse - // the validation checks. - std::string dictionary_domain(".google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - // Verify that a leading dot in the domain is acceptable, as long as the host - // name does not contain any dots preceding the matched domain name. - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://www.google.com"))); -} - -// Make sure the order of the tests is not helping us or confusing things. -// See test CanSetExactMatchDictionary above for first try. -TEST_F(SdchFilterTest, CanStillSetExactMatchDictionary) { - std::string dictionary_domain("x.y.z.google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - // Perfect match should *STILL* work. - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); -} - -// Make sure the DOS protection precludes the addition of too many dictionaries. -TEST_F(SdchFilterTest, TooManyDictionaries) { - std::string dictionary_domain(".google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - size_t count = 0; - while (count <= SdchManager::kMaxDictionaryCount + 1) { - if (!sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://www.google.com"))) - break; - - dictionary_text += " "; // Create dictionary with different SHA signature. - ++count; - } - EXPECT_EQ(SdchManager::kMaxDictionaryCount, count); -} - -TEST_F(SdchFilterTest, DictionaryNotTooLarge) { - std::string dictionary_domain(".google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - dictionary_text.append( - SdchManager::kMaxDictionarySize - dictionary_text.size(), ' '); - EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); -} - -TEST_F(SdchFilterTest, DictionaryTooLarge) { - std::string dictionary_domain(".google.com"); - std::string dictionary_text(NewSdchDictionary(dictionary_domain)); - - dictionary_text.append( - SdchManager::kMaxDictionarySize + 1 - dictionary_text.size(), ' '); - EXPECT_FALSE(sdch_manager_->AddSdchDictionary(dictionary_text, - GURL("http://" + dictionary_domain))); -} - -TEST_F(SdchFilterTest, PathMatch) { - bool (*PathMatch)(const std::string& path, const std::string& restriction) = - SdchManager::Dictionary::PathMatch; - // Perfect match is supported. - EXPECT_TRUE(PathMatch("/search", "/search")); - EXPECT_TRUE(PathMatch("/search/", "/search/")); - - // Prefix only works if last character of restriction is a slash, or first - // character in path after a match is a slash. Validate each case separately. - - // Rely on the slash in the path (not at the end of the restriction). - EXPECT_TRUE(PathMatch("/search/something", "/search")); - EXPECT_TRUE(PathMatch("/search/s", "/search")); - EXPECT_TRUE(PathMatch("/search/other", "/search")); - EXPECT_TRUE(PathMatch("/search/something", "/search")); - - // Rely on the slash at the end of the restriction. - EXPECT_TRUE(PathMatch("/search/something", "/search/")); - EXPECT_TRUE(PathMatch("/search/s", "/search/")); - EXPECT_TRUE(PathMatch("/search/other", "/search/")); - EXPECT_TRUE(PathMatch("/search/something", "/search/")); - - // Make sure less that sufficient prefix match is false. - EXPECT_FALSE(PathMatch("/sear", "/search")); - EXPECT_FALSE(PathMatch("/", "/search")); - EXPECT_FALSE(PathMatch(std::string(), "/search")); - - // Add examples with several levels of direcories in the restriction. - EXPECT_FALSE(PathMatch("/search/something", "search/s")); - EXPECT_FALSE(PathMatch("/search/", "/search/s")); - - // Make sure adding characters to path will also fail. - EXPECT_FALSE(PathMatch("/searching", "/search/")); - EXPECT_FALSE(PathMatch("/searching", "/search")); - - // Make sure we're case sensitive. - EXPECT_FALSE(PathMatch("/ABC", "/abc")); - EXPECT_FALSE(PathMatch("/abc", "/ABC")); -} - -// The following are only applicable while we have a latency test in the code, -// and can be removed when that functionality is stripped. -TEST_F(SdchFilterTest, LatencyTestControls) { - GURL url("http://www.google.com"); - GURL url2("http://www.google2.com"); - - // First make sure we default to false. - EXPECT_FALSE(sdch_manager_->AllowLatencyExperiment(url)); - EXPECT_FALSE(sdch_manager_->AllowLatencyExperiment(url2)); - - // That we can set each to true. - sdch_manager_->SetAllowLatencyExperiment(url, true); - EXPECT_TRUE(sdch_manager_->AllowLatencyExperiment(url)); - EXPECT_FALSE(sdch_manager_->AllowLatencyExperiment(url2)); - - sdch_manager_->SetAllowLatencyExperiment(url2, true); - EXPECT_TRUE(sdch_manager_->AllowLatencyExperiment(url)); - EXPECT_TRUE(sdch_manager_->AllowLatencyExperiment(url2)); - - // And can reset them to false. - sdch_manager_->SetAllowLatencyExperiment(url, false); - EXPECT_FALSE(sdch_manager_->AllowLatencyExperiment(url)); - EXPECT_TRUE(sdch_manager_->AllowLatencyExperiment(url2)); - - sdch_manager_->SetAllowLatencyExperiment(url2, false); - EXPECT_FALSE(sdch_manager_->AllowLatencyExperiment(url)); - EXPECT_FALSE(sdch_manager_->AllowLatencyExperiment(url2)); -} - -} // namespace net |