15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h>
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/filter/mock_filter_context.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/filter/sdch_filter.h"
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "net/url_request/url_request_context.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_http_job.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/zlib/zlib.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Provide sample data and compression results with a sample VCDIFF dictionary.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note an SDCH dictionary has extra meta-data before the VCDIFF dictionary.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kTestVcdiffDictionary[] = "DictionaryFor"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "SdchCompression1SdchCompression2SdchCompression3SdchCompression\n";
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pre-compression test data.  Note that we pad with a lot of highly gzip
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// compressible content to help to exercise the chaining pipeline.  That is why
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// there are a PILE of zeros at the start and end.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This will ensure that gzip compressed data can be fed to the chain in one
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// gulp, but (with careful selection of intermediate buffers) that it takes
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// several sdch buffers worth of data to satisfy the sdch filter.  See detailed
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CHECK() calls in FilterChaining test for specifics.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kTestData[] = "0000000000000000000000000000000000000000000000"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "0000000000000000000000000000TestData "
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "SdchCompression1SdchCompression2SdchCompression3SdchCompression"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "00000000000000000000000000000000000000000000000000000000000000000000000000"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "000000000000000000000000000000000000000\n";
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note SDCH compressed data will include a reference to the SDCH dictionary.
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kSdchCompressedTestData[] =
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "\326\303\304\0\0\001M\0\201S\202\004\0\201E\006\001"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "00000000000000000000000000000000000000000000000000000000000000000000000000"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "TestData 00000000000000000000000000000000000000000000000000000000000000000"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "000000000000000000000000000000000000000000000000\n\001S\023\077\001r\r";
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SdchFilterTest : public testing::Test {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SdchFilterTest()
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : test_vcdiff_dictionary_(kTestVcdiffDictionary,
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              sizeof(kTestVcdiffDictionary) - 1),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      vcdiff_compressed_data_(kSdchCompressedTestData,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              sizeof(kSdchCompressedTestData) - 1),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expanded_(kTestData, sizeof(kTestData) - 1),
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      sdch_manager_(new SdchManager),
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      filter_context_(new MockFilterContext) {
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    URLRequestContext* url_request_context =
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        filter_context_->GetModifiableURLRequestContext();
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    url_request_context->set_sdch_manager(sdch_manager_.get());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Attempt to add a dictionary to the manager; returns whether or not
671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // the attempt succeeded.
681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  bool AddSdchDictionary(const std::string& dictionary_text,
691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         const GURL& gurl) {
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string list;
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sdch_manager_->GetAvailDictionaryList(gurl, &list);
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sdch_manager_->AddSdchDictionary(dictionary_text, gurl);
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string list2;
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    sdch_manager_->GetAvailDictionaryList(gurl, &list2);
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // The list of hashes should change iff the addition succeeds.
771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return (list != list2);
781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  MockFilterContext* filter_context() { return filter_context_.get(); }
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::string NewSdchCompressedData(const std::string dictionary) {
831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string client_hash;
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string server_hash;
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SdchManager::GenerateHash(dictionary, &client_hash, &server_hash);
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Build compressed data that refers to our dictionary.
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    std::string compressed(server_hash);
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    compressed.append("\0", 1);
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    compressed.append(vcdiff_compressed_data_);
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return compressed;
921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string test_vcdiff_dictionary_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string vcdiff_compressed_data_;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string expanded_;  // Desired final, decompressed data.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<SdchManager> sdch_manager_;
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<MockFilterContext> filter_context_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, Hashing) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string client_hash, server_hash;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary("test contents");
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SdchManager::GenerateHash(dictionary, &client_hash, &server_hash);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(client_hash, "lMQBjS3P");
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(server_hash, "MyciMVll");
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Provide a generic helper function for trying to filter data.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function repeatedly calls the filter to process data, until the entire
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// source is consumed.  The return value from the filter is appended to output.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This allows us to vary input and output block sizes in order to test for edge
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// effects (boundary effects?) during the filtering process.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function provides data to the filter in blocks of no-more-than the
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// specified input_block_length.  It allows the filter to fill no more than
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// output_buffer_length in any one call to proccess (a.k.a., Read) data, and
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// concatenates all these little output blocks into the singular output string.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool FilterTestData(const std::string& source,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           size_t input_block_length,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const size_t output_buffer_length,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           Filter* filter, std::string* output) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GT(input_block_length, 0u);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FilterStatus status(Filter::FILTER_NEED_MORE_DATA);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t source_index = 0;
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<char[]> output_buffer(new char[output_buffer_length]);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t input_amount = std::min(input_block_length,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<size_t>(filter->stream_buffer_size()));
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int copy_amount = std::min(input_amount, source.size() - source_index);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (copy_amount > 0 && status == Filter::FILTER_NEED_MORE_DATA) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memcpy(filter->stream_buffer()->data(), source.data() + source_index,
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             copy_amount);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      filter->FlushStreamBuffer(copy_amount);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source_index += copy_amount;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int buffer_length = output_buffer_length;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status = filter->ReadData(output_buffer.get(), &buffer_length);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->append(output_buffer.get(), buffer_length);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (status == Filter::FILTER_ERROR)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Callers assume that FILTER_OK with no output buffer means FILTER_DONE.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (Filter::FILTER_OK == status && 0 == buffer_length)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (copy_amount == 0 && buffer_length == 0)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (1);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static std::string NewSdchDictionary(const std::string& domain) {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!domain.empty()) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary.append("Domain: ");
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary.append(domain);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    dictionary.append("\n");
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary.append("\n");
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary.append(kTestVcdiffDictionary, sizeof(kTestVcdiffDictionary) - 1);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dictionary;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, EmptyInputOk) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char output_buffer[20];
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string("http://ignore.com");
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // With no input data, try to read output.
18003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  int output_bytes_or_buffer_size = sizeof(output_buffer);
18103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  Filter::FilterStatus status = filter->ReadData(output_buffer,
18203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                                 &output_bytes_or_buffer_size);
18303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
18403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(0, output_bytes_or_buffer_size);
18503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status);
18603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
18703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
18803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Make sure that the filter context has everything that might be
18903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// nuked from it during URLRequest teardown before the SdchFilter
19003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// destructor.
19103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)TEST_F(SdchFilterTest, SparseContextOk) {
19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
19303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  char output_buffer[20];
19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  std::string url_string("http://ignore.com");
19603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));
19703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // With no input data, try to read output.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int output_bytes_or_buffer_size = sizeof(output_buffer);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FilterStatus status = filter->ReadData(output_buffer,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &output_bytes_or_buffer_size);
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, output_bytes_or_buffer_size);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status);
20603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
20703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Partially tear down context.  Anything that goes through request()
20803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // without checking it for null in the URLRequestJob::HttpFilterContext
20903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // implementation is suspect.  Everything that does check it for null should
21003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // return null.  This is to test for incorrectly relying on filter_context()
21103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // from the SdchFilter destructor.
21203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  filter_context()->NukeUnstableInterfaces();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, PassThroughWhenTentative) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Selective a tentative filter (which can fall back to pass through).
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_GZIP_HELPING_SDCH);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char output_buffer[20];
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Response code needs to be 200 to allow a pass through.
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetResponseCode(200);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string("http://ignore.com");
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Supply enough data to force a pass-through mode..
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string non_gzip_content("not GZIPed data");
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* input_buffer = filter->stream_buffer()->data();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int input_buffer_size = filter->stream_buffer_size();
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(static_cast<int>(non_gzip_content.size()),
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            input_buffer_size);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(input_buffer, non_gzip_content.data(),
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         non_gzip_content.size());
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter->FlushStreamBuffer(non_gzip_content.size());
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to read output.
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int output_bytes_or_buffer_size = sizeof(output_buffer);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FilterStatus status = filter->ReadData(output_buffer,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &output_bytes_or_buffer_size);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(non_gzip_content.size(),
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<size_t>(output_bytes_or_buffer_size));
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_GT(sizeof(output_buffer),
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              static_cast<size_t>(output_bytes_or_buffer_size));
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_buffer[output_bytes_or_buffer_size] = '\0';
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(non_gzip_content == output_buffer);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, RefreshBadReturnCode) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Selective a tentative filter (which can fall back to pass through).
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char output_buffer[20];
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Response code needs to be 200 to allow a pass through.
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetResponseCode(403);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Meta refresh will only appear for html content
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetMimeType("text/html");
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string("http://ignore.com");
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Supply enough data to force a pass-through mode, which means we have
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // provided more than 9 characters that can't be a dictionary hash.
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string non_sdch_content("This is not SDCH");
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* input_buffer = filter->stream_buffer()->data();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int input_buffer_size = filter->stream_buffer_size();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(static_cast<int>(non_sdch_content.size()),
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            input_buffer_size);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(input_buffer, non_sdch_content.data(),
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         non_sdch_content.size());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter->FlushStreamBuffer(non_sdch_content.size());
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to read output.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int output_bytes_or_buffer_size = sizeof(output_buffer);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FilterStatus status = filter->ReadData(output_buffer,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &output_bytes_or_buffer_size);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have read a long and complicated meta-refresh request.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(sizeof(output_buffer) == output_bytes_or_buffer_size);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check at least the prefix of the return.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, strncmp(output_buffer,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\"></head>",
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sizeof(output_buffer)));
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_OK, status);
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, ErrorOnBadReturnCode) {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Selective a tentative filter (which can fall back to pass through).
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char output_buffer[20];
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Response code needs to be 200 to allow a pass through.
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetResponseCode(403);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Meta refresh will only appear for html content, so set to something else
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to induce an error (we can't meta refresh).
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetMimeType("anything");
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string("http://ignore.com");
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Supply enough data to force a pass-through mode, which means we have
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // provided more than 9 characters that can't be a dictionary hash.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string non_sdch_content("This is not SDCH");
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* input_buffer = filter->stream_buffer()->data();
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int input_buffer_size = filter->stream_buffer_size();
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(static_cast<int>(non_sdch_content.size()),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            input_buffer_size);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(input_buffer, non_sdch_content.data(),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         non_sdch_content.size());
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter->FlushStreamBuffer(non_sdch_content.size());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to read output.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int output_bytes_or_buffer_size = sizeof(output_buffer);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FilterStatus status = filter->ReadData(output_buffer,
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &output_bytes_or_buffer_size);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, output_bytes_or_buffer_size);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_ERROR, status);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, ErrorOnBadReturnCodeWithHtml) {
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Selective a tentative filter (which can fall back to pass through).
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH_POSSIBLE);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char output_buffer[20];
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Response code needs to be 200 to allow a pass through.
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetResponseCode(403);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Meta refresh will only appear for html content
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetMimeType("text/html");
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string("http://ignore.com");
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));
339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Supply enough data to force a pass-through mode, which means we have
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // provided more than 9 characters that can't be a dictionary hash.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string non_sdch_content("This is not SDCH");
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* input_buffer = filter->stream_buffer()->data();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int input_buffer_size = filter->stream_buffer_size();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(static_cast<int>(non_sdch_content.size()),
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            input_buffer_size);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(input_buffer, non_sdch_content.data(),
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         non_sdch_content.size());
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter->FlushStreamBuffer(non_sdch_content.size());
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to read output.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int output_bytes_or_buffer_size = sizeof(output_buffer);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FilterStatus status = filter->ReadData(output_buffer,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &output_bytes_or_buffer_size);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We should have read a long and complicated meta-refresh request.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(sizeof(output_buffer),
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            static_cast<size_t>(output_bytes_or_buffer_size));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check at least the prefix of the return.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, strncmp(output_buffer,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "<head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"0\"></head>",
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sizeof(output_buffer)));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_OK, status);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, BasicBadDictionary) {
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char output_buffer[20];
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string("http://ignore.com");
374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));
375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Supply bogus data (which doesn't yet specify a full dictionary hash).
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Dictionary hash is 8 characters followed by a null.
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary_hash_prefix("123");
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* input_buffer = filter->stream_buffer()->data();
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int input_buffer_size = filter->stream_buffer_size();
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_LT(static_cast<int>(dictionary_hash_prefix.size()),
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            input_buffer_size);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(input_buffer, dictionary_hash_prefix.data(),
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         dictionary_hash_prefix.size());
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter->FlushStreamBuffer(dictionary_hash_prefix.size());
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // With less than a dictionary specifier, try to read output.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int output_bytes_or_buffer_size = sizeof(output_buffer);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Filter::FilterStatus status = filter->ReadData(output_buffer,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 &output_bytes_or_buffer_size);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, output_bytes_or_buffer_size);
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA, status);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Provide enough data to complete *a* hash, but it is bogus, and not in our
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // list of dictionaries, so the filter should error out immediately.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary_hash_postfix("4abcd\0", 6);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_LT(dictionary_hash_postfix.size(),
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           static_cast<size_t>(input_buffer_size));
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(input_buffer, dictionary_hash_postfix.data(),
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         dictionary_hash_postfix.size());
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter->FlushStreamBuffer(dictionary_hash_postfix.size());
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // With a non-existant dictionary specifier, try to read output.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_bytes_or_buffer_size = sizeof(output_buffer);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  status = filter->ReadData(output_buffer, &output_bytes_or_buffer_size);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, output_bytes_or_buffer_size);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_ERROR, status);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_FALSE(sdch_manager_->IsInSupportedDomain(GURL(url_string)));
416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  sdch_manager_->ClearBlacklistings();
417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(sdch_manager_->IsInSupportedDomain(GURL(url_string)));
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, DictionaryAddOnce) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check we can't add it twice.
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(AddSdchDictionary(dictionary, url));
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain2 = "sdchtest2.com";
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Don't test adding a second dictionary if our limits are tight.
4356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (SdchManager::kMaxDictionaryCount > 1) {
4366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // Construct a second SDCH dictionary from a VCDIFF dictionary.
4376d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    std::string dictionary2(NewSdchDictionary(kSampleDomain2));
4386d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
4396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    std::string url_string2 = "http://" + kSampleDomain2;
4406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    GURL url2(url_string2);
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    EXPECT_TRUE(AddSdchDictionary(dictionary2, url2));
4426d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, BasicDictionary) {
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
4531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(NewSdchCompressedData(dictionary));
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(url);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = 100;
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = 100;
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             filter.get(), &output));
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Decode with really small buffers (size 1) to check for edge effects.
472f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(Filter::Factory(filter_types, *filter_context()));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 1;
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 1;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size,
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             filter.get(), &output));
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, NoDecodeHttps) {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(NewSdchCompressedData(dictionary));
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
497f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL("https://" + kSampleDomain));
498f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t feed_block_size(100);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t output_block_size(100);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size,
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             filter.get(), &output));
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Current failsafe TODO/hack refuses to decode any content that doesn't use
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http as the scheme (see use of DICTIONARY_SELECTED_FOR_NON_HTTP).
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following tests this blockage.  Note that blacklisting results, so we
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we need separate tests for each of these.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, NoDecodeFtp) {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(NewSdchCompressedData(dictionary));
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
527f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL("ftp://" + kSampleDomain));
528f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t feed_block_size(100);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t output_block_size(100);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size,
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             filter.get(), &output));
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, NoDecodeFileColon) {
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
5461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(NewSdchCompressedData(dictionary));
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
553f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL("file://" + kSampleDomain));
554f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t feed_block_size(100);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t output_block_size(100);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size,
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             filter.get(), &output));
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, NoDecodeAboutColon) {
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
5721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(NewSdchCompressedData(dictionary));
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
579f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL("about://" + kSampleDomain));
580f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t feed_block_size(100);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t output_block_size(100);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size,
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             filter.get(), &output));
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, NoDecodeJavaScript) {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
5981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(NewSdchCompressedData(dictionary));
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL("javascript://" + kSampleDomain));
606f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t feed_block_size(100);
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t output_block_size(100);
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size,
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             filter.get(), &output));
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, CanStillDecodeHttp) {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
6241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(NewSdchCompressedData(dictionary));
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
631f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL("http://" + kSampleDomain));
632f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t feed_block_size(100);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t output_block_size(100);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(compressed, feed_block_size, output_block_size,
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             filter.get(), &output));
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, CrossDomainDictionaryUse) {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
6501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(NewSdchCompressedData(dictionary));
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Decode with content arriving from the "wrong" domain.
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This tests SdchManager::CanSet().
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL wrong_domain_url("http://www.wrongdomain.com");
660f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(wrong_domain_url);
661f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types,  *filter_context()));
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = 100;
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = 100;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(FilterTestData(compressed, feed_block_size, output_block_size,
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              filter.get(), &output));
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output.size(), 0u);  // No output written.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
670f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(sdch_manager_->IsInSupportedDomain(GURL(url_string)));
671f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_FALSE(sdch_manager_->IsInSupportedDomain(wrong_domain_url));
672f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  sdch_manager_->ClearBlacklistings();
673f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(sdch_manager_->IsInSupportedDomain(wrong_domain_url));
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, DictionaryPathValidation) {
6776d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Can't test path distinction between dictionaries if we aren't allowed
6786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // more than one dictionary.
6796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (SdchManager::kMaxDictionaryCount <= 1)
6806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
6816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
6891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a dictionary with a path restriction, by prefixing dictionary.
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string path("/special_path/bin");
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary_with_path("Path: " + path + "\n");
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary_with_path.append(dictionary);
6951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  GURL url2(url_string + path);
6961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary_with_path, url2));
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed_for_path(NewSdchCompressedData(dictionary_with_path));
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test decode the path data, arriving from a valid path.
704f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string + path));
705f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = 100;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = 100;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(compressed_for_path, feed_block_size,
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test decode the path data, arriving from a invalid path.
716f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));
717f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(Filter::Factory(filter_types, *filter_context()));
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 100;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 100;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(FilterTestData(compressed_for_path, feed_block_size,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              output_block_size, filter.get(), &output));
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output.size(), 0u);  // No output written.
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
726f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_FALSE(sdch_manager_->IsInSupportedDomain(GURL(url_string)));
727f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  sdch_manager_->ClearBlacklistings();
728f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(sdch_manager_->IsInSupportedDomain(GURL(url_string)));
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, DictionaryPortValidation) {
7326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // Can't test port distinction between dictionaries if we aren't allowed
7336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  // more than one dictionary.
7346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (SdchManager::kMaxDictionaryCount <= 1)
7356d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    return;
7366d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
7441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a dictionary with a port restriction, by prefixing old dictionary.
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string port("502");
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary_with_port("Port: " + port + "\n");
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary_with_port.append("Port: 80\n");  // Add default port.
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dictionary_with_port.append(dictionary);
7511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary_with_port,
7521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                GURL(url_string + ":" + port)));
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed_for_port(NewSdchCompressedData(dictionary_with_port));
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test decode the port data, arriving from a valid port.
760f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string + ":" + port));
761f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = 100;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = 100;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(compressed_for_port, feed_block_size,
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test decode the port data, arriving from a valid (default) port.
771f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string));  // Default port.
772f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(Filter::Factory(filter_types, *filter_context()));
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 100;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 100;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(compressed_for_port, feed_block_size,
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test decode the port data, arriving from a invalid port.
782f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(GURL(url_string + ":" + port + "1"));
783f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(Filter::Factory(filter_types, *filter_context()));
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 100;
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 100;
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(FilterTestData(compressed_for_port, feed_block_size,
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              output_block_size, filter.get(), &output));
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output.size(), 0u);  // No output written.
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
792f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_FALSE(sdch_manager_->IsInSupportedDomain(GURL(url_string)));
793f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  sdch_manager_->ClearBlacklistings();
794f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  EXPECT_TRUE(sdch_manager_->IsInSupportedDomain(GURL(url_string)));
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper function to perform gzip compression of data.
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static std::string gzip_compress(const std::string &input) {
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  z_stream zlib_stream;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&zlib_stream, 0, sizeof(zlib_stream));
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int code;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize zlib
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  code = deflateInit2(&zlib_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      -MAX_WBITS,
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      8,  // DEF_MEM_LEVEL
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      Z_DEFAULT_STRATEGY);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(Z_OK, code);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fill in zlib control block
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zlib_stream.next_in = bit_cast<Bytef*>(input.data());
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zlib_stream.avail_in = input.size();
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assume we can compress into similar buffer (add 100 bytes to be sure).
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t gzip_compressed_length = zlib_stream.avail_in + 100;
819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<char[]> gzip_compressed(new char[gzip_compressed_length]);
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zlib_stream.next_out = bit_cast<Bytef*>(gzip_compressed.get());
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zlib_stream.avail_out = gzip_compressed_length;
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The GZIP header (see RFC 1952):
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   +---+---+---+---+---+---+---+---+---+---+
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   |ID1|ID2|CM |FLG|     MTIME     |XFL|OS |
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   +---+---+---+---+---+---+---+---+---+---+
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     ID1     \037
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     ID2     \213
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     CM      \010 (compression method == DEFLATE)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     FLG     \000 (special flags that we do not support)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     MTIME   Unix format modification time (0 means not available)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     XFL     2-4? DEFLATE flags
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     OS      ???? Operating system indicator (255 means unknown)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Header value we generate:
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kGZipHeader[] = { '\037', '\213', '\010', '\000', '\000',
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               '\000', '\000', '\000', '\002', '\377' };
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GT(zlib_stream.avail_out, sizeof(kGZipHeader));
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(zlib_stream.next_out, kGZipHeader, sizeof(kGZipHeader));
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zlib_stream.next_out += sizeof(kGZipHeader);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  zlib_stream.avail_out -= sizeof(kGZipHeader);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do deflate
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  code = deflate(&zlib_stream, Z_FINISH);
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gzip_compressed_length -= zlib_stream.avail_out;
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string compressed(gzip_compressed.get(), gzip_compressed_length);
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deflateEnd(&zlib_stream);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return compressed;
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//------------------------------------------------------------------------------
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SdchFilterChainingTest {
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static Filter* Factory(const std::vector<Filter::FilterType>& types,
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const FilterContext& context, int size) {
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Filter::FactoryForTests(types, context, size);
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that filters can be cascaded (chained) so that the output of one filter
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is processed by the next one.  This is most critical for SDCH, which is
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// routinely followed by gzip (during encoding).  The filter we'll test for will
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// do the gzip decoding first, and then decode the SDCH content.
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, FilterChaining) {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
8731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sdch_compressed(NewSdchCompressedData(dictionary));
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use Gzip to compress the sdch sdch_compressed data.
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string gzip_compressed_sdch = gzip_compress(sdch_compressed);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a chained filter.
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_GZIP);
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First try with a large buffer (larger than test input, or compressed data).
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kLargeInputBufferSize(1000);  // Used internally in filters.
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GT(kLargeInputBufferSize, gzip_compressed_sdch.size());
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GT(kLargeInputBufferSize, sdch_compressed.size());
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GT(kLargeInputBufferSize, expanded_.size());
890f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(url);
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Filter> filter(
892f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SdchFilterChainingTest::Factory(filter_types, *filter_context(),
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      kLargeInputBufferSize));
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(kLargeInputBufferSize),
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            filter->stream_buffer_size());
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that chained filter is waiting for data.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char tiny_output_buffer[10];
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tiny_output_size = sizeof(tiny_output_buffer);
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA,
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            filter->ReadData(tiny_output_buffer, &tiny_output_size));
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make chain process all data.
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = kLargeInputBufferSize;
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = kLargeInputBufferSize;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next try with a mid-sized internal buffer size.
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kMidSizedInputBufferSize(100);
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Buffer should be big enough to swallow whole gzip content.
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_GT(kMidSizedInputBufferSize, gzip_compressed_sdch.size());
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Buffer should be small enough that entire SDCH content can't fit.
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'll go even further, and force the chain to flush the buffer between the
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // two filters more than once (that is why we multiply by 2).
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_LT(kMidSizedInputBufferSize * 2, sdch_compressed.size());
919f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(url);
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter.reset(
921f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      SdchFilterChainingTest::Factory(filter_types, *filter_context(),
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      kMidSizedInputBufferSize));
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(kMidSizedInputBufferSize),
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            filter->stream_buffer_size());
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = kMidSizedInputBufferSize;
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = kMidSizedInputBufferSize;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next try with a tiny input and output buffer to cover edge effects.
934f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(SdchFilterChainingTest::Factory(filter_types, *filter_context(),
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               kLargeInputBufferSize));
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(kLargeInputBufferSize),
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            filter->stream_buffer_size());
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 1;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 1;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, DefaultGzipIfSdch) {
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
9551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sdch_compressed(NewSdchCompressedData(dictionary));
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use Gzip to compress the sdch sdch_compressed data.
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string gzip_compressed_sdch = gzip_compress(sdch_compressed);
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only claim to have sdch content, but really use the gzipped sdch content.
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // System should automatically add the missing (optional) gzip.
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_SDCH);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
967f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetMimeType("anything/mime");
968f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetSdchResponse(true);
969f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Filter::FixupEncodingTypes(*filter_context(), &filter_types);
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(filter_types.size(), 2u);
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH);
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First try with a large buffer (larger than test input, or compressed data).
975f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(url);
976f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that chained filter is waiting for data.
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char tiny_output_buffer[10];
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tiny_output_size = sizeof(tiny_output_buffer);
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA,
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            filter->ReadData(tiny_output_buffer, &tiny_output_size));
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = 100;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = 100;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next try with a tiny buffer to cover edge effects.
993f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(Filter::Factory(filter_types, *filter_context()));
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 1;
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 1;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, AcceptGzipSdchIfGzip) {
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
10111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sdch_compressed(NewSdchCompressedData(dictionary));
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use Gzip to compress the sdch sdch_compressed data.
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string gzip_compressed_sdch = gzip_compress(sdch_compressed);
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Some proxies strip the content encoding statement down to a mere gzip, but
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pass through the original content (with full sdch,gzip encoding).
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only claim to have gzip content, but really use the gzipped sdch content.
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // System should automatically add the missing (optional) sdch.
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_GZIP);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetMimeType("anything/mime");
1026f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetSdchResponse(true);
1027f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Filter::FixupEncodingTypes(*filter_context(), &filter_types);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(filter_types.size(), 3u);
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE);
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH);
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP);
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First try with a large buffer (larger than test input, or compressed data).
1034f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(url);
1035f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that chained filter is waiting for data.
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char tiny_output_buffer[10];
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tiny_output_size = sizeof(tiny_output_buffer);
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA,
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            filter->ReadData(tiny_output_buffer, &tiny_output_size));
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = 100;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = 100;
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next try with a tiny buffer to cover edge effects.
1052f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(Filter::Factory(filter_types, *filter_context()));
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 1;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 1;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, DefaultSdchGzipIfEmpty) {
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
10701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sdch_compressed(NewSdchCompressedData(dictionary));
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use Gzip to compress the sdch sdch_compressed data.
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string gzip_compressed_sdch = gzip_compress(sdch_compressed);
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only claim to have non-encoded content, but really use the gzipped sdch
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content.
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // System should automatically add the missing (optional) sdch,gzip.
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1082f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetMimeType("anything/mime");
1083f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetSdchResponse(true);
1084f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Filter::FixupEncodingTypes(*filter_context(), &filter_types);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(filter_types.size(), 2u);
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE);
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH);
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First try with a large buffer (larger than test input, or compressed data).
1090f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(url);
1091f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that chained filter is waiting for data.
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char tiny_output_buffer[10];
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tiny_output_size = sizeof(tiny_output_buffer);
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA,
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            filter->ReadData(tiny_output_buffer, &tiny_output_size));
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = 100;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = 100;
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next try with a tiny buffer to cover edge effects.
1108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(Filter::Factory(filter_types, *filter_context()));
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 1;
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 1;
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(gzip_compressed_sdch, feed_block_size,
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SdchFilterTest, AcceptGzipGzipSdchIfGzip) {
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a valid SDCH dictionary from a VCDIFF dictionary.
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string kSampleDomain = "sdchtest.com";
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string dictionary(NewSdchDictionary(kSampleDomain));
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string url_string = "http://" + kSampleDomain;
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(url_string);
11261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(AddSdchDictionary(dictionary, url));
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string sdch_compressed(NewSdchCompressedData(dictionary));
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Vodaphone (UK) Mobile Broadband provides double gzipped sdch with a content
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // encoding of merely gzip (apparently, only listing the extra level of
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // wrapper compression they added, but discarding the actual content encoding.
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Use Gzip to double compress the sdch sdch_compressed data.
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string double_gzip_compressed_sdch = gzip_compress(gzip_compress(
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sdch_compressed));
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only claim to have gzip content, but really use the double gzipped sdch
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // content.
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // System should automatically add the missing (optional) sdch, gzip decoders.
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Filter::FilterType> filter_types;
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  filter_types.push_back(Filter::FILTER_TYPE_GZIP);
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetMimeType("anything/mime");
1144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetSdchResponse(true);
1145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  Filter::FixupEncodingTypes(*filter_context(), &filter_types);
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(filter_types.size(), 3u);
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[0], Filter::FILTER_TYPE_SDCH_POSSIBLE);
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[1], Filter::FILTER_TYPE_GZIP_HELPING_SDCH);
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(filter_types[2], Filter::FILTER_TYPE_GZIP);
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First try with a large buffer (larger than test input, or compressed data).
1152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter_context()->SetURL(url);
1153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<Filter> filter(Filter::Factory(filter_types, *filter_context()));
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify that chained filter is waiting for data.
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char tiny_output_buffer[10];
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int tiny_output_size = sizeof(tiny_output_buffer);
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(Filter::FILTER_NEED_MORE_DATA,
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            filter->ReadData(tiny_output_buffer, &tiny_output_size));
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t feed_block_size = 100;
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t output_block_size = 100;
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string output;
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(double_gzip_compressed_sdch, feed_block_size,
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next try with a tiny buffer to cover edge effects.
1169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  filter.reset(Filter::Factory(filter_types, *filter_context()));
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  feed_block_size = 1;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_block_size = 1;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.clear();
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(FilterTestData(double_gzip_compressed_sdch, feed_block_size,
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             output_block_size, filter.get(), &output));
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(output, expanded_);
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1180