This source file includes following definitions.
- sdch_manager_
- NewSdchCompressedData
- TEST_F
- FilterTestData
- NewSdchDictionary
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- gzip_compress
- Factory
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include <limits.h>
#include <algorithm>
#include <string>
#include <vector>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/io_buffer.h"
#include "net/filter/mock_filter_context.h"
#include "net/filter/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 {
static const char kTestVcdiffDictionary[] = "DictionaryFor"
"SdchCompression1SdchCompression2SdchCompression3SdchCompression\n";
static const char kTestData[] = "0000000000000000000000000000000000000000000000"
"0000000000000000000000000000TestData "
"SdchCompression1SdchCompression2SdchCompression3SdchCompression"
"00000000000000000000000000000000000000000000000000000000000000000000000000"
"000000000000000000000000000000000000000\n";
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_;
scoped_ptr<SdchManager> sdch_manager_;
};
std::string SdchFilterTest::NewSdchCompressedData(
const std::string dictionary) {
std::string client_hash;
std::string server_hash;
SdchManager::GenerateHash(dictionary, &client_hash, &server_hash);
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");
}
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;
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));
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;
filter_types.push_back(Filter::FILTER_TYPE_GZIP_HELPING_SDCH);
char output_buffer[20];
MockFilterContext filter_context;
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));
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());
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;
filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE);
char output_buffer[20];
MockFilterContext filter_context;
filter_context.SetResponseCode(403);
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));
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());
int output_bytes_or_buffer_size = sizeof(output_buffer);
Filter::FilterStatus status = filter->ReadData(output_buffer,
&output_bytes_or_buffer_size);
EXPECT_TRUE(sizeof(output_buffer) == output_bytes_or_buffer_size);
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;
filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE);
char output_buffer[20];
MockFilterContext filter_context;
filter_context.SetResponseCode(403);
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));
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());
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;
filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE);
char output_buffer[20];
MockFilterContext filter_context;
filter_context.SetResponseCode(403);
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));
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());
int output_bytes_or_buffer_size = sizeof(output_buffer);
Filter::FilterStatus status = filter->ReadData(output_buffer,
&output_bytes_or_buffer_size);
EXPECT_EQ(sizeof(output_buffer),
static_cast<size_t>(output_bytes_or_buffer_size));
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));
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());
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);
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());
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) {
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));
EXPECT_FALSE(sdch_manager_->AddSdchDictionary(dictionary, url));
const std::string kSampleDomain2 = "sdchtest2.com";
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) {
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_);
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) {
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));
}
TEST_F(SdchFilterTest, NoDecodeFtp) {
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) {
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) {
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) {
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) {
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) {
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;
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);
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) {
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));
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);
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_);
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);
EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string)));
SdchManager::ClearBlacklistings();
EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string)));
}
TEST_F(SdchFilterTest, DictionaryPortValidation) {
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));
const std::string port("502");
std::string dictionary_with_port("Port: " + port + "\n");
dictionary_with_port.append("Port: 80\n");
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);
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_);
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_TRUE(FilterTestData(compressed_for_port, feed_block_size,
output_block_size, filter.get(), &output));
EXPECT_EQ(output, expanded_);
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);
EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string)));
SdchManager::ClearBlacklistings();
EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string)));
}
static std::string gzip_compress(const std::string &input) {
z_stream zlib_stream;
memset(&zlib_stream, 0, sizeof(zlib_stream));
int code;
code = deflateInit2(&zlib_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
-MAX_WBITS,
8,
Z_DEFAULT_STRATEGY);
CHECK_EQ(Z_OK, code);
zlib_stream.next_in = bit_cast<Bytef*>(input.data());
zlib_stream.avail_in = input.size();
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;
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);
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_F(SdchFilterTest, FilterChaining) {
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));
std::string gzip_compressed_sdch = gzip_compress(sdch_compressed);
std::vector<Filter::FilterType> filter_types;
filter_types.push_back(Filter::FILTER_TYPE_SDCH);
filter_types.push_back(Filter::FILTER_TYPE_GZIP);
const size_t kLargeInputBufferSize(1000);
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());
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 = 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_);
const size_t kMidSizedInputBufferSize(100);
CHECK_GT(kMidSizedInputBufferSize, gzip_compressed_sdch.size());
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_);
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) {
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));
std::string gzip_compressed_sdch = gzip_compress(sdch_compressed);
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);
filter_context.SetURL(url);
scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
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_);
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) {
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));
std::string gzip_compressed_sdch = gzip_compress(sdch_compressed);
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);
filter_context.SetURL(url);
scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
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_);
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) {
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));
std::string gzip_compressed_sdch = gzip_compress(sdch_compressed);
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);
filter_context.SetURL(url);
scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
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_);
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) {
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));
std::string double_gzip_compressed_sdch = gzip_compress(gzip_compress(
sdch_compressed));
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);
filter_context.SetURL(url);
scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context));
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_);
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_);
}
}