| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <limits.h> | 5 #include <limits.h> |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "net/base/io_buffer.h" | 13 #include "net/base/io_buffer.h" |
| 14 #include "net/filter/mock_filter_context.h" | 14 #include "net/filter/mock_filter_context.h" |
| 15 #include "net/filter/sdch_filter.h" | 15 #include "net/filter/sdch_filter.h" |
| 16 #include "net/url_request/url_request_http_job.h" | 16 #include "net/url_request/url_request_http_job.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" | 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 #include "third_party/zlib/zlib.h" | 18 #include "third_party/zlib/zlib.h" |
| 19 | 19 |
| 20 namespace net { | 20 namespace net { |
| 21 | 21 |
| 22 //------------------------------------------------------------------------------ | 22 //------------------------------------------------------------------------------ |
| 23 // Provide sample data and compression results with a sample VCDIFF dictionary. | 23 // Provide sample data and compression results with a sample VCDIFF dictionary. |
| 24 // Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary. | 24 // Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary. |
| 25 static const char kTestVcdiffDictionary[] = "DictionaryFor" | 25 static const char kTestVcdiffDictionary[] = |
| 26 "DictionaryFor" |
| 26 "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n"; | 27 "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n"; |
| 27 // Pre-compression test data. Note that we pad with a lot of highly gzip | 28 // Pre-compression test data. Note that we pad with a lot of highly gzip |
| 28 // compressible content to help to exercise the chaining pipeline. That is why | 29 // compressible content to help to exercise the chaining pipeline. That is why |
| 29 // there are a PILE of zeros at the start and end. | 30 // there are a PILE of zeros at the start and end. |
| 30 // This will ensure that gzip compressed data can be fed to the chain in one | 31 // This will ensure that gzip compressed data can be fed to the chain in one |
| 31 // gulp, but (with careful selection of intermediate buffers) that it takes | 32 // gulp, but (with careful selection of intermediate buffers) that it takes |
| 32 // several sdch buffers worth of data to satisfy the sdch filter. See detailed | 33 // several sdch buffers worth of data to satisfy the sdch filter. See detailed |
| 33 // CHECK() calls in FilterChaining test for specifics. | 34 // CHECK() calls in FilterChaining test for specifics. |
| 34 static const char kTestData[] = "0000000000000000000000000000000000000000000000" | 35 static const char kTestData[] = |
| 36 "0000000000000000000000000000000000000000000000" |
| 35 "0000000000000000000000000000TestData " | 37 "0000000000000000000000000000TestData " |
| 36 "SdchCompression1SdchCompression2SdchCompression3SdchCompression" | 38 "SdchCompression1SdchCompression2SdchCompression3SdchCompression" |
| 37 "00000000000000000000000000000000000000000000000000000000000000000000000000" | 39 "00000000000000000000000000000000000000000000000000000000000000000000000000" |
| 38 "000000000000000000000000000000000000000\n"; | 40 "000000000000000000000000000000000000000\n"; |
| 39 | 41 |
| 40 // Note SDCH compressed data will include a reference to the SDCH dictionary. | 42 // Note SDCH compressed data will include a reference to the SDCH dictionary. |
| 41 static const char kSdchCompressedTestData[] = | 43 static const char kSdchCompressedTestData[] = |
| 42 "\326\303\304\0\0\001M\0\201S\202\004\0\201E\006\001" | 44 "\326\303\304\0\0\001M\0\201S\202\004\0\201E\006\001" |
| 43 "00000000000000000000000000000000000000000000000000000000000000000000000000" | 45 "00000000000000000000000000000000000000000000000000000000000000000000000000" |
| 44 "TestData 00000000000000000000000000000000000000000000000000000000000000000" | 46 "TestData 00000000000000000000000000000000000000000000000000000000000000000" |
| 45 "000000000000000000000000000000000000000000000000\n\001S\023\077\001r\r"; | 47 "000000000000000000000000000000000000000000000000\n\001S\023\077\001r\r"; |
| 46 | 48 |
| 47 //------------------------------------------------------------------------------ | 49 //------------------------------------------------------------------------------ |
| 48 | 50 |
| 49 class SdchFilterTest : public testing::Test { | 51 class SdchFilterTest : public testing::Test { |
| 50 protected: | 52 protected: |
| 51 SdchFilterTest() | 53 SdchFilterTest() |
| 52 : test_vcdiff_dictionary_(kTestVcdiffDictionary, | 54 : test_vcdiff_dictionary_(kTestVcdiffDictionary, |
| 53 sizeof(kTestVcdiffDictionary) - 1), | 55 sizeof(kTestVcdiffDictionary) - 1), |
| 54 vcdiff_compressed_data_(kSdchCompressedTestData, | 56 vcdiff_compressed_data_(kSdchCompressedTestData, |
| 55 sizeof(kSdchCompressedTestData) - 1), | 57 sizeof(kSdchCompressedTestData) - 1), |
| 56 expanded_(kTestData, sizeof(kTestData) - 1), | 58 expanded_(kTestData, sizeof(kTestData) - 1), |
| 57 sdch_manager_(new SdchManager) { | 59 sdch_manager_(new SdchManager) {} |
| 58 } | |
| 59 | 60 |
| 60 std::string NewSdchCompressedData(const std::string dictionary); | 61 std::string NewSdchCompressedData(const std::string dictionary); |
| 61 | 62 |
| 62 const std::string test_vcdiff_dictionary_; | 63 const std::string test_vcdiff_dictionary_; |
| 63 const std::string vcdiff_compressed_data_; | 64 const std::string vcdiff_compressed_data_; |
| 64 const std::string expanded_; // Desired final, decompressed data. | 65 const std::string expanded_; // Desired final, decompressed data. |
| 65 | 66 |
| 66 scoped_ptr<SdchManager> sdch_manager_; // A singleton database. | 67 scoped_ptr<SdchManager> sdch_manager_; // A singleton database. |
| 67 }; | 68 }; |
| 68 | 69 |
| 69 std::string SdchFilterTest::NewSdchCompressedData( | 70 std::string SdchFilterTest::NewSdchCompressedData( |
| 70 const std::string dictionary) { | 71 const std::string dictionary) { |
| 71 std::string client_hash; | 72 std::string client_hash; |
| 72 std::string server_hash; | 73 std::string server_hash; |
| 73 SdchManager::GenerateHash(dictionary, &client_hash, &server_hash); | 74 SdchManager::GenerateHash(dictionary, &client_hash, &server_hash); |
| 74 | 75 |
| 75 // Build compressed data that refers to our dictionary. | 76 // Build compressed data that refers to our dictionary. |
| 76 std::string compressed(server_hash); | 77 std::string compressed(server_hash); |
| 77 compressed.append("\0", 1); | 78 compressed.append("\0", 1); |
| 78 compressed.append(vcdiff_compressed_data_); | 79 compressed.append(vcdiff_compressed_data_); |
| 79 return compressed; | 80 return compressed; |
| 80 } | 81 } |
| 81 | 82 |
| 82 //------------------------------------------------------------------------------ | 83 //------------------------------------------------------------------------------ |
| 83 | 84 |
| 84 | |
| 85 TEST_F(SdchFilterTest, Hashing) { | 85 TEST_F(SdchFilterTest, Hashing) { |
| 86 std::string client_hash, server_hash; | 86 std::string client_hash, server_hash; |
| 87 std::string dictionary("test contents"); | 87 std::string dictionary("test contents"); |
| 88 SdchManager::GenerateHash(dictionary, &client_hash, &server_hash); | 88 SdchManager::GenerateHash(dictionary, &client_hash, &server_hash); |
| 89 | 89 |
| 90 EXPECT_EQ(client_hash, "lMQBjS3P"); | 90 EXPECT_EQ(client_hash, "lMQBjS3P"); |
| 91 EXPECT_EQ(server_hash, "MyciMVll"); | 91 EXPECT_EQ(server_hash, "MyciMVll"); |
| 92 } | 92 } |
| 93 | 93 |
| 94 | |
| 95 //------------------------------------------------------------------------------ | 94 //------------------------------------------------------------------------------ |
| 96 // Provide a generic helper function for trying to filter data. | 95 // Provide a generic helper function for trying to filter data. |
| 97 // This function repeatedly calls the filter to process data, until the entire | 96 // This function repeatedly calls the filter to process data, until the entire |
| 98 // source is consumed. The return value from the filter is appended to output. | 97 // source is consumed. The return value from the filter is appended to output. |
| 99 // This allows us to vary input and output block sizes in order to test for edge | 98 // This allows us to vary input and output block sizes in order to test for edge |
| 100 // effects (boundary effects?) during the filtering process. | 99 // effects (boundary effects?) during the filtering process. |
| 101 // This function provides data to the filter in blocks of no-more-than the | 100 // This function provides data to the filter in blocks of no-more-than the |
| 102 // specified input_block_length. It allows the filter to fill no more than | 101 // specified input_block_length. It allows the filter to fill no more than |
| 103 // output_buffer_length in any one call to proccess (a.k.a., Read) data, and | 102 // output_buffer_length in any one call to proccess (a.k.a., Read) data, and |
| 104 // concatenates all these little output blocks into the singular output string. | 103 // concatenates all these little output blocks into the singular output string. |
| 105 static bool FilterTestData(const std::string& source, | 104 static bool FilterTestData(const std::string& source, |
| 106 size_t input_block_length, | 105 size_t input_block_length, |
| 107 const size_t output_buffer_length, | 106 const size_t output_buffer_length, |
| 108 Filter* filter, std::string* output) { | 107 Filter* filter, |
| 108 std::string* output) { |
| 109 CHECK_GT(input_block_length, 0u); | 109 CHECK_GT(input_block_length, 0u); |
| 110 Filter::FilterStatus status(Filter::FILTER_NEED_MORE_DATA); | 110 Filter::FilterStatus status(Filter::FILTER_NEED_MORE_DATA); |
| 111 size_t source_index = 0; | 111 size_t source_index = 0; |
| 112 scoped_ptr<char[]> output_buffer(new char[output_buffer_length]); | 112 scoped_ptr<char[]> output_buffer(new char[output_buffer_length]); |
| 113 size_t input_amount = std::min(input_block_length, | 113 size_t input_amount = std::min( |
| 114 static_cast<size_t>(filter->stream_buffer_size())); | 114 input_block_length, static_cast<size_t>(filter->stream_buffer_size())); |
| 115 | 115 |
| 116 do { | 116 do { |
| 117 int copy_amount = std::min(input_amount, source.size() - source_index); | 117 int copy_amount = std::min(input_amount, source.size() - source_index); |
| 118 if (copy_amount > 0 && status == Filter::FILTER_NEED_MORE_DATA) { | 118 if (copy_amount > 0 && status == Filter::FILTER_NEED_MORE_DATA) { |
| 119 memcpy(filter->stream_buffer()->data(), source.data() + source_index, | 119 memcpy(filter->stream_buffer()->data(), |
| 120 source.data() + source_index, |
| 120 copy_amount); | 121 copy_amount); |
| 121 filter->FlushStreamBuffer(copy_amount); | 122 filter->FlushStreamBuffer(copy_amount); |
| 122 source_index += copy_amount; | 123 source_index += copy_amount; |
| 123 } | 124 } |
| 124 int buffer_length = output_buffer_length; | 125 int buffer_length = output_buffer_length; |
| 125 status = filter->ReadData(output_buffer.get(), &buffer_length); | 126 status = filter->ReadData(output_buffer.get(), &buffer_length); |
| 126 output->append(output_buffer.get(), buffer_length); | 127 output->append(output_buffer.get(), buffer_length); |
| 127 if (status == Filter::FILTER_ERROR) | 128 if (status == Filter::FILTER_ERROR) |
| 128 return false; | 129 return false; |
| 129 // Callers assume that FILTER_OK with no output buffer means FILTER_DONE. | 130 // Callers assume that FILTER_OK with no output buffer means FILTER_DONE. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 150 | 151 |
| 151 TEST_F(SdchFilterTest, EmptyInputOk) { | 152 TEST_F(SdchFilterTest, EmptyInputOk) { |
| 152 std::vector<Filter::FilterType> filter_types; | 153 std::vector<Filter::FilterType> filter_types; |
| 153 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 154 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 154 char output_buffer[20]; | 155 char output_buffer[20]; |
| 155 MockFilterContext filter_context; | 156 MockFilterContext filter_context; |
| 156 std::string url_string("http://ignore.com"); | 157 std::string url_string("http://ignore.com"); |
| 157 filter_context.SetURL(GURL(url_string)); | 158 filter_context.SetURL(GURL(url_string)); |
| 158 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 159 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 159 | 160 |
| 160 | |
| 161 // With no input data, try to read output. | 161 // With no input data, try to read output. |
| 162 int output_bytes_or_buffer_size = sizeof(output_buffer); | 162 int output_bytes_or_buffer_size = sizeof(output_buffer); |
| 163 Filter::FilterStatus status = filter->ReadData(output_buffer, | 163 Filter::FilterStatus status = |
| 164 &output_bytes_or_buffer_size); | 164 filter->ReadData(output_buffer, &output_bytes_or_buffer_size); |
| 165 | 165 |
| 166 EXPECT_EQ(0, output_bytes_or_buffer_size); | 166 EXPECT_EQ(0, output_bytes_or_buffer_size); |
| 167 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); | 167 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); |
| 168 } | 168 } |
| 169 | 169 |
| 170 TEST_F(SdchFilterTest, PassThroughWhenTentative) { | 170 TEST_F(SdchFilterTest, PassThroughWhenTentative) { |
| 171 std::vector<Filter::FilterType> filter_types; | 171 std::vector<Filter::FilterType> filter_types; |
| 172 // Selective a tentative filter (which can fall back to pass through). | 172 // Selective a tentative filter (which can fall back to pass through). |
| 173 filter_types.push_back(Filter::FILTER_TYPE_GZIP_HELPING_SDCH); | 173 filter_types.push_back(Filter::FILTER_TYPE_GZIP_HELPING_SDCH); |
| 174 char output_buffer[20]; | 174 char output_buffer[20]; |
| 175 MockFilterContext filter_context; | 175 MockFilterContext filter_context; |
| 176 // Response code needs to be 200 to allow a pass through. | 176 // Response code needs to be 200 to allow a pass through. |
| 177 filter_context.SetResponseCode(200); | 177 filter_context.SetResponseCode(200); |
| 178 std::string url_string("http://ignore.com"); | 178 std::string url_string("http://ignore.com"); |
| 179 filter_context.SetURL(GURL(url_string)); | 179 filter_context.SetURL(GURL(url_string)); |
| 180 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 180 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 181 | 181 |
| 182 // Supply enough data to force a pass-through mode.. | 182 // Supply enough data to force a pass-through mode.. |
| 183 std::string non_gzip_content("not GZIPed data"); | 183 std::string non_gzip_content("not GZIPed data"); |
| 184 | 184 |
| 185 char* input_buffer = filter->stream_buffer()->data(); | 185 char* input_buffer = filter->stream_buffer()->data(); |
| 186 int input_buffer_size = filter->stream_buffer_size(); | 186 int input_buffer_size = filter->stream_buffer_size(); |
| 187 | 187 |
| 188 EXPECT_LT(static_cast<int>(non_gzip_content.size()), | 188 EXPECT_LT(static_cast<int>(non_gzip_content.size()), input_buffer_size); |
| 189 input_buffer_size); | 189 memcpy(input_buffer, non_gzip_content.data(), non_gzip_content.size()); |
| 190 memcpy(input_buffer, non_gzip_content.data(), | |
| 191 non_gzip_content.size()); | |
| 192 filter->FlushStreamBuffer(non_gzip_content.size()); | 190 filter->FlushStreamBuffer(non_gzip_content.size()); |
| 193 | 191 |
| 194 // Try to read output. | 192 // Try to read output. |
| 195 int output_bytes_or_buffer_size = sizeof(output_buffer); | 193 int output_bytes_or_buffer_size = sizeof(output_buffer); |
| 196 Filter::FilterStatus status = filter->ReadData(output_buffer, | 194 Filter::FilterStatus status = |
| 197 &output_bytes_or_buffer_size); | 195 filter->ReadData(output_buffer, &output_bytes_or_buffer_size); |
| 198 | 196 |
| 199 EXPECT_EQ(non_gzip_content.size(), | 197 EXPECT_EQ(non_gzip_content.size(), |
| 200 static_cast<size_t>(output_bytes_or_buffer_size)); | 198 static_cast<size_t>(output_bytes_or_buffer_size)); |
| 201 ASSERT_GT(sizeof(output_buffer), | 199 ASSERT_GT(sizeof(output_buffer), |
| 202 static_cast<size_t>(output_bytes_or_buffer_size)); | 200 static_cast<size_t>(output_bytes_or_buffer_size)); |
| 203 output_buffer[output_bytes_or_buffer_size] = '\0'; | 201 output_buffer[output_bytes_or_buffer_size] = '\0'; |
| 204 EXPECT_TRUE(non_gzip_content == output_buffer); | 202 EXPECT_TRUE(non_gzip_content == output_buffer); |
| 205 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); | 203 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); |
| 206 } | 204 } |
| 207 | 205 |
| 208 TEST_F(SdchFilterTest, RefreshBadReturnCode) { | 206 TEST_F(SdchFilterTest, RefreshBadReturnCode) { |
| 209 std::vector<Filter::FilterType> filter_types; | 207 std::vector<Filter::FilterType> filter_types; |
| 210 // Selective a tentative filter (which can fall back to pass through). | 208 // Selective a tentative filter (which can fall back to pass through). |
| 211 filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); | 209 filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); |
| 212 char output_buffer[20]; | 210 char output_buffer[20]; |
| 213 MockFilterContext filter_context; | 211 MockFilterContext filter_context; |
| 214 // Response code needs to be 200 to allow a pass through. | 212 // Response code needs to be 200 to allow a pass through. |
| 215 filter_context.SetResponseCode(403); | 213 filter_context.SetResponseCode(403); |
| 216 // Meta refresh will only appear for html content | 214 // Meta refresh will only appear for html content |
| 217 filter_context.SetMimeType("text/html"); | 215 filter_context.SetMimeType("text/html"); |
| 218 std::string url_string("http://ignore.com"); | 216 std::string url_string("http://ignore.com"); |
| 219 filter_context.SetURL(GURL(url_string)); | 217 filter_context.SetURL(GURL(url_string)); |
| 220 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 218 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 221 | 219 |
| 222 // Supply enough data to force a pass-through mode, which means we have | 220 // Supply enough data to force a pass-through mode, which means we have |
| 223 // provided more than 9 characters that can't be a dictionary hash. | 221 // provided more than 9 characters that can't be a dictionary hash. |
| 224 std::string non_sdch_content("This is not SDCH"); | 222 std::string non_sdch_content("This is not SDCH"); |
| 225 | 223 |
| 226 char* input_buffer = filter->stream_buffer()->data(); | 224 char* input_buffer = filter->stream_buffer()->data(); |
| 227 int input_buffer_size = filter->stream_buffer_size(); | 225 int input_buffer_size = filter->stream_buffer_size(); |
| 228 | 226 |
| 229 EXPECT_LT(static_cast<int>(non_sdch_content.size()), | 227 EXPECT_LT(static_cast<int>(non_sdch_content.size()), input_buffer_size); |
| 230 input_buffer_size); | 228 memcpy(input_buffer, non_sdch_content.data(), non_sdch_content.size()); |
| 231 memcpy(input_buffer, non_sdch_content.data(), | |
| 232 non_sdch_content.size()); | |
| 233 filter->FlushStreamBuffer(non_sdch_content.size()); | 229 filter->FlushStreamBuffer(non_sdch_content.size()); |
| 234 | 230 |
| 235 // Try to read output. | 231 // Try to read output. |
| 236 int output_bytes_or_buffer_size = sizeof(output_buffer); | 232 int output_bytes_or_buffer_size = sizeof(output_buffer); |
| 237 Filter::FilterStatus status = filter->ReadData(output_buffer, | 233 Filter::FilterStatus status = |
| 238 &output_bytes_or_buffer_size); | 234 filter->ReadData(output_buffer, &output_bytes_or_buffer_size); |
| 239 | 235 |
| 240 // We should have read a long and complicated meta-refresh request. | 236 // We should have read a long and complicated meta-refresh request. |
| 241 EXPECT_TRUE(sizeof(output_buffer) == output_bytes_or_buffer_size); | 237 EXPECT_TRUE(sizeof(output_buffer) == output_bytes_or_buffer_size); |
| 242 // Check at least the prefix of the return. | 238 // Check at least the prefix of the return. |
| 243 EXPECT_EQ(0, strncmp(output_buffer, | 239 EXPECT_EQ(0, |
| 244 "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\"></head>", | 240 strncmp(output_buffer, |
| 245 sizeof(output_buffer))); | 241 "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\"></head>", |
| 242 sizeof(output_buffer))); |
| 246 EXPECT_EQ(Filter::FILTER_OK, status); | 243 EXPECT_EQ(Filter::FILTER_OK, status); |
| 247 } | 244 } |
| 248 | 245 |
| 249 TEST_F(SdchFilterTest, ErrorOnBadReturnCode) { | 246 TEST_F(SdchFilterTest, ErrorOnBadReturnCode) { |
| 250 std::vector<Filter::FilterType> filter_types; | 247 std::vector<Filter::FilterType> filter_types; |
| 251 // Selective a tentative filter (which can fall back to pass through). | 248 // Selective a tentative filter (which can fall back to pass through). |
| 252 filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); | 249 filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); |
| 253 char output_buffer[20]; | 250 char output_buffer[20]; |
| 254 MockFilterContext filter_context; | 251 MockFilterContext filter_context; |
| 255 // Response code needs to be 200 to allow a pass through. | 252 // Response code needs to be 200 to allow a pass through. |
| 256 filter_context.SetResponseCode(403); | 253 filter_context.SetResponseCode(403); |
| 257 // Meta refresh will only appear for html content, so set to something else | 254 // Meta refresh will only appear for html content, so set to something else |
| 258 // to induce an error (we can't meta refresh). | 255 // to induce an error (we can't meta refresh). |
| 259 filter_context.SetMimeType("anything"); | 256 filter_context.SetMimeType("anything"); |
| 260 std::string url_string("http://ignore.com"); | 257 std::string url_string("http://ignore.com"); |
| 261 filter_context.SetURL(GURL(url_string)); | 258 filter_context.SetURL(GURL(url_string)); |
| 262 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 259 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 263 | 260 |
| 264 // Supply enough data to force a pass-through mode, which means we have | 261 // Supply enough data to force a pass-through mode, which means we have |
| 265 // provided more than 9 characters that can't be a dictionary hash. | 262 // provided more than 9 characters that can't be a dictionary hash. |
| 266 std::string non_sdch_content("This is not SDCH"); | 263 std::string non_sdch_content("This is not SDCH"); |
| 267 | 264 |
| 268 char* input_buffer = filter->stream_buffer()->data(); | 265 char* input_buffer = filter->stream_buffer()->data(); |
| 269 int input_buffer_size = filter->stream_buffer_size(); | 266 int input_buffer_size = filter->stream_buffer_size(); |
| 270 | 267 |
| 271 EXPECT_LT(static_cast<int>(non_sdch_content.size()), | 268 EXPECT_LT(static_cast<int>(non_sdch_content.size()), input_buffer_size); |
| 272 input_buffer_size); | 269 memcpy(input_buffer, non_sdch_content.data(), non_sdch_content.size()); |
| 273 memcpy(input_buffer, non_sdch_content.data(), | |
| 274 non_sdch_content.size()); | |
| 275 filter->FlushStreamBuffer(non_sdch_content.size()); | 270 filter->FlushStreamBuffer(non_sdch_content.size()); |
| 276 | 271 |
| 277 // Try to read output. | 272 // Try to read output. |
| 278 int output_bytes_or_buffer_size = sizeof(output_buffer); | 273 int output_bytes_or_buffer_size = sizeof(output_buffer); |
| 279 Filter::FilterStatus status = filter->ReadData(output_buffer, | 274 Filter::FilterStatus status = |
| 280 &output_bytes_or_buffer_size); | 275 filter->ReadData(output_buffer, &output_bytes_or_buffer_size); |
| 281 | 276 |
| 282 EXPECT_EQ(0, output_bytes_or_buffer_size); | 277 EXPECT_EQ(0, output_bytes_or_buffer_size); |
| 283 EXPECT_EQ(Filter::FILTER_ERROR, status); | 278 EXPECT_EQ(Filter::FILTER_ERROR, status); |
| 284 } | 279 } |
| 285 | 280 |
| 286 TEST_F(SdchFilterTest, ErrorOnBadReturnCodeWithHtml) { | 281 TEST_F(SdchFilterTest, ErrorOnBadReturnCodeWithHtml) { |
| 287 std::vector<Filter::FilterType> filter_types; | 282 std::vector<Filter::FilterType> filter_types; |
| 288 // Selective a tentative filter (which can fall back to pass through). | 283 // Selective a tentative filter (which can fall back to pass through). |
| 289 filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); | 284 filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE); |
| 290 char output_buffer[20]; | 285 char output_buffer[20]; |
| 291 MockFilterContext filter_context; | 286 MockFilterContext filter_context; |
| 292 // Response code needs to be 200 to allow a pass through. | 287 // Response code needs to be 200 to allow a pass through. |
| 293 filter_context.SetResponseCode(403); | 288 filter_context.SetResponseCode(403); |
| 294 // Meta refresh will only appear for html content | 289 // Meta refresh will only appear for html content |
| 295 filter_context.SetMimeType("text/html"); | 290 filter_context.SetMimeType("text/html"); |
| 296 std::string url_string("http://ignore.com"); | 291 std::string url_string("http://ignore.com"); |
| 297 filter_context.SetURL(GURL(url_string)); | 292 filter_context.SetURL(GURL(url_string)); |
| 298 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 293 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 299 | 294 |
| 300 // Supply enough data to force a pass-through mode, which means we have | 295 // Supply enough data to force a pass-through mode, which means we have |
| 301 // provided more than 9 characters that can't be a dictionary hash. | 296 // provided more than 9 characters that can't be a dictionary hash. |
| 302 std::string non_sdch_content("This is not SDCH"); | 297 std::string non_sdch_content("This is not SDCH"); |
| 303 | 298 |
| 304 char* input_buffer = filter->stream_buffer()->data(); | 299 char* input_buffer = filter->stream_buffer()->data(); |
| 305 int input_buffer_size = filter->stream_buffer_size(); | 300 int input_buffer_size = filter->stream_buffer_size(); |
| 306 | 301 |
| 307 EXPECT_LT(static_cast<int>(non_sdch_content.size()), | 302 EXPECT_LT(static_cast<int>(non_sdch_content.size()), input_buffer_size); |
| 308 input_buffer_size); | 303 memcpy(input_buffer, non_sdch_content.data(), non_sdch_content.size()); |
| 309 memcpy(input_buffer, non_sdch_content.data(), | |
| 310 non_sdch_content.size()); | |
| 311 filter->FlushStreamBuffer(non_sdch_content.size()); | 304 filter->FlushStreamBuffer(non_sdch_content.size()); |
| 312 | 305 |
| 313 // Try to read output. | 306 // Try to read output. |
| 314 int output_bytes_or_buffer_size = sizeof(output_buffer); | 307 int output_bytes_or_buffer_size = sizeof(output_buffer); |
| 315 Filter::FilterStatus status = filter->ReadData(output_buffer, | 308 Filter::FilterStatus status = |
| 316 &output_bytes_or_buffer_size); | 309 filter->ReadData(output_buffer, &output_bytes_or_buffer_size); |
| 317 | 310 |
| 318 // We should have read a long and complicated meta-refresh request. | 311 // We should have read a long and complicated meta-refresh request. |
| 319 EXPECT_EQ(sizeof(output_buffer), | 312 EXPECT_EQ(sizeof(output_buffer), |
| 320 static_cast<size_t>(output_bytes_or_buffer_size)); | 313 static_cast<size_t>(output_bytes_or_buffer_size)); |
| 321 // Check at least the prefix of the return. | 314 // Check at least the prefix of the return. |
| 322 EXPECT_EQ(0, strncmp(output_buffer, | 315 EXPECT_EQ(0, |
| 323 "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\"></head>", | 316 strncmp(output_buffer, |
| 324 sizeof(output_buffer))); | 317 "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\"></head>", |
| 318 sizeof(output_buffer))); |
| 325 EXPECT_EQ(Filter::FILTER_OK, status); | 319 EXPECT_EQ(Filter::FILTER_OK, status); |
| 326 } | 320 } |
| 327 | 321 |
| 328 TEST_F(SdchFilterTest, BasicBadDictionary) { | 322 TEST_F(SdchFilterTest, BasicBadDictionary) { |
| 329 std::vector<Filter::FilterType> filter_types; | 323 std::vector<Filter::FilterType> filter_types; |
| 330 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 324 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 331 char output_buffer[20]; | 325 char output_buffer[20]; |
| 332 MockFilterContext filter_context; | 326 MockFilterContext filter_context; |
| 333 std::string url_string("http://ignore.com"); | 327 std::string url_string("http://ignore.com"); |
| 334 filter_context.SetURL(GURL(url_string)); | 328 filter_context.SetURL(GURL(url_string)); |
| 335 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 329 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 336 | 330 |
| 337 // Supply bogus data (which doesn't yet specify a full dictionary hash). | 331 // Supply bogus data (which doesn't yet specify a full dictionary hash). |
| 338 // Dictionary hash is 8 characters followed by a null. | 332 // Dictionary hash is 8 characters followed by a null. |
| 339 std::string dictionary_hash_prefix("123"); | 333 std::string dictionary_hash_prefix("123"); |
| 340 | 334 |
| 341 char* input_buffer = filter->stream_buffer()->data(); | 335 char* input_buffer = filter->stream_buffer()->data(); |
| 342 int input_buffer_size = filter->stream_buffer_size(); | 336 int input_buffer_size = filter->stream_buffer_size(); |
| 343 | 337 |
| 344 EXPECT_LT(static_cast<int>(dictionary_hash_prefix.size()), | 338 EXPECT_LT(static_cast<int>(dictionary_hash_prefix.size()), input_buffer_size); |
| 345 input_buffer_size); | 339 memcpy(input_buffer, |
| 346 memcpy(input_buffer, dictionary_hash_prefix.data(), | 340 dictionary_hash_prefix.data(), |
| 347 dictionary_hash_prefix.size()); | 341 dictionary_hash_prefix.size()); |
| 348 filter->FlushStreamBuffer(dictionary_hash_prefix.size()); | 342 filter->FlushStreamBuffer(dictionary_hash_prefix.size()); |
| 349 | 343 |
| 350 // With less than a dictionary specifier, try to read output. | 344 // With less than a dictionary specifier, try to read output. |
| 351 int output_bytes_or_buffer_size = sizeof(output_buffer); | 345 int output_bytes_or_buffer_size = sizeof(output_buffer); |
| 352 Filter::FilterStatus status = filter->ReadData(output_buffer, | 346 Filter::FilterStatus status = |
| 353 &output_bytes_or_buffer_size); | 347 filter->ReadData(output_buffer, &output_bytes_or_buffer_size); |
| 354 | 348 |
| 355 EXPECT_EQ(0, output_bytes_or_buffer_size); | 349 EXPECT_EQ(0, output_bytes_or_buffer_size); |
| 356 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); | 350 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status); |
| 357 | 351 |
| 358 // Provide enough data to complete *a* hash, but it is bogus, and not in our | 352 // Provide enough data to complete *a* hash, but it is bogus, and not in our |
| 359 // list of dictionaries, so the filter should error out immediately. | 353 // list of dictionaries, so the filter should error out immediately. |
| 360 std::string dictionary_hash_postfix("4abcd\0", 6); | 354 std::string dictionary_hash_postfix("4abcd\0", 6); |
| 361 | 355 |
| 362 CHECK_LT(dictionary_hash_postfix.size(), | 356 CHECK_LT(dictionary_hash_postfix.size(), |
| 363 static_cast<size_t>(input_buffer_size)); | 357 static_cast<size_t>(input_buffer_size)); |
| 364 memcpy(input_buffer, dictionary_hash_postfix.data(), | 358 memcpy(input_buffer, |
| 359 dictionary_hash_postfix.data(), |
| 365 dictionary_hash_postfix.size()); | 360 dictionary_hash_postfix.size()); |
| 366 filter->FlushStreamBuffer(dictionary_hash_postfix.size()); | 361 filter->FlushStreamBuffer(dictionary_hash_postfix.size()); |
| 367 | 362 |
| 368 // With a non-existant dictionary specifier, try to read output. | 363 // With a non-existant dictionary specifier, try to read output. |
| 369 output_bytes_or_buffer_size = sizeof(output_buffer); | 364 output_bytes_or_buffer_size = sizeof(output_buffer); |
| 370 status = filter->ReadData(output_buffer, &output_bytes_or_buffer_size); | 365 status = filter->ReadData(output_buffer, &output_bytes_or_buffer_size); |
| 371 | 366 |
| 372 EXPECT_EQ(0, output_bytes_or_buffer_size); | 367 EXPECT_EQ(0, output_bytes_or_buffer_size); |
| 373 EXPECT_EQ(Filter::FILTER_ERROR, status); | 368 EXPECT_EQ(Filter::FILTER_ERROR, status); |
| 374 | 369 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 410 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 416 | 411 |
| 417 MockFilterContext filter_context; | 412 MockFilterContext filter_context; |
| 418 filter_context.SetURL(url); | 413 filter_context.SetURL(url); |
| 419 | 414 |
| 420 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 415 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 421 | 416 |
| 422 size_t feed_block_size = 100; | 417 size_t feed_block_size = 100; |
| 423 size_t output_block_size = 100; | 418 size_t output_block_size = 100; |
| 424 std::string output; | 419 std::string output; |
| 425 EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size, | 420 EXPECT_TRUE(FilterTestData( |
| 426 filter.get(), &output)); | 421 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 427 EXPECT_EQ(output, expanded_); | 422 EXPECT_EQ(output, expanded_); |
| 428 | 423 |
| 429 // Decode with really small buffers (size 1) to check for edge effects. | 424 // Decode with really small buffers (size 1) to check for edge effects. |
| 430 filter.reset(Filter::Factory(filter_types, filter_context)); | 425 filter.reset(Filter::Factory(filter_types, filter_context)); |
| 431 | 426 |
| 432 feed_block_size = 1; | 427 feed_block_size = 1; |
| 433 output_block_size = 1; | 428 output_block_size = 1; |
| 434 output.clear(); | 429 output.clear(); |
| 435 EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size, | 430 EXPECT_TRUE(FilterTestData( |
| 436 filter.get(), &output)); | 431 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 437 EXPECT_EQ(output, expanded_); | 432 EXPECT_EQ(output, expanded_); |
| 438 } | 433 } |
| 439 | 434 |
| 440 TEST_F(SdchFilterTest, NoDecodeHttps) { | 435 TEST_F(SdchFilterTest, NoDecodeHttps) { |
| 441 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 436 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 442 const std::string kSampleDomain = "sdchtest.com"; | 437 const std::string kSampleDomain = "sdchtest.com"; |
| 443 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 438 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 444 | 439 |
| 445 std::string url_string = "http://" + kSampleDomain; | 440 std::string url_string = "http://" + kSampleDomain; |
| 446 | 441 |
| 447 GURL url(url_string); | 442 GURL url(url_string); |
| 448 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 443 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 449 | 444 |
| 450 std::string compressed(NewSdchCompressedData(dictionary)); | 445 std::string compressed(NewSdchCompressedData(dictionary)); |
| 451 | 446 |
| 452 std::vector<Filter::FilterType> filter_types; | 447 std::vector<Filter::FilterType> filter_types; |
| 453 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 448 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 454 | 449 |
| 455 MockFilterContext filter_context; | 450 MockFilterContext filter_context; |
| 456 filter_context.SetURL(GURL("https://" + kSampleDomain)); | 451 filter_context.SetURL(GURL("https://" + kSampleDomain)); |
| 457 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 452 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 458 | 453 |
| 459 const size_t feed_block_size(100); | 454 const size_t feed_block_size(100); |
| 460 const size_t output_block_size(100); | 455 const size_t output_block_size(100); |
| 461 std::string output; | 456 std::string output; |
| 462 | 457 |
| 463 EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, | 458 EXPECT_FALSE(FilterTestData( |
| 464 filter.get(), &output)); | 459 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 465 } | 460 } |
| 466 | 461 |
| 467 // Current failsafe TODO/hack refuses to decode any content that doesn't use | 462 // Current failsafe TODO/hack refuses to decode any content that doesn't use |
| 468 // http as the scheme (see use of DICTIONARY_SELECTED_FOR_NON_HTTP). | 463 // http as the scheme (see use of DICTIONARY_SELECTED_FOR_NON_HTTP). |
| 469 // The following tests this blockage. Note that blacklisting results, so we | 464 // The following tests this blockage. Note that blacklisting results, so we |
| 470 // we need separate tests for each of these. | 465 // we need separate tests for each of these. |
| 471 TEST_F(SdchFilterTest, NoDecodeFtp) { | 466 TEST_F(SdchFilterTest, NoDecodeFtp) { |
| 472 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 467 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 473 const std::string kSampleDomain = "sdchtest.com"; | 468 const std::string kSampleDomain = "sdchtest.com"; |
| 474 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 469 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 475 | 470 |
| 476 std::string url_string = "http://" + kSampleDomain; | 471 std::string url_string = "http://" + kSampleDomain; |
| 477 | 472 |
| 478 GURL url(url_string); | 473 GURL url(url_string); |
| 479 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 474 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 480 | 475 |
| 481 std::string compressed(NewSdchCompressedData(dictionary)); | 476 std::string compressed(NewSdchCompressedData(dictionary)); |
| 482 | 477 |
| 483 std::vector<Filter::FilterType> filter_types; | 478 std::vector<Filter::FilterType> filter_types; |
| 484 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 479 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 485 | 480 |
| 486 MockFilterContext filter_context; | 481 MockFilterContext filter_context; |
| 487 filter_context.SetURL(GURL("ftp://" + kSampleDomain)); | 482 filter_context.SetURL(GURL("ftp://" + kSampleDomain)); |
| 488 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 483 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 489 | 484 |
| 490 const size_t feed_block_size(100); | 485 const size_t feed_block_size(100); |
| 491 const size_t output_block_size(100); | 486 const size_t output_block_size(100); |
| 492 std::string output; | 487 std::string output; |
| 493 | 488 |
| 494 EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, | 489 EXPECT_FALSE(FilterTestData( |
| 495 filter.get(), &output)); | 490 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 496 } | 491 } |
| 497 | 492 |
| 498 TEST_F(SdchFilterTest, NoDecodeFileColon) { | 493 TEST_F(SdchFilterTest, NoDecodeFileColon) { |
| 499 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 494 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 500 const std::string kSampleDomain = "sdchtest.com"; | 495 const std::string kSampleDomain = "sdchtest.com"; |
| 501 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 496 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 502 | 497 |
| 503 std::string url_string = "http://" + kSampleDomain; | 498 std::string url_string = "http://" + kSampleDomain; |
| 504 | 499 |
| 505 GURL url(url_string); | 500 GURL url(url_string); |
| 506 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 501 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 507 | 502 |
| 508 std::string compressed(NewSdchCompressedData(dictionary)); | 503 std::string compressed(NewSdchCompressedData(dictionary)); |
| 509 | 504 |
| 510 std::vector<Filter::FilterType> filter_types; | 505 std::vector<Filter::FilterType> filter_types; |
| 511 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 506 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 512 | 507 |
| 513 MockFilterContext filter_context; | 508 MockFilterContext filter_context; |
| 514 filter_context.SetURL(GURL("file://" + kSampleDomain)); | 509 filter_context.SetURL(GURL("file://" + kSampleDomain)); |
| 515 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 510 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 516 | 511 |
| 517 const size_t feed_block_size(100); | 512 const size_t feed_block_size(100); |
| 518 const size_t output_block_size(100); | 513 const size_t output_block_size(100); |
| 519 std::string output; | 514 std::string output; |
| 520 | 515 |
| 521 EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, | 516 EXPECT_FALSE(FilterTestData( |
| 522 filter.get(), &output)); | 517 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 523 } | 518 } |
| 524 | 519 |
| 525 TEST_F(SdchFilterTest, NoDecodeAboutColon) { | 520 TEST_F(SdchFilterTest, NoDecodeAboutColon) { |
| 526 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 521 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 527 const std::string kSampleDomain = "sdchtest.com"; | 522 const std::string kSampleDomain = "sdchtest.com"; |
| 528 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 523 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 529 | 524 |
| 530 std::string url_string = "http://" + kSampleDomain; | 525 std::string url_string = "http://" + kSampleDomain; |
| 531 | 526 |
| 532 GURL url(url_string); | 527 GURL url(url_string); |
| 533 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 528 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 534 | 529 |
| 535 std::string compressed(NewSdchCompressedData(dictionary)); | 530 std::string compressed(NewSdchCompressedData(dictionary)); |
| 536 | 531 |
| 537 std::vector<Filter::FilterType> filter_types; | 532 std::vector<Filter::FilterType> filter_types; |
| 538 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 533 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 539 | 534 |
| 540 MockFilterContext filter_context; | 535 MockFilterContext filter_context; |
| 541 filter_context.SetURL(GURL("about://" + kSampleDomain)); | 536 filter_context.SetURL(GURL("about://" + kSampleDomain)); |
| 542 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 537 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 543 | 538 |
| 544 const size_t feed_block_size(100); | 539 const size_t feed_block_size(100); |
| 545 const size_t output_block_size(100); | 540 const size_t output_block_size(100); |
| 546 std::string output; | 541 std::string output; |
| 547 | 542 |
| 548 EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, | 543 EXPECT_FALSE(FilterTestData( |
| 549 filter.get(), &output)); | 544 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 550 } | 545 } |
| 551 | 546 |
| 552 TEST_F(SdchFilterTest, NoDecodeJavaScript) { | 547 TEST_F(SdchFilterTest, NoDecodeJavaScript) { |
| 553 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 548 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 554 const std::string kSampleDomain = "sdchtest.com"; | 549 const std::string kSampleDomain = "sdchtest.com"; |
| 555 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 550 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 556 | 551 |
| 557 std::string url_string = "http://" + kSampleDomain; | 552 std::string url_string = "http://" + kSampleDomain; |
| 558 | 553 |
| 559 GURL url(url_string); | 554 GURL url(url_string); |
| 560 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 555 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 561 | 556 |
| 562 std::string compressed(NewSdchCompressedData(dictionary)); | 557 std::string compressed(NewSdchCompressedData(dictionary)); |
| 563 | 558 |
| 564 std::vector<Filter::FilterType> filter_types; | 559 std::vector<Filter::FilterType> filter_types; |
| 565 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 560 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 566 | 561 |
| 567 MockFilterContext filter_context; | 562 MockFilterContext filter_context; |
| 568 filter_context.SetURL(GURL("javascript://" + kSampleDomain)); | 563 filter_context.SetURL(GURL("javascript://" + kSampleDomain)); |
| 569 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 564 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 570 | 565 |
| 571 const size_t feed_block_size(100); | 566 const size_t feed_block_size(100); |
| 572 const size_t output_block_size(100); | 567 const size_t output_block_size(100); |
| 573 std::string output; | 568 std::string output; |
| 574 | 569 |
| 575 EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, | 570 EXPECT_FALSE(FilterTestData( |
| 576 filter.get(), &output)); | 571 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 577 } | 572 } |
| 578 | 573 |
| 579 TEST_F(SdchFilterTest, CanStillDecodeHttp) { | 574 TEST_F(SdchFilterTest, CanStillDecodeHttp) { |
| 580 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 575 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 581 const std::string kSampleDomain = "sdchtest.com"; | 576 const std::string kSampleDomain = "sdchtest.com"; |
| 582 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 577 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 583 | 578 |
| 584 std::string url_string = "http://" + kSampleDomain; | 579 std::string url_string = "http://" + kSampleDomain; |
| 585 | 580 |
| 586 GURL url(url_string); | 581 GURL url(url_string); |
| 587 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 582 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 588 | 583 |
| 589 std::string compressed(NewSdchCompressedData(dictionary)); | 584 std::string compressed(NewSdchCompressedData(dictionary)); |
| 590 | 585 |
| 591 std::vector<Filter::FilterType> filter_types; | 586 std::vector<Filter::FilterType> filter_types; |
| 592 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 587 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 593 | 588 |
| 594 MockFilterContext filter_context; | 589 MockFilterContext filter_context; |
| 595 filter_context.SetURL(GURL("http://" + kSampleDomain)); | 590 filter_context.SetURL(GURL("http://" + kSampleDomain)); |
| 596 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 591 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 597 | 592 |
| 598 const size_t feed_block_size(100); | 593 const size_t feed_block_size(100); |
| 599 const size_t output_block_size(100); | 594 const size_t output_block_size(100); |
| 600 std::string output; | 595 std::string output; |
| 601 | 596 |
| 602 EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size, | 597 EXPECT_TRUE(FilterTestData( |
| 603 filter.get(), &output)); | 598 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 604 } | 599 } |
| 605 | 600 |
| 606 TEST_F(SdchFilterTest, CrossDomainDictionaryUse) { | 601 TEST_F(SdchFilterTest, CrossDomainDictionaryUse) { |
| 607 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 602 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 608 const std::string kSampleDomain = "sdchtest.com"; | 603 const std::string kSampleDomain = "sdchtest.com"; |
| 609 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 604 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 610 | 605 |
| 611 std::string url_string = "http://" + kSampleDomain; | 606 std::string url_string = "http://" + kSampleDomain; |
| 612 | 607 |
| 613 GURL url(url_string); | 608 GURL url(url_string); |
| 614 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 609 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 615 | 610 |
| 616 std::string compressed(NewSdchCompressedData(dictionary)); | 611 std::string compressed(NewSdchCompressedData(dictionary)); |
| 617 | 612 |
| 618 std::vector<Filter::FilterType> filter_types; | 613 std::vector<Filter::FilterType> filter_types; |
| 619 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 614 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 620 | 615 |
| 621 // Decode with content arriving from the "wrong" domain. | 616 // Decode with content arriving from the "wrong" domain. |
| 622 // This tests SdchManager::CanSet(). | 617 // This tests SdchManager::CanSet(). |
| 623 MockFilterContext filter_context; | 618 MockFilterContext filter_context; |
| 624 GURL wrong_domain_url("http://www.wrongdomain.com"); | 619 GURL wrong_domain_url("http://www.wrongdomain.com"); |
| 625 filter_context.SetURL(wrong_domain_url); | 620 filter_context.SetURL(wrong_domain_url); |
| 626 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 621 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 627 | 622 |
| 628 size_t feed_block_size = 100; | 623 size_t feed_block_size = 100; |
| 629 size_t output_block_size = 100; | 624 size_t output_block_size = 100; |
| 630 std::string output; | 625 std::string output; |
| 631 EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size, | 626 EXPECT_FALSE(FilterTestData( |
| 632 filter.get(), &output)); | 627 compressed, feed_block_size, output_block_size, filter.get(), &output)); |
| 633 EXPECT_EQ(output.size(), 0u); // No output written. | 628 EXPECT_EQ(output.size(), 0u); // No output written. |
| 634 | 629 |
| 635 EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); | 630 EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); |
| 636 EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(wrong_domain_url)); | 631 EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(wrong_domain_url)); |
| 637 SdchManager::ClearBlacklistings(); | 632 SdchManager::ClearBlacklistings(); |
| 638 EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(wrong_domain_url)); | 633 EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(wrong_domain_url)); |
| 639 } | 634 } |
| 640 | 635 |
| 641 TEST_F(SdchFilterTest, DictionaryPathValidation) { | 636 TEST_F(SdchFilterTest, DictionaryPathValidation) { |
| 642 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 637 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| (...skipping 18 matching lines...) Expand all Loading... |
| 661 | 656 |
| 662 // Test decode the path data, arriving from a valid path. | 657 // Test decode the path data, arriving from a valid path. |
| 663 MockFilterContext filter_context; | 658 MockFilterContext filter_context; |
| 664 filter_context.SetURL(GURL(url_string + path)); | 659 filter_context.SetURL(GURL(url_string + path)); |
| 665 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 660 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 666 | 661 |
| 667 size_t feed_block_size = 100; | 662 size_t feed_block_size = 100; |
| 668 size_t output_block_size = 100; | 663 size_t output_block_size = 100; |
| 669 std::string output; | 664 std::string output; |
| 670 | 665 |
| 671 EXPECT_TRUE(FilterTestData(compressed_for_path, feed_block_size, | 666 EXPECT_TRUE(FilterTestData(compressed_for_path, |
| 672 output_block_size, filter.get(), &output)); | 667 feed_block_size, |
| 668 output_block_size, |
| 669 filter.get(), |
| 670 &output)); |
| 673 EXPECT_EQ(output, expanded_); | 671 EXPECT_EQ(output, expanded_); |
| 674 | 672 |
| 675 // Test decode the path data, arriving from a invalid path. | 673 // Test decode the path data, arriving from a invalid path. |
| 676 filter_context.SetURL(GURL(url_string)); | 674 filter_context.SetURL(GURL(url_string)); |
| 677 filter.reset(Filter::Factory(filter_types, filter_context)); | 675 filter.reset(Filter::Factory(filter_types, filter_context)); |
| 678 | 676 |
| 679 feed_block_size = 100; | 677 feed_block_size = 100; |
| 680 output_block_size = 100; | 678 output_block_size = 100; |
| 681 output.clear(); | 679 output.clear(); |
| 682 EXPECT_FALSE(FilterTestData(compressed_for_path, feed_block_size, | 680 EXPECT_FALSE(FilterTestData(compressed_for_path, |
| 683 output_block_size, filter.get(), &output)); | 681 feed_block_size, |
| 682 output_block_size, |
| 683 filter.get(), |
| 684 &output)); |
| 684 EXPECT_EQ(output.size(), 0u); // No output written. | 685 EXPECT_EQ(output.size(), 0u); // No output written. |
| 685 | 686 |
| 686 EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); | 687 EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); |
| 687 SdchManager::ClearBlacklistings(); | 688 SdchManager::ClearBlacklistings(); |
| 688 EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); | 689 EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); |
| 689 } | 690 } |
| 690 | 691 |
| 691 TEST_F(SdchFilterTest, DictionaryPortValidation) { | 692 TEST_F(SdchFilterTest, DictionaryPortValidation) { |
| 692 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 693 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 693 const std::string kSampleDomain = "sdchtest.com"; | 694 const std::string kSampleDomain = "sdchtest.com"; |
| 694 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 695 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 695 | 696 |
| 696 std::string url_string = "http://" + kSampleDomain; | 697 std::string url_string = "http://" + kSampleDomain; |
| 697 | 698 |
| 698 GURL url(url_string); | 699 GURL url(url_string); |
| 699 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 700 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 700 | 701 |
| 701 | |
| 702 // Create a dictionary with a port restriction, by prefixing old dictionary. | 702 // Create a dictionary with a port restriction, by prefixing old dictionary. |
| 703 const std::string port("502"); | 703 const std::string port("502"); |
| 704 std::string dictionary_with_port("Port: " + port + "\n"); | 704 std::string dictionary_with_port("Port: " + port + "\n"); |
| 705 dictionary_with_port.append("Port: 80\n"); // Add default port. | 705 dictionary_with_port.append("Port: 80\n"); // Add default port. |
| 706 dictionary_with_port.append(dictionary); | 706 dictionary_with_port.append(dictionary); |
| 707 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_with_port, | 707 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary_with_port, |
| 708 GURL(url_string + ":" + port))); | 708 GURL(url_string + ":" + port))); |
| 709 | 709 |
| 710 std::string compressed_for_port(NewSdchCompressedData(dictionary_with_port)); | 710 std::string compressed_for_port(NewSdchCompressedData(dictionary_with_port)); |
| 711 | 711 |
| 712 std::vector<Filter::FilterType> filter_types; | 712 std::vector<Filter::FilterType> filter_types; |
| 713 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 713 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 714 | 714 |
| 715 // Test decode the port data, arriving from a valid port. | 715 // Test decode the port data, arriving from a valid port. |
| 716 MockFilterContext filter_context; | 716 MockFilterContext filter_context; |
| 717 filter_context.SetURL(GURL(url_string + ":" + port)); | 717 filter_context.SetURL(GURL(url_string + ":" + port)); |
| 718 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 718 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 719 | 719 |
| 720 size_t feed_block_size = 100; | 720 size_t feed_block_size = 100; |
| 721 size_t output_block_size = 100; | 721 size_t output_block_size = 100; |
| 722 std::string output; | 722 std::string output; |
| 723 EXPECT_TRUE(FilterTestData(compressed_for_port, feed_block_size, | 723 EXPECT_TRUE(FilterTestData(compressed_for_port, |
| 724 output_block_size, filter.get(), &output)); | 724 feed_block_size, |
| 725 output_block_size, |
| 726 filter.get(), |
| 727 &output)); |
| 725 EXPECT_EQ(output, expanded_); | 728 EXPECT_EQ(output, expanded_); |
| 726 | 729 |
| 727 // Test decode the port data, arriving from a valid (default) port. | 730 // Test decode the port data, arriving from a valid (default) port. |
| 728 filter_context.SetURL(GURL(url_string)); // Default port. | 731 filter_context.SetURL(GURL(url_string)); // Default port. |
| 729 filter.reset(Filter::Factory(filter_types, filter_context)); | 732 filter.reset(Filter::Factory(filter_types, filter_context)); |
| 730 | 733 |
| 731 feed_block_size = 100; | 734 feed_block_size = 100; |
| 732 output_block_size = 100; | 735 output_block_size = 100; |
| 733 output.clear(); | 736 output.clear(); |
| 734 EXPECT_TRUE(FilterTestData(compressed_for_port, feed_block_size, | 737 EXPECT_TRUE(FilterTestData(compressed_for_port, |
| 735 output_block_size, filter.get(), &output)); | 738 feed_block_size, |
| 739 output_block_size, |
| 740 filter.get(), |
| 741 &output)); |
| 736 EXPECT_EQ(output, expanded_); | 742 EXPECT_EQ(output, expanded_); |
| 737 | 743 |
| 738 // Test decode the port data, arriving from a invalid port. | 744 // Test decode the port data, arriving from a invalid port. |
| 739 filter_context.SetURL(GURL(url_string + ":" + port + "1")); | 745 filter_context.SetURL(GURL(url_string + ":" + port + "1")); |
| 740 filter.reset(Filter::Factory(filter_types, filter_context)); | 746 filter.reset(Filter::Factory(filter_types, filter_context)); |
| 741 | 747 |
| 742 feed_block_size = 100; | 748 feed_block_size = 100; |
| 743 output_block_size = 100; | 749 output_block_size = 100; |
| 744 output.clear(); | 750 output.clear(); |
| 745 EXPECT_FALSE(FilterTestData(compressed_for_port, feed_block_size, | 751 EXPECT_FALSE(FilterTestData(compressed_for_port, |
| 746 output_block_size, filter.get(), &output)); | 752 feed_block_size, |
| 753 output_block_size, |
| 754 filter.get(), |
| 755 &output)); |
| 747 EXPECT_EQ(output.size(), 0u); // No output written. | 756 EXPECT_EQ(output.size(), 0u); // No output written. |
| 748 | 757 |
| 749 EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); | 758 EXPECT_FALSE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); |
| 750 SdchManager::ClearBlacklistings(); | 759 SdchManager::ClearBlacklistings(); |
| 751 EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); | 760 EXPECT_TRUE(SdchManager::Global()->IsInSupportedDomain(GURL(url_string))); |
| 752 } | 761 } |
| 753 | 762 |
| 754 //------------------------------------------------------------------------------ | 763 //------------------------------------------------------------------------------ |
| 755 // Helper function to perform gzip compression of data. | 764 // Helper function to perform gzip compression of data. |
| 756 | 765 |
| 757 static std::string gzip_compress(const std::string &input) { | 766 static std::string gzip_compress(const std::string& input) { |
| 758 z_stream zlib_stream; | 767 z_stream zlib_stream; |
| 759 memset(&zlib_stream, 0, sizeof(zlib_stream)); | 768 memset(&zlib_stream, 0, sizeof(zlib_stream)); |
| 760 int code; | 769 int code; |
| 761 | 770 |
| 762 // Initialize zlib | 771 // Initialize zlib |
| 763 code = deflateInit2(&zlib_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, | 772 code = deflateInit2(&zlib_stream, |
| 773 Z_DEFAULT_COMPRESSION, |
| 774 Z_DEFLATED, |
| 764 -MAX_WBITS, | 775 -MAX_WBITS, |
| 765 8, // DEF_MEM_LEVEL | 776 8, // DEF_MEM_LEVEL |
| 766 Z_DEFAULT_STRATEGY); | 777 Z_DEFAULT_STRATEGY); |
| 767 | 778 |
| 768 CHECK_EQ(Z_OK, code); | 779 CHECK_EQ(Z_OK, code); |
| 769 | 780 |
| 770 // Fill in zlib control block | 781 // Fill in zlib control block |
| 771 zlib_stream.next_in = bit_cast<Bytef*>(input.data()); | 782 zlib_stream.next_in = bit_cast<Bytef*>(input.data()); |
| 772 zlib_stream.avail_in = input.size(); | 783 zlib_stream.avail_in = input.size(); |
| 773 | 784 |
| 774 // Assume we can compress into similar buffer (add 100 bytes to be sure). | 785 // Assume we can compress into similar buffer (add 100 bytes to be sure). |
| 775 size_t gzip_compressed_length = zlib_stream.avail_in + 100; | 786 size_t gzip_compressed_length = zlib_stream.avail_in + 100; |
| 776 scoped_ptr<char[]> gzip_compressed(new char[gzip_compressed_length]); | 787 scoped_ptr<char[]> gzip_compressed(new char[gzip_compressed_length]); |
| 777 zlib_stream.next_out = bit_cast<Bytef*>(gzip_compressed.get()); | 788 zlib_stream.next_out = bit_cast<Bytef*>(gzip_compressed.get()); |
| 778 zlib_stream.avail_out = gzip_compressed_length; | 789 zlib_stream.avail_out = gzip_compressed_length; |
| 779 | 790 |
| 780 // The GZIP header (see RFC 1952): | 791 // The GZIP header (see RFC 1952): |
| 781 // +---+---+---+---+---+---+---+---+---+---+ | 792 // +---+---+---+---+---+---+---+---+---+---+ |
| 782 // |ID1|ID2|CM |FLG| MTIME |XFL|OS | | 793 // |ID1|ID2|CM |FLG| MTIME |XFL|OS | |
| 783 // +---+---+---+---+---+---+---+---+---+---+ | 794 // +---+---+---+---+---+---+---+---+---+---+ |
| 784 // ID1 \037 | 795 // ID1 \037 |
| 785 // ID2 \213 | 796 // ID2 \213 |
| 786 // CM \010 (compression method == DEFLATE) | 797 // CM \010 (compression method == DEFLATE) |
| 787 // FLG \000 (special flags that we do not support) | 798 // FLG \000 (special flags that we do not support) |
| 788 // MTIME Unix format modification time (0 means not available) | 799 // MTIME Unix format modification time (0 means not available) |
| 789 // XFL 2-4? DEFLATE flags | 800 // XFL 2-4? DEFLATE flags |
| 790 // OS ???? Operating system indicator (255 means unknown) | 801 // OS ???? Operating system indicator (255 means unknown) |
| 791 // | 802 // |
| 792 // Header value we generate: | 803 // Header value we generate: |
| 793 const char kGZipHeader[] = { '\037', '\213', '\010', '\000', '\000', | 804 const char kGZipHeader[] = {'\037', '\213', '\010', '\000', '\000', |
| 794 '\000', '\000', '\000', '\002', '\377' }; | 805 '\000', '\000', '\000', '\002', '\377'}; |
| 795 CHECK_GT(zlib_stream.avail_out, sizeof(kGZipHeader)); | 806 CHECK_GT(zlib_stream.avail_out, sizeof(kGZipHeader)); |
| 796 memcpy(zlib_stream.next_out, kGZipHeader, sizeof(kGZipHeader)); | 807 memcpy(zlib_stream.next_out, kGZipHeader, sizeof(kGZipHeader)); |
| 797 zlib_stream.next_out += sizeof(kGZipHeader); | 808 zlib_stream.next_out += sizeof(kGZipHeader); |
| 798 zlib_stream.avail_out -= sizeof(kGZipHeader); | 809 zlib_stream.avail_out -= sizeof(kGZipHeader); |
| 799 | 810 |
| 800 // Do deflate | 811 // Do deflate |
| 801 code = deflate(&zlib_stream, Z_FINISH); | 812 code = deflate(&zlib_stream, Z_FINISH); |
| 802 gzip_compressed_length -= zlib_stream.avail_out; | 813 gzip_compressed_length -= zlib_stream.avail_out; |
| 803 std::string compressed(gzip_compressed.get(), gzip_compressed_length); | 814 std::string compressed(gzip_compressed.get(), gzip_compressed_length); |
| 804 deflateEnd(&zlib_stream); | 815 deflateEnd(&zlib_stream); |
| 805 return compressed; | 816 return compressed; |
| 806 } | 817 } |
| 807 | 818 |
| 808 //------------------------------------------------------------------------------ | 819 //------------------------------------------------------------------------------ |
| 809 | 820 |
| 810 class SdchFilterChainingTest { | 821 class SdchFilterChainingTest { |
| 811 public: | 822 public: |
| 812 static Filter* Factory(const std::vector<Filter::FilterType>& types, | 823 static Filter* Factory(const std::vector<Filter::FilterType>& types, |
| 813 const FilterContext& context, int size) { | 824 const FilterContext& context, |
| 825 int size) { |
| 814 return Filter::FactoryForTests(types, context, size); | 826 return Filter::FactoryForTests(types, context, size); |
| 815 } | 827 } |
| 816 }; | 828 }; |
| 817 | 829 |
| 818 // Test that filters can be cascaded (chained) so that the output of one filter | 830 // Test that filters can be cascaded (chained) so that the output of one filter |
| 819 // is processed by the next one. This is most critical for SDCH, which is | 831 // is processed by the next one. This is most critical for SDCH, which is |
| 820 // routinely followed by gzip (during encoding). The filter we'll test for will | 832 // routinely followed by gzip (during encoding). The filter we'll test for will |
| 821 // do the gzip decoding first, and then decode the SDCH content. | 833 // do the gzip decoding first, and then decode the SDCH content. |
| 822 TEST_F(SdchFilterTest, FilterChaining) { | 834 TEST_F(SdchFilterTest, FilterChaining) { |
| 823 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 835 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 839 filter_types.push_back(Filter::FILTER_TYPE_SDCH); | 851 filter_types.push_back(Filter::FILTER_TYPE_SDCH); |
| 840 filter_types.push_back(Filter::FILTER_TYPE_GZIP); | 852 filter_types.push_back(Filter::FILTER_TYPE_GZIP); |
| 841 | 853 |
| 842 // First try with a large buffer (larger than test input, or compressed data). | 854 // First try with a large buffer (larger than test input, or compressed data). |
| 843 const size_t kLargeInputBufferSize(1000); // Used internally in filters. | 855 const size_t kLargeInputBufferSize(1000); // Used internally in filters. |
| 844 CHECK_GT(kLargeInputBufferSize, gzip_compressed_sdch.size()); | 856 CHECK_GT(kLargeInputBufferSize, gzip_compressed_sdch.size()); |
| 845 CHECK_GT(kLargeInputBufferSize, sdch_compressed.size()); | 857 CHECK_GT(kLargeInputBufferSize, sdch_compressed.size()); |
| 846 CHECK_GT(kLargeInputBufferSize, expanded_.size()); | 858 CHECK_GT(kLargeInputBufferSize, expanded_.size()); |
| 847 MockFilterContext filter_context; | 859 MockFilterContext filter_context; |
| 848 filter_context.SetURL(url); | 860 filter_context.SetURL(url); |
| 849 scoped_ptr<Filter> filter( | 861 scoped_ptr<Filter> filter(SdchFilterChainingTest::Factory( |
| 850 SdchFilterChainingTest::Factory(filter_types, filter_context, | 862 filter_types, filter_context, kLargeInputBufferSize)); |
| 851 kLargeInputBufferSize)); | |
| 852 EXPECT_EQ(static_cast<int>(kLargeInputBufferSize), | 863 EXPECT_EQ(static_cast<int>(kLargeInputBufferSize), |
| 853 filter->stream_buffer_size()); | 864 filter->stream_buffer_size()); |
| 854 | 865 |
| 855 // Verify that chained filter is waiting for data. | 866 // Verify that chained filter is waiting for data. |
| 856 char tiny_output_buffer[10]; | 867 char tiny_output_buffer[10]; |
| 857 int tiny_output_size = sizeof(tiny_output_buffer); | 868 int tiny_output_size = sizeof(tiny_output_buffer); |
| 858 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, | 869 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, |
| 859 filter->ReadData(tiny_output_buffer, &tiny_output_size)); | 870 filter->ReadData(tiny_output_buffer, &tiny_output_size)); |
| 860 | 871 |
| 861 // Make chain process all data. | 872 // Make chain process all data. |
| 862 size_t feed_block_size = kLargeInputBufferSize; | 873 size_t feed_block_size = kLargeInputBufferSize; |
| 863 size_t output_block_size = kLargeInputBufferSize; | 874 size_t output_block_size = kLargeInputBufferSize; |
| 864 std::string output; | 875 std::string output; |
| 865 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 876 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 866 output_block_size, filter.get(), &output)); | 877 feed_block_size, |
| 878 output_block_size, |
| 879 filter.get(), |
| 880 &output)); |
| 867 EXPECT_EQ(output, expanded_); | 881 EXPECT_EQ(output, expanded_); |
| 868 | 882 |
| 869 // Next try with a mid-sized internal buffer size. | 883 // Next try with a mid-sized internal buffer size. |
| 870 const size_t kMidSizedInputBufferSize(100); | 884 const size_t kMidSizedInputBufferSize(100); |
| 871 // Buffer should be big enough to swallow whole gzip content. | 885 // Buffer should be big enough to swallow whole gzip content. |
| 872 CHECK_GT(kMidSizedInputBufferSize, gzip_compressed_sdch.size()); | 886 CHECK_GT(kMidSizedInputBufferSize, gzip_compressed_sdch.size()); |
| 873 // Buffer should be small enough that entire SDCH content can't fit. | 887 // Buffer should be small enough that entire SDCH content can't fit. |
| 874 // We'll go even further, and force the chain to flush the buffer between the | 888 // We'll go even further, and force the chain to flush the buffer between the |
| 875 // two filters more than once (that is why we multiply by 2). | 889 // two filters more than once (that is why we multiply by 2). |
| 876 CHECK_LT(kMidSizedInputBufferSize * 2, sdch_compressed.size()); | 890 CHECK_LT(kMidSizedInputBufferSize * 2, sdch_compressed.size()); |
| 877 filter_context.SetURL(url); | 891 filter_context.SetURL(url); |
| 878 filter.reset( | 892 filter.reset(SdchFilterChainingTest::Factory( |
| 879 SdchFilterChainingTest::Factory(filter_types, filter_context, | 893 filter_types, filter_context, kMidSizedInputBufferSize)); |
| 880 kMidSizedInputBufferSize)); | |
| 881 EXPECT_EQ(static_cast<int>(kMidSizedInputBufferSize), | 894 EXPECT_EQ(static_cast<int>(kMidSizedInputBufferSize), |
| 882 filter->stream_buffer_size()); | 895 filter->stream_buffer_size()); |
| 883 | 896 |
| 884 feed_block_size = kMidSizedInputBufferSize; | 897 feed_block_size = kMidSizedInputBufferSize; |
| 885 output_block_size = kMidSizedInputBufferSize; | 898 output_block_size = kMidSizedInputBufferSize; |
| 886 output.clear(); | 899 output.clear(); |
| 887 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 900 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 888 output_block_size, filter.get(), &output)); | 901 feed_block_size, |
| 902 output_block_size, |
| 903 filter.get(), |
| 904 &output)); |
| 889 EXPECT_EQ(output, expanded_); | 905 EXPECT_EQ(output, expanded_); |
| 890 | 906 |
| 891 // Next try with a tiny input and output buffer to cover edge effects. | 907 // Next try with a tiny input and output buffer to cover edge effects. |
| 892 filter.reset(SdchFilterChainingTest::Factory(filter_types, filter_context, | 908 filter.reset(SdchFilterChainingTest::Factory( |
| 893 kLargeInputBufferSize)); | 909 filter_types, filter_context, kLargeInputBufferSize)); |
| 894 EXPECT_EQ(static_cast<int>(kLargeInputBufferSize), | 910 EXPECT_EQ(static_cast<int>(kLargeInputBufferSize), |
| 895 filter->stream_buffer_size()); | 911 filter->stream_buffer_size()); |
| 896 | 912 |
| 897 feed_block_size = 1; | 913 feed_block_size = 1; |
| 898 output_block_size = 1; | 914 output_block_size = 1; |
| 899 output.clear(); | 915 output.clear(); |
| 900 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 916 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 901 output_block_size, filter.get(), &output)); | 917 feed_block_size, |
| 918 output_block_size, |
| 919 filter.get(), |
| 920 &output)); |
| 902 EXPECT_EQ(output, expanded_); | 921 EXPECT_EQ(output, expanded_); |
| 903 } | 922 } |
| 904 | 923 |
| 905 TEST_F(SdchFilterTest, DefaultGzipIfSdch) { | 924 TEST_F(SdchFilterTest, DefaultGzipIfSdch) { |
| 906 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 925 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 907 const std::string kSampleDomain = "sdchtest.com"; | 926 const std::string kSampleDomain = "sdchtest.com"; |
| 908 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 927 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 909 | 928 |
| 910 std::string url_string = "http://" + kSampleDomain; | 929 std::string url_string = "http://" + kSampleDomain; |
| 911 | 930 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 927 filter_context.SetSdchResponse(true); | 946 filter_context.SetSdchResponse(true); |
| 928 Filter::FixupEncodingTypes(filter_context, &filter_types); | 947 Filter::FixupEncodingTypes(filter_context, &filter_types); |
| 929 ASSERT_EQ(filter_types.size(), 2u); | 948 ASSERT_EQ(filter_types.size(), 2u); |
| 930 EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH); | 949 EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH); |
| 931 EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); | 950 EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); |
| 932 | 951 |
| 933 // First try with a large buffer (larger than test input, or compressed data). | 952 // First try with a large buffer (larger than test input, or compressed data). |
| 934 filter_context.SetURL(url); | 953 filter_context.SetURL(url); |
| 935 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 954 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 936 | 955 |
| 937 | |
| 938 // Verify that chained filter is waiting for data. | 956 // Verify that chained filter is waiting for data. |
| 939 char tiny_output_buffer[10]; | 957 char tiny_output_buffer[10]; |
| 940 int tiny_output_size = sizeof(tiny_output_buffer); | 958 int tiny_output_size = sizeof(tiny_output_buffer); |
| 941 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, | 959 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, |
| 942 filter->ReadData(tiny_output_buffer, &tiny_output_size)); | 960 filter->ReadData(tiny_output_buffer, &tiny_output_size)); |
| 943 | 961 |
| 944 size_t feed_block_size = 100; | 962 size_t feed_block_size = 100; |
| 945 size_t output_block_size = 100; | 963 size_t output_block_size = 100; |
| 946 std::string output; | 964 std::string output; |
| 947 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 965 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 948 output_block_size, filter.get(), &output)); | 966 feed_block_size, |
| 967 output_block_size, |
| 968 filter.get(), |
| 969 &output)); |
| 949 EXPECT_EQ(output, expanded_); | 970 EXPECT_EQ(output, expanded_); |
| 950 | 971 |
| 951 // Next try with a tiny buffer to cover edge effects. | 972 // Next try with a tiny buffer to cover edge effects. |
| 952 filter.reset(Filter::Factory(filter_types, filter_context)); | 973 filter.reset(Filter::Factory(filter_types, filter_context)); |
| 953 | 974 |
| 954 feed_block_size = 1; | 975 feed_block_size = 1; |
| 955 output_block_size = 1; | 976 output_block_size = 1; |
| 956 output.clear(); | 977 output.clear(); |
| 957 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 978 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 958 output_block_size, filter.get(), &output)); | 979 feed_block_size, |
| 980 output_block_size, |
| 981 filter.get(), |
| 982 &output)); |
| 959 EXPECT_EQ(output, expanded_); | 983 EXPECT_EQ(output, expanded_); |
| 960 } | 984 } |
| 961 | 985 |
| 962 TEST_F(SdchFilterTest, AcceptGzipSdchIfGzip) { | 986 TEST_F(SdchFilterTest, AcceptGzipSdchIfGzip) { |
| 963 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 987 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 964 const std::string kSampleDomain = "sdchtest.com"; | 988 const std::string kSampleDomain = "sdchtest.com"; |
| 965 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 989 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 966 | 990 |
| 967 std::string url_string = "http://" + kSampleDomain; | 991 std::string url_string = "http://" + kSampleDomain; |
| 968 | 992 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 987 Filter::FixupEncodingTypes(filter_context, &filter_types); | 1011 Filter::FixupEncodingTypes(filter_context, &filter_types); |
| 988 ASSERT_EQ(filter_types.size(), 3u); | 1012 ASSERT_EQ(filter_types.size(), 3u); |
| 989 EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); | 1013 EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); |
| 990 EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); | 1014 EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); |
| 991 EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP); | 1015 EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP); |
| 992 | 1016 |
| 993 // First try with a large buffer (larger than test input, or compressed data). | 1017 // First try with a large buffer (larger than test input, or compressed data). |
| 994 filter_context.SetURL(url); | 1018 filter_context.SetURL(url); |
| 995 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 1019 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 996 | 1020 |
| 997 | |
| 998 // Verify that chained filter is waiting for data. | 1021 // Verify that chained filter is waiting for data. |
| 999 char tiny_output_buffer[10]; | 1022 char tiny_output_buffer[10]; |
| 1000 int tiny_output_size = sizeof(tiny_output_buffer); | 1023 int tiny_output_size = sizeof(tiny_output_buffer); |
| 1001 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, | 1024 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, |
| 1002 filter->ReadData(tiny_output_buffer, &tiny_output_size)); | 1025 filter->ReadData(tiny_output_buffer, &tiny_output_size)); |
| 1003 | 1026 |
| 1004 size_t feed_block_size = 100; | 1027 size_t feed_block_size = 100; |
| 1005 size_t output_block_size = 100; | 1028 size_t output_block_size = 100; |
| 1006 std::string output; | 1029 std::string output; |
| 1007 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 1030 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 1008 output_block_size, filter.get(), &output)); | 1031 feed_block_size, |
| 1032 output_block_size, |
| 1033 filter.get(), |
| 1034 &output)); |
| 1009 EXPECT_EQ(output, expanded_); | 1035 EXPECT_EQ(output, expanded_); |
| 1010 | 1036 |
| 1011 // Next try with a tiny buffer to cover edge effects. | 1037 // Next try with a tiny buffer to cover edge effects. |
| 1012 filter.reset(Filter::Factory(filter_types, filter_context)); | 1038 filter.reset(Filter::Factory(filter_types, filter_context)); |
| 1013 | 1039 |
| 1014 feed_block_size = 1; | 1040 feed_block_size = 1; |
| 1015 output_block_size = 1; | 1041 output_block_size = 1; |
| 1016 output.clear(); | 1042 output.clear(); |
| 1017 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 1043 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 1018 output_block_size, filter.get(), &output)); | 1044 feed_block_size, |
| 1045 output_block_size, |
| 1046 filter.get(), |
| 1047 &output)); |
| 1019 EXPECT_EQ(output, expanded_); | 1048 EXPECT_EQ(output, expanded_); |
| 1020 } | 1049 } |
| 1021 | 1050 |
| 1022 TEST_F(SdchFilterTest, DefaultSdchGzipIfEmpty) { | 1051 TEST_F(SdchFilterTest, DefaultSdchGzipIfEmpty) { |
| 1023 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 1052 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 1024 const std::string kSampleDomain = "sdchtest.com"; | 1053 const std::string kSampleDomain = "sdchtest.com"; |
| 1025 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 1054 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 1026 | 1055 |
| 1027 std::string url_string = "http://" + kSampleDomain; | 1056 std::string url_string = "http://" + kSampleDomain; |
| 1028 | 1057 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1044 filter_context.SetSdchResponse(true); | 1073 filter_context.SetSdchResponse(true); |
| 1045 Filter::FixupEncodingTypes(filter_context, &filter_types); | 1074 Filter::FixupEncodingTypes(filter_context, &filter_types); |
| 1046 ASSERT_EQ(filter_types.size(), 2u); | 1075 ASSERT_EQ(filter_types.size(), 2u); |
| 1047 EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); | 1076 EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); |
| 1048 EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); | 1077 EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); |
| 1049 | 1078 |
| 1050 // First try with a large buffer (larger than test input, or compressed data). | 1079 // First try with a large buffer (larger than test input, or compressed data). |
| 1051 filter_context.SetURL(url); | 1080 filter_context.SetURL(url); |
| 1052 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 1081 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 1053 | 1082 |
| 1054 | |
| 1055 // Verify that chained filter is waiting for data. | 1083 // Verify that chained filter is waiting for data. |
| 1056 char tiny_output_buffer[10]; | 1084 char tiny_output_buffer[10]; |
| 1057 int tiny_output_size = sizeof(tiny_output_buffer); | 1085 int tiny_output_size = sizeof(tiny_output_buffer); |
| 1058 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, | 1086 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, |
| 1059 filter->ReadData(tiny_output_buffer, &tiny_output_size)); | 1087 filter->ReadData(tiny_output_buffer, &tiny_output_size)); |
| 1060 | 1088 |
| 1061 size_t feed_block_size = 100; | 1089 size_t feed_block_size = 100; |
| 1062 size_t output_block_size = 100; | 1090 size_t output_block_size = 100; |
| 1063 std::string output; | 1091 std::string output; |
| 1064 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 1092 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 1065 output_block_size, filter.get(), &output)); | 1093 feed_block_size, |
| 1094 output_block_size, |
| 1095 filter.get(), |
| 1096 &output)); |
| 1066 EXPECT_EQ(output, expanded_); | 1097 EXPECT_EQ(output, expanded_); |
| 1067 | 1098 |
| 1068 // Next try with a tiny buffer to cover edge effects. | 1099 // Next try with a tiny buffer to cover edge effects. |
| 1069 filter.reset(Filter::Factory(filter_types, filter_context)); | 1100 filter.reset(Filter::Factory(filter_types, filter_context)); |
| 1070 | 1101 |
| 1071 feed_block_size = 1; | 1102 feed_block_size = 1; |
| 1072 output_block_size = 1; | 1103 output_block_size = 1; |
| 1073 output.clear(); | 1104 output.clear(); |
| 1074 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size, | 1105 EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, |
| 1075 output_block_size, filter.get(), &output)); | 1106 feed_block_size, |
| 1107 output_block_size, |
| 1108 filter.get(), |
| 1109 &output)); |
| 1076 EXPECT_EQ(output, expanded_); | 1110 EXPECT_EQ(output, expanded_); |
| 1077 } | 1111 } |
| 1078 | 1112 |
| 1079 TEST_F(SdchFilterTest, AcceptGzipGzipSdchIfGzip) { | 1113 TEST_F(SdchFilterTest, AcceptGzipGzipSdchIfGzip) { |
| 1080 // Construct a valid SDCH dictionary from a VCDIFF dictionary. | 1114 // Construct a valid SDCH dictionary from a VCDIFF dictionary. |
| 1081 const std::string kSampleDomain = "sdchtest.com"; | 1115 const std::string kSampleDomain = "sdchtest.com"; |
| 1082 std::string dictionary(NewSdchDictionary(kSampleDomain)); | 1116 std::string dictionary(NewSdchDictionary(kSampleDomain)); |
| 1083 | 1117 |
| 1084 std::string url_string = "http://" + kSampleDomain; | 1118 std::string url_string = "http://" + kSampleDomain; |
| 1085 | 1119 |
| 1086 GURL url(url_string); | 1120 GURL url(url_string); |
| 1087 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); | 1121 EXPECT_TRUE(sdch_manager_->AddSdchDictionary(dictionary, url)); |
| 1088 | 1122 |
| 1089 std::string sdch_compressed(NewSdchCompressedData(dictionary)); | 1123 std::string sdch_compressed(NewSdchCompressedData(dictionary)); |
| 1090 | 1124 |
| 1091 // Vodaphone (UK) Mobile Broadband provides double gzipped sdch with a content | 1125 // Vodaphone (UK) Mobile Broadband provides double gzipped sdch with a content |
| 1092 // encoding of merely gzip (apparently, only listing the extra level of | 1126 // encoding of merely gzip (apparently, only listing the extra level of |
| 1093 // wrapper compression they added, but discarding the actual content encoding. | 1127 // wrapper compression they added, but discarding the actual content encoding. |
| 1094 // Use Gzip to double compress the sdch sdch_compressed data. | 1128 // Use Gzip to double compress the sdch sdch_compressed data. |
| 1095 std::string double_gzip_compressed_sdch = gzip_compress(gzip_compress( | 1129 std::string double_gzip_compressed_sdch = |
| 1096 sdch_compressed)); | 1130 gzip_compress(gzip_compress(sdch_compressed)); |
| 1097 | 1131 |
| 1098 // Only claim to have gzip content, but really use the double gzipped sdch | 1132 // Only claim to have gzip content, but really use the double gzipped sdch |
| 1099 // content. | 1133 // content. |
| 1100 // System should automatically add the missing (optional) sdch, gzip decoders. | 1134 // System should automatically add the missing (optional) sdch, gzip decoders. |
| 1101 std::vector<Filter::FilterType> filter_types; | 1135 std::vector<Filter::FilterType> filter_types; |
| 1102 filter_types.push_back(Filter::FILTER_TYPE_GZIP); | 1136 filter_types.push_back(Filter::FILTER_TYPE_GZIP); |
| 1103 | 1137 |
| 1104 MockFilterContext filter_context; | 1138 MockFilterContext filter_context; |
| 1105 filter_context.SetMimeType("anything/mime"); | 1139 filter_context.SetMimeType("anything/mime"); |
| 1106 filter_context.SetSdchResponse(true); | 1140 filter_context.SetSdchResponse(true); |
| 1107 Filter::FixupEncodingTypes(filter_context, &filter_types); | 1141 Filter::FixupEncodingTypes(filter_context, &filter_types); |
| 1108 ASSERT_EQ(filter_types.size(), 3u); | 1142 ASSERT_EQ(filter_types.size(), 3u); |
| 1109 EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); | 1143 EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE); |
| 1110 EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); | 1144 EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH); |
| 1111 EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP); | 1145 EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP); |
| 1112 | 1146 |
| 1113 // First try with a large buffer (larger than test input, or compressed data). | 1147 // First try with a large buffer (larger than test input, or compressed data). |
| 1114 filter_context.SetURL(url); | 1148 filter_context.SetURL(url); |
| 1115 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); | 1149 scoped_ptr<Filter> filter(Filter::Factory(filter_types, filter_context)); |
| 1116 | 1150 |
| 1117 // Verify that chained filter is waiting for data. | 1151 // Verify that chained filter is waiting for data. |
| 1118 char tiny_output_buffer[10]; | 1152 char tiny_output_buffer[10]; |
| 1119 int tiny_output_size = sizeof(tiny_output_buffer); | 1153 int tiny_output_size = sizeof(tiny_output_buffer); |
| 1120 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, | 1154 EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, |
| 1121 filter->ReadData(tiny_output_buffer, &tiny_output_size)); | 1155 filter->ReadData(tiny_output_buffer, &tiny_output_size)); |
| 1122 | 1156 |
| 1123 size_t feed_block_size = 100; | 1157 size_t feed_block_size = 100; |
| 1124 size_t output_block_size = 100; | 1158 size_t output_block_size = 100; |
| 1125 std::string output; | 1159 std::string output; |
| 1126 EXPECT_TRUE(FilterTestData(double_gzip_compressed_sdch, feed_block_size, | 1160 EXPECT_TRUE(FilterTestData(double_gzip_compressed_sdch, |
| 1127 output_block_size, filter.get(), &output)); | 1161 feed_block_size, |
| 1162 output_block_size, |
| 1163 filter.get(), |
| 1164 &output)); |
| 1128 EXPECT_EQ(output, expanded_); | 1165 EXPECT_EQ(output, expanded_); |
| 1129 | 1166 |
| 1130 // Next try with a tiny buffer to cover edge effects. | 1167 // Next try with a tiny buffer to cover edge effects. |
| 1131 filter.reset(Filter::Factory(filter_types, filter_context)); | 1168 filter.reset(Filter::Factory(filter_types, filter_context)); |
| 1132 | 1169 |
| 1133 feed_block_size = 1; | 1170 feed_block_size = 1; |
| 1134 output_block_size = 1; | 1171 output_block_size = 1; |
| 1135 output.clear(); | 1172 output.clear(); |
| 1136 EXPECT_TRUE(FilterTestData(double_gzip_compressed_sdch, feed_block_size, | 1173 EXPECT_TRUE(FilterTestData(double_gzip_compressed_sdch, |
| 1137 output_block_size, filter.get(), &output)); | 1174 feed_block_size, |
| 1175 output_block_size, |
| 1176 filter.get(), |
| 1177 &output)); |
| 1138 EXPECT_EQ(output, expanded_); | 1178 EXPECT_EQ(output, expanded_); |
| 1139 } | 1179 } |
| 1140 | 1180 |
| 1141 } // namespace net | 1181 } // namespace net |
| OLD | NEW |