/*
 * Copyright 2010 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Author: sligocki@google.com (Shawn Ligocki)

#include "net/instaweb/rewriter/public/rewrite_test_base.h"

#include <cstddef>
#include <vector>

#include "base/logging.h"
#include "net/instaweb/config/rewrite_options_manager.h"
#include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/counting_url_async_fetcher.h"
#include "net/instaweb/http/public/http_cache.h"
#include "net/instaweb/http/public/http_cache_failure.h"
#include "net/instaweb/http/public/http_value.h"
#include "net/instaweb/http/public/log_record.h"
#include "net/instaweb/http/public/log_record_test_helper.h"
#include "net/instaweb/http/public/logging_proto.h"
#include "net/instaweb/http/public/logging_proto_impl.h"
#include "net/instaweb/http/public/mock_callback.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/public/global_constants.h"
#include "net/instaweb/rewriter/cached_result.pb.h"
#include "net/instaweb/rewriter/public/css_tag_scanner.h"
#include "net/instaweb/rewriter/public/css_url_encoder.h"
#include "net/instaweb/rewriter/public/domain_lawyer.h"
#include "net/instaweb/rewriter/public/image_url_encoder.h"
#include "net/instaweb/rewriter/public/lazyload_images_filter.h"
#include "net/instaweb/rewriter/public/process_context.h"
#include "net/instaweb/rewriter/public/resource.h"
#include "net/instaweb/rewriter/public/resource_namer.h"
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_driver_factory.h"
#include "net/instaweb/rewriter/public/rewrite_filter.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/rewrite_stats.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "net/instaweb/rewriter/public/test_rewrite_driver_factory.h"
#include "net/instaweb/rewriter/public/test_url_namer.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/base64_util.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/ref_counted_ptr.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/stdio_file_system.h"
#include "pagespeed/kernel/base/stl_util.h"
#include "pagespeed/kernel/base/string_writer.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/cache/delay_cache.h"
#include "pagespeed/kernel/cache/lru_cache.h"
#include "pagespeed/kernel/cache/mock_time_cache.h"
#include "pagespeed/kernel/html/empty_html_filter.h"
#include "pagespeed/kernel/html/html_element.h"
#include "pagespeed/kernel/html/html_parse.h"
#include "pagespeed/kernel/html/html_parse_test_base.h"
#include "pagespeed/kernel/html/html_writer_filter.h"
#include "pagespeed/kernel/http/content_type.h"
#include "pagespeed/kernel/http/google_url.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/thread/mock_scheduler.h"
#include "pagespeed/kernel/util/simple_stats.h"
#include "pagespeed/kernel/util/url_multipart_encoder.h"

namespace net_instaweb {

namespace {

// Logging at the INFO level slows down tests, adds to the noise, and
// adds considerably to the speed variability.
class RewriteTestBaseProcessContext : public ProcessContext {
 public:
  RewriteTestBaseProcessContext() {
    logging::SetMinLogLevel(logging::LOG_WARNING);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(RewriteTestBaseProcessContext);
};
RewriteTestBaseProcessContext rewrite_test_base_process_context;

class TestRewriteOptionsManager : public RewriteOptionsManager {
 public:
  TestRewriteOptionsManager()
      : options_(NULL) {}

  void GetRewriteOptions(const GoogleUrl& url,
                         const RequestHeaders& headers,
                         OptionsCallback* done) {
    done->Run((options_ == NULL) ? NULL : options_->Clone());
  }

  void set_options(RewriteOptions* options) { options_ = options; }

 private:
  RewriteOptions* options_;
};

}  // namespace

const char RewriteTestBase::kTestData[] = "/net/instaweb/rewriter/testdata/";
const char RewriteTestBase::kConfiguredBeaconingKey[] =
    "configured_beaconing_key";
const char RewriteTestBase::kWrongBeaconingKey[] = "wrong_beaconing_key";
const char kMessagePatternShrinkImage[] = "*Shrinking image*";

RewriteTestBase::RewriteTestBase()
    : kFoundResult(HTTPCache::kFound, kFetchStatusOK),
      kNotFoundResult(HTTPCache::kNotFound, kFetchStatusNotSet),
      test_distributed_fetcher_(this),
      factory_(new TestRewriteDriverFactory(rewrite_test_base_process_context,
                                            GTestTempDir(),
                                            &mock_url_fetcher_,
                                            &test_distributed_fetcher_)),
      other_factory_(new TestRewriteDriverFactory(
          rewrite_test_base_process_context,
          GTestTempDir(),
          &mock_url_fetcher_,
          &test_distributed_fetcher_)),
      use_managed_rewrite_drivers_(false),
      options_(factory_->NewRewriteOptions()),
      other_options_(other_factory_->NewRewriteOptions()),
      kEtag0(HTTPCache::FormatEtag("0")),
      expected_nonce_(0) {
  statistics_.reset(new SimpleStats(factory_->thread_system()));
  Init();
}

// Takes ownership of the statistics.
RewriteTestBase::RewriteTestBase(Statistics* statistics)
    : kFoundResult(HTTPCache::kFound, kFetchStatusOK),
      kNotFoundResult(HTTPCache::kNotFound, kFetchStatusNotSet),
      test_distributed_fetcher_(this),
      statistics_(statistics),
      factory_(new TestRewriteDriverFactory(rewrite_test_base_process_context,
                                            GTestTempDir(),
                                            &mock_url_fetcher_,
                                            &test_distributed_fetcher_)),
      other_factory_(new TestRewriteDriverFactory(
          rewrite_test_base_process_context,
          GTestTempDir(),
          &mock_url_fetcher_,
          &test_distributed_fetcher_)),
      use_managed_rewrite_drivers_(false),
      options_(factory_->NewRewriteOptions()),
      other_options_(other_factory_->NewRewriteOptions()),
      expected_nonce_(0) {
  Init();
}

RewriteTestBase::RewriteTestBase(
    std::pair<TestRewriteDriverFactory*, TestRewriteDriverFactory*> factories)
    : kFoundResult(HTTPCache::kFound, kFetchStatusOK),
      kNotFoundResult(HTTPCache::kNotFound, kFetchStatusNotSet),
      test_distributed_fetcher_(this),
      factory_(factories.first),
      other_factory_(factories.second),
      use_managed_rewrite_drivers_(false),
      options_(factory_->NewRewriteOptions()),
      other_options_(other_factory_->NewRewriteOptions()),
      expected_nonce_(0) {
  statistics_.reset(new SimpleStats(factory_->thread_system()));
  Init();
}

void RewriteTestBase::Init() {
  DCHECK(statistics_ != NULL);
  RewriteDriverFactory::Initialize();
  TestRewriteDriverFactory::InitStats(statistics_.get());
  factory_->SetStatistics(statistics_.get());
  other_factory_->SetStatistics(statistics_.get());
  server_context_ = factory_->CreateServerContext();
  other_server_context_ = other_factory_->CreateServerContext();
  active_server_ = kPrimary;
  message_handler_.set_mutex(factory_->thread_system()->NewMutex());
}

RewriteTestBase::~RewriteTestBase() {
  RewriteDriverFactory::Terminate();
}

// The Setup/Constructor split is designed so that test subclasses can
// add options prior to calling RewriteTestBase::SetUp().
void RewriteTestBase::SetUp() {
  HtmlParseTestBaseNoAlloc::SetUp();
  rewrite_driver_ = MakeDriver(server_context_, options_);
  other_rewrite_driver_ = MakeDriver(other_server_context_, other_options_);
}

void RewriteTestBase::TearDown() {
  if (use_managed_rewrite_drivers_) {
    factory_->ShutDown();
    other_factory_->ShutDown();
  } else {
    rewrite_driver_->WaitForShutDown();

    // We need to make sure we shutdown the threads here before
    // deleting the driver, as the last task on the rewriter's job
    // queue may still be wrapping up some cleanups and notifications.
    factory_->ShutDown();
    rewrite_driver_->Clear();
    delete rewrite_driver_;
    rewrite_driver_ = NULL;

    other_rewrite_driver_->WaitForShutDown();
    other_factory_->ShutDown();
    other_rewrite_driver_->Clear();
    delete other_rewrite_driver_;
    other_rewrite_driver_ = NULL;
  }
  HtmlParseTestBaseNoAlloc::TearDown();
}

// Adds rewrite filters related to recompress images.
void RewriteTestBase::AddRecompressImageFilters() {
  // TODO(vchudnov): Consider adding kConvertToWebpLossless.
  options()->EnableFilter(RewriteOptions::kRecompressJpeg);
  options()->EnableFilter(RewriteOptions::kRecompressPng);
  options()->EnableFilter(RewriteOptions::kRecompressWebp);
  options()->EnableFilter(RewriteOptions::kConvertPngToJpeg);
  options()->EnableFilter(RewriteOptions::kConvertJpegToWebp);
  options()->EnableFilter(RewriteOptions::kConvertGifToPng);
}

// Add a single rewrite filter to rewrite_driver_.
void RewriteTestBase::AddFilter(RewriteOptions::Filter filter) {
  options()->EnableFilter(filter);
  rewrite_driver_->AddFilters();
}

// Add a single rewrite filter to other_rewrite_driver_.
void RewriteTestBase::AddOtherFilter(RewriteOptions::Filter filter) {
  other_options()->EnableFilter(filter);
  other_rewrite_driver_->AddFilters();
}

void RewriteTestBase::AddRewriteFilter(RewriteFilter* filter) {
  rewrite_driver_->RegisterRewriteFilter(filter);
  rewrite_driver_->EnableRewriteFilter(filter->id());
}

void RewriteTestBase::AddFetchOnlyRewriteFilter(RewriteFilter* filter) {
  rewrite_driver_->RegisterRewriteFilter(filter);
}

void RewriteTestBase::AddOtherRewriteFilter(RewriteFilter* filter) {
  other_rewrite_driver_->RegisterRewriteFilter(filter);
  other_rewrite_driver_->EnableRewriteFilter(filter->id());
}

void RewriteTestBase::SetBaseUrlForFetch(const StringPiece& url) {
  rewrite_driver_->SetBaseUrlForFetch(url);
}

void RewriteTestBase::ParseUrl(StringPiece url, StringPiece html_input) {
  if (rewrite_driver_->request_headers() == NULL) {
    SetDriverRequestHeaders();
  }
  HtmlParseTestBaseNoAlloc::ParseUrl(url, html_input);
}

void RewriteTestBase::PopulateRequestHeaders(RequestHeaders* request_headers) {
  request_headers->Add(HttpAttributes::kUserAgent, current_user_agent_);
  CHECK_EQ(request_attribute_names_.size(), request_attribute_values_.size());
  for (size_t i = 0, n = request_attribute_names_.size(); i < n; ++i) {
    request_headers->Add(request_attribute_names_[i],
                         request_attribute_values_[i]);
  }
}

void RewriteTestBase::SetDriverRequestHeaders() {
  RequestHeaders request_headers;
  PopulateRequestHeaders(&request_headers);
  rewrite_driver()->SetRequestHeaders(request_headers);
}

void RewriteTestBase::AddRequestAttribute(StringPiece name, StringPiece value) {
  request_attribute_names_.push_back(name.as_string());
  request_attribute_values_.push_back(value.as_string());
}

void RewriteTestBase::SetDownstreamCacheDirectives(
    StringPiece downstream_cache_purge_method,
    StringPiece downstream_cache_purge_location_prefix,
    StringPiece rebeaconing_key) {
  options_->ClearSignatureForTesting();
  options_->set_downstream_cache_rewritten_percentage_threshold(95);
  options_->set_downstream_cache_purge_method(downstream_cache_purge_method);
  options_->set_downstream_cache_purge_location_prefix(
      downstream_cache_purge_location_prefix);
  options_->set_downstream_cache_rebeaconing_key(rebeaconing_key);
  options_->ComputeSignature();
}

void RewriteTestBase::SetShouldBeaconHeader(StringPiece rebeaconing_key) {
  AddRequestAttribute(kPsaShouldBeacon, rebeaconing_key);
  SetDriverRequestHeaders();
}

ResourcePtr RewriteTestBase::CreateResource(const StringPiece& base,
                                            const StringPiece& url) {
  rewrite_driver_->SetBaseUrlForFetch(base);
  GoogleUrl base_url(base);
  GoogleUrl resource_url(base_url, url);
  bool unused;
  return rewrite_driver_->CreateInputResource(resource_url, &unused);
}

void RewriteTestBase::PopulateDefaultHeaders(
    const ContentType& content_type, int64 original_content_length,
    ResponseHeaders* headers) {
  int64 time = timer()->NowUs();
  // Reset mock timer so synthetic headers match original.  This temporarily
  // fakes out the mock_scheduler, but we will repair the damage below.
  AdjustTimeUsWithoutWakingAlarms(start_time_ms() * Timer::kMsUs);
  SetDefaultLongCacheHeaders(&content_type, headers);
  // Then set it back.  Note that no alarms should fire at this point
  // because alarms work on absolute time.
  AdjustTimeUsWithoutWakingAlarms(time);
  if (original_content_length > 0) {
    headers->SetOriginalContentLength(original_content_length);
  }
}

void RewriteTestBase::AppendDefaultHeaders(
    const ContentType& content_type, GoogleString* text) {
  ResponseHeaders headers;
  PopulateDefaultHeaders(content_type, 0, &headers);
  StringWriter writer(text);
  headers.WriteAsHttp(&writer, message_handler());
}

void RewriteTestBase::AppendDefaultHeadersWithCanonical(
    const ContentType& content_type, StringPiece canon, GoogleString* text) {
  ResponseHeaders headers;
  headers.Add(HttpAttributes::kLink,
              StrCat("<", canon, ">; rel=\"canonical\""));
  PopulateDefaultHeaders(content_type, 0, &headers);
  StringWriter writer(text);
  headers.WriteAsHttp(&writer, message_handler());
}

void RewriteTestBase::AppendDefaultHeaders(
    const ContentType& content_type, int64 original_content_length,
    GoogleString* text) {
  ResponseHeaders headers;
  PopulateDefaultHeaders(content_type, original_content_length, &headers);
  StringWriter writer(text);
  headers.WriteAsHttp(&writer, message_handler());
}

void RewriteTestBase::ServeResourceFromManyContexts(
    const GoogleString& resource_url,
    const StringPiece& expected_content) {
  ServeResourceFromNewContext(resource_url, expected_content);
}

void RewriteTestBase::ServeResourceFromManyContextsWithUA(
    const GoogleString& resource_url,
    const StringPiece& expected_content,
    const StringPiece& user_agent) {
  // TODO(sligocki): Serve the resource under several contexts. For example:
  //   1) With output-resource cached,
  //   2) With output-resource not cached, but in a file,
  //   3) With output-resource unavailable, but input-resource cached,
  //   4) With output-resource unavailable and input-resource not cached,
  //      but still fetchable,
  SetCurrentUserAgent(user_agent);
  ServeResourceFromNewContext(resource_url, expected_content);
  //   5) With nothing available (failure).
}

TestRewriteDriverFactory* RewriteTestBase::MakeTestFactory() {
  return new TestRewriteDriverFactory(rewrite_test_base_process_context,
                                      GTestTempDir(), &mock_url_fetcher_,
                                      &test_distributed_fetcher_);
}

// Test that a resource can be served from a new server that has not yet
// been constructed.
void RewriteTestBase::ServeResourceFromNewContext(
    const GoogleString& resource_url,
    const StringPiece& expected_content) {
  // New objects for the new server.
  SimpleStats stats(factory_->thread_system());
  scoped_ptr<TestRewriteDriverFactory> new_factory(MakeTestFactory());
  TestRewriteDriverFactory::InitStats(&stats);
  new_factory->SetUseTestUrlNamer(factory_->use_test_url_namer());
  new_factory->SetStatistics(&stats);
  ServerContext* new_server_context = new_factory->CreateServerContext();
  new_server_context->set_hasher(server_context_->hasher());
  RewriteOptions* new_options = options_->Clone();
  server_context_->ComputeSignature(new_options);
  RewriteDriver* new_rewrite_driver = MakeDriver(new_server_context,
                                                 new_options);
  RequestHeaders request_headers;
  PopulateRequestHeaders(&request_headers);
  new_rewrite_driver->SetRequestHeaders(request_headers);

  new_factory->SetupWaitFetcher();

  MockMessageHandler* handler = new_factory->mock_message_handler();
  handler->AddPatternToSkipPrinting(kMessagePatternShrinkImage);

  // TODO(sligocki): We should set default request headers.
  ExpectStringAsyncFetch response_contents(true, CreateRequestContext());

  // Check that we don't already have it in cache.
  HTTPValue value;
  ResponseHeaders response_headers;
  EXPECT_EQ(kNotFoundResult, HttpBlockingFind(
      resource_url, new_server_context->http_cache(), &value,
      &response_headers));
  // Initiate fetch.
  EXPECT_TRUE(new_rewrite_driver->FetchResource(
      resource_url, &response_contents));

  // Content should not be set until we call the callback.
  EXPECT_FALSE(response_contents.done());
  EXPECT_EQ("", response_contents.buffer());

  // After we call the callback, it should be correct.
  new_factory->CallFetcherCallbacksForDriver(new_rewrite_driver);
  // Since CallFetcherCallbacksForDriver waits for completion, we
  // can safely call Clear() on the driver now.
  new_rewrite_driver->Clear();
  EXPECT_TRUE(response_contents.done());
  EXPECT_STREQ(expected_content, response_contents.buffer());

  // Check that stats say we took the construct resource path.
  RewriteStats* new_stats = new_factory->rewrite_stats();
  EXPECT_EQ(0, new_stats->cached_resource_fetches()->Get());
  // We should construct at least one resource, and maybe more if the
  // output resource was produced by multiple filters (e.g. JS minimize
  // then combine).
  EXPECT_LE(1, new_stats->succeeded_filter_resource_fetches()->Get());
  EXPECT_EQ(0, new_stats->failed_filter_resource_fetches()->Get());

  // Make sure to shut the new worker down before we hit ~RewriteDriver for
  // new_rewrite_driver.
  new_factory->ShutDown();
  delete new_rewrite_driver;
}

GoogleString RewriteTestBase::AbsolutifyUrl(
    const StringPiece& resource_name) {
  GoogleString name;
  if (resource_name.starts_with("http://") ||
      resource_name.starts_with("https://")) {
    resource_name.CopyToString(&name);
  } else {
    name = StrCat(kTestDomain, resource_name);
  }
  return name;
}

void RewriteTestBase::DefaultResponseHeaders(
    const ContentType& content_type, int64 ttl_sec,
    ResponseHeaders* response_headers) {
  SetDefaultLongCacheHeaders(&content_type, response_headers);
  response_headers->SetDateAndCaching(
      timer()->NowMs(), ttl_sec * Timer::kSecondMs);
  response_headers->ComputeCaching();
}

// Initializes a resource for mock fetching.
void RewriteTestBase::SetResponseWithDefaultHeaders(
    const StringPiece& resource_name,
    const ContentType& content_type,
    const StringPiece& content,
    int64 ttl_sec) {
  GoogleString url = AbsolutifyUrl(resource_name);
  ResponseHeaders response_headers;
  DefaultResponseHeaders(content_type, ttl_sec, &response_headers);
  // Do not set Etag and Last-Modified headers to the constants since they make
  // conditional refreshes always succeed and aren't updated in tests when the
  // actual response is updated.
  response_headers.RemoveAll(HttpAttributes::kEtag);
  response_headers.RemoveAll(HttpAttributes::kLastModified);
  SetFetchResponse(url, response_headers, content);
}

void RewriteTestBase::SetFetchResponse404(
    const StringPiece& resource_name) {
  GoogleString name = AbsolutifyUrl(resource_name);
  ResponseHeaders response_headers;
  SetDefaultLongCacheHeaders(&kContentTypeText, &response_headers);
  response_headers.SetStatusAndReason(HttpStatus::kNotFound);
  SetFetchResponse(name, response_headers, "");
}

bool RewriteTestBase::LoadFile(const StringPiece& filename,
                               GoogleString* contents) {
  // We need to load a file from the testdata directory. Don't use this
  // physical filesystem for anything else, use file_system_ which can be
  // abstracted as a MemFileSystem instead.
  StdioFileSystem stdio_file_system;
  GoogleString filename_str = StrCat(GTestSrcDir(), kTestData, filename);
  return stdio_file_system.ReadFile(
      filename_str.c_str(), contents, message_handler());
}

void RewriteTestBase::AddFileToMockFetcher(
    const StringPiece& url,
    const StringPiece& filename,
    const ContentType& content_type,
    int64 ttl_sec) {
  // TODO(sligocki): There's probably a lot of wasteful copying here.

  GoogleString contents;
  ASSERT_TRUE(LoadFile(filename, &contents));
  SetResponseWithDefaultHeaders(url, content_type, contents, ttl_sec);
}

// Helper function to test resource fetching, returning true if the fetch
// succeeded, and modifying content.  It is up to the caller to EXPECT_TRUE
// on the status and EXPECT_EQ on the content.
bool RewriteTestBase::FetchResource(
    const StringPiece& path, const StringPiece& filter_id,
    const StringPiece& name, const StringPiece& ext,
    GoogleString* content, ResponseHeaders* response) {
  GoogleString url = Encode(path, filter_id, "0", name, ext);
  return FetchResourceUrl(url, content, response);
}

bool RewriteTestBase::FetchResource(
    const StringPiece& path, const StringPiece& filter_id,
    const StringPiece& name, const StringPiece& ext,
    GoogleString* content) {
  ResponseHeaders response;
  return FetchResource(path, filter_id, name, ext, content, &response);
}

bool RewriteTestBase::FetchResourceUrl(
    const StringPiece& url, GoogleString* content) {
  ResponseHeaders response;
  return FetchResourceUrl(url, content, &response);
}

bool RewriteTestBase::FetchResourceUrl(
    const StringPiece& url, GoogleString* content, ResponseHeaders* response) {
  return FetchResourceUrl(url, NULL, content, response);
}

bool RewriteTestBase::FetchResourceUrl(const StringPiece& url,
                                       RequestHeaders* request_headers,
                                       GoogleString* content,
                                       ResponseHeaders* response_headers) {
  content->clear();
  StringAsyncFetch async_fetch(rewrite_driver_->request_context(), content);
  if (request_headers != NULL) {
    async_fetch.set_request_headers(request_headers);
  } else if (rewrite_driver_->request_headers() == NULL) {
    SetDriverRequestHeaders();
  }
  async_fetch.set_response_headers(response_headers);
  bool fetched = rewrite_driver_->FetchResource(url, &async_fetch);
  // Make sure we let the rewrite complete, and also wait for the driver to be
  // idle so we can reuse it safely.
  rewrite_driver_->WaitForShutDown();

  ClearRewriteDriver();

  // The callback should be called if and only if FetchResource returns true.
  EXPECT_EQ(fetched, async_fetch.done());
  return fetched && async_fetch.success();
}

void RewriteTestBase::TestServeFiles(
    const ContentType* content_type,
    const StringPiece& filter_id,
    const StringPiece& rewritten_ext,
    const StringPiece& orig_name,
    const StringPiece& orig_content,
    const StringPiece& rewritten_name,
    const StringPiece& rewritten_content) {

  GoogleString expected_rewritten_path = Encode(kTestDomain, filter_id, "0",
                                                rewritten_name, rewritten_ext);
  GoogleString content;

  // When we start, there are no mock fetchers, so we'll need to get it
  // from the cache.
  ResponseHeaders headers;
  SetDefaultLongCacheHeaders(content_type, &headers);
  HTTPCache* http_cache = server_context_->http_cache();
  http_cache->Put(expected_rewritten_path, rewrite_driver_->CacheFragment(),
                  RequestHeaders::Properties(),
                  ResponseHeaders::GetVaryOption(options()->respect_vary()),
                  &headers, rewritten_content, message_handler());
  EXPECT_EQ(0U, lru_cache()->num_hits());
  EXPECT_TRUE(FetchResource(kTestDomain, filter_id,
                            rewritten_name, rewritten_ext, &content));
  RewriteFilter* filter = rewrite_driver_->FindFilter(filter_id);
  if (lru_cache()->IsHealthy()) {
    if (filter->ComputeOnTheFly()) {
      EXPECT_EQ(2U, lru_cache()->num_hits());
    } else {
      EXPECT_EQ(1U, lru_cache()->num_hits());
    }
  }
  EXPECT_STREQ(rewritten_content, content);

  // Now nuke the cache, get it via a fetch.
  lru_cache()->Clear();
  SetResponseWithDefaultHeaders(orig_name, *content_type,
                                orig_content, 100 /* ttl in seconds */);
  EXPECT_TRUE(FetchResource(kTestDomain, filter_id,
                            rewritten_name, rewritten_ext, &content));
  EXPECT_EQ(rewritten_content, content);

  // Now we expect the cache entry to be there.
  if (!filter->ComputeOnTheFly() && lru_cache()->IsHealthy()) {
    HTTPValue value;
    ResponseHeaders response_headers;
    EXPECT_EQ(kFoundResult, HttpBlockingFind(
        expected_rewritten_path, http_cache, &value, &response_headers));
  }
}

void RewriteTestBase::ValidateFallbackHeaderSanitizationHelper(
    StringPiece filter_id, StringPiece origin_content_type, bool expect_load) {

  // Mangle the content type to make a url name by removing '/'s.
  GoogleString leafable(origin_content_type.as_string());
  GlobalReplaceSubstring("/", "-", &leafable);

  GoogleString leaf = StrCat("leaf-", leafable);
  GoogleString origin_contents = "this isn't a real file";

  ResponseHeaders origin_response_headers;
  origin_response_headers.set_major_version(1);
  origin_response_headers.set_minor_version(1);
  origin_response_headers.SetStatusAndReason(HttpStatus::kOK);
  origin_response_headers.Add(HttpAttributes::kContentType,
                              origin_content_type);

  int64 now_ms = timer()->NowMs();
  // This is a case where we do need to make some changes for security and we
  // want to be sure we make them even if no-transform is set.
  origin_response_headers.SetDateAndCaching(now_ms, 0 /* ttl */,
                                            "; no-transform");
  origin_response_headers.ComputeCaching();

  SetFetchResponse(
      AbsolutifyUrl(leaf), origin_response_headers, origin_contents);

  GoogleString resource = AbsolutifyUrl(Encode(
      "", filter_id, "0", leaf, "ignored"));

  GoogleString response_content;
  ResponseHeaders response_headers;

  if (expect_load) {
    ASSERT_TRUE(FetchResourceUrl(resource,
                                 NULL /* use default request headers */,
                                 &response_content,
                                 &response_headers));
    EXPECT_EQ(origin_contents, response_content);
    const ContentType* content_type = response_headers.DetermineContentType();
    ASSERT_TRUE(NULL != content_type);
    EXPECT_EQ(origin_content_type, content_type->mime_type());

    const char* nosniff = response_headers.Lookup1("X-Content-Type-Options");
    ASSERT_TRUE(NULL != nosniff);
    EXPECT_EQ("nosniff", GoogleString(nosniff));
  } else {
    ASSERT_FALSE(FetchResourceUrl(resource,
                                  NULL /* use default request headers */,
                                  &response_content,
                                  &response_headers));
  }
}


void RewriteTestBase::ValidateFallbackHeaderSanitization(
    StringPiece filter_id) {
  // Freeze our options.
  server_context()->ComputeSignature(options());

  // These content types will all be preserved.
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "text/css", true);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "text/javascript", true);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "application/javascript", true);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "image/jpg", true);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "image/jpeg", true);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "image/png", true);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "image/gif", true);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "image/webp", true);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "application/pdf", true);

  // All other content types will be stripped.
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "text/html", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "text/plain", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "text/xml", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "application/xml", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "image/svg", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "image/svg+xml", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "audio/mp3", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "video/mp4", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "", false);
  ValidateFallbackHeaderSanitizationHelper(
      filter_id, "invalid", false);
}

// Just check if we can fetch a resource successfully, ignore response.
bool RewriteTestBase::TryFetchResource(const StringPiece& url) {
  GoogleString contents;
  ResponseHeaders response;
  return FetchResourceUrl(url, &contents, &response);
}


RewriteTestBase::CssLink::CssLink(
    const StringPiece& url, const StringPiece& content,
    const StringPiece& media, bool supply_mock)
    : url_(url.data(), url.size()),
      content_(content.data(), content.size()),
      media_(media.data(), media.size()),
      supply_mock_(supply_mock) {
}

RewriteTestBase::CssLink::Vector::~Vector() {
  STLDeleteElements(this);
}

void RewriteTestBase::CssLink::Vector::Add(
    const StringPiece& url, const StringPiece& content,
    const StringPiece& media, bool supply_mock) {
  push_back(new CssLink(url, content, media, supply_mock));
}

bool RewriteTestBase::CssLink::DecomposeCombinedUrl(
    StringPiece base_url, GoogleString* base,
    StringVector* segments, MessageHandler* handler) {
  GoogleUrl base_gurl(base_url);
  GoogleUrl gurl(base_gurl, url_);
  bool ret = false;
  if (gurl.IsWebValid()) {
    gurl.AllExceptLeaf().CopyToString(base);
    ResourceNamer namer;
    if (namer.DecodeIgnoreHashAndSignature(gurl.LeafWithQuery()) &&
        (namer.id() == RewriteOptions::kCssCombinerId)) {
      UrlMultipartEncoder multipart_encoder;
      GoogleString segment;
      ret = multipart_encoder.Decode(namer.name(), segments, NULL, handler);
    }
  }
  return ret;
}

namespace {

// Helper class to collect CSS hrefs.
class CssCollector : public EmptyHtmlFilter {
 public:
  CssCollector(HtmlParse* html_parse,
               RewriteTestBase::CssLink::Vector* css_links)
      : css_links_(css_links) {
  }

  virtual void EndElement(HtmlElement* element) {
    HtmlElement::Attribute* href;
    const char* media;
    if (CssTagScanner::ParseCssElement(element, &href, &media)) {
      // TODO(jmarantz): collect content of the CSS files, before and
      // after combination, so we can diff.
      const char* content = "";
      css_links_->Add(href->DecodedValueOrNull(), content, media, false);
    }
  }

  virtual const char* Name() const { return "CssCollector"; }

 private:
  RewriteTestBase::CssLink::Vector* css_links_;

  DISALLOW_COPY_AND_ASSIGN(CssCollector);
};

}  // namespace

// Collects just the hrefs from CSS links into a string vector.
void RewriteTestBase::CollectCssLinks(
    const StringPiece& id, const StringPiece& html, StringVector* css_links) {
  CssLink::Vector v;
  CollectCssLinks(id, html, &v);
  for (int i = 0, n = v.size(); i < n; ++i) {
    css_links->push_back(v[i]->url_);
  }
}

// Collects all information about CSS links into a CssLink::Vector.
void RewriteTestBase::CollectCssLinks(
    const StringPiece& id, const StringPiece& html,
    CssLink::Vector* css_links) {
  HtmlParse html_parse(message_handler());
  CssCollector collector(&html_parse, css_links);
  html_parse.AddFilter(&collector);
  GoogleString dummy_url = StrCat("http://collect.css.links/", id, ".html");
  html_parse.StartParse(dummy_url);
  html_parse.ParseText(html.data(), html.size());
  html_parse.FinishParse();
}

void RewriteTestBase::EncodePathAndLeaf(const StringPiece& id,
                                        const StringPiece& hash,
                                        const StringVector& name_vector,
                                        const StringPiece& ext,
                                        ResourceNamer* namer) {
  namer->set_id(id);
  namer->set_hash(hash);

  // We only want to encode the last path-segment of 'name'.
  // Note that this block of code could be avoided if all call-sites
  // put subdirectory info in the 'path' argument, but it turns out
  // to be a lot more convenient for tests if we allow relative paths
  // in the 'name' argument for this method, so the one-time effort of
  // teasing out the leaf and encoding that saves a whole lot of clutter
  // in, at least, CacheExtenderTest.
  //
  // Note that this can only be done for 1-element name_vectors.
  // TODO(jmarantz): Modify this to work with combining across paths.
  for (int i = 0, n = name_vector.size(); i < n; ++i) {
    const GoogleString& name = name_vector[i];
    CHECK(name.find('/') == GoogleString::npos) << "No slashes should be "
        "found in " << name << " but we found at least one.  "
        "Put it in the path";
  }

  // Note: This uses an empty context, so no custom parameters like image
  // dimensions can be passed in.
  ResourceContext dummy_context;
  ImageUrlEncoder::SetWebpAndMobileUserAgent(*rewrite_driver(), &dummy_context);
  const UrlSegmentEncoder* encoder = FindEncoder(id);
  GoogleString encoded_name;
  encoder->Encode(name_vector, &dummy_context, &encoded_name);
  namer->set_name(encoded_name);
  namer->set_ext(ext);
}

const UrlSegmentEncoder* RewriteTestBase::FindEncoder(
    const StringPiece& id) const {
  RewriteFilter* filter = rewrite_driver_->FindFilter(id);
  return (filter == NULL) ? &default_encoder_ : filter->encoder();
}

GoogleString RewriteTestBase::Encode(const StringPiece& path,
                                     const StringPiece& id,
                                     const StringPiece& hash,
                                     const StringVector& name_vector,
                                     const StringPiece& ext) {
  return EncodeWithBase(kTestDomain, path, id, hash, name_vector, ext);
}

GoogleString RewriteTestBase::EncodeNormal(
    const StringPiece& path,
    const StringPiece& id,
    const StringPiece& hash,
    const StringVector& name_vector,
    const StringPiece& ext) {
  ResourceNamer namer;
  EncodePathAndLeaf(id, hash, name_vector, ext, &namer);
  return StrCat(path, namer.Encode());
}

GoogleString RewriteTestBase::EncodeWithBase(
    const StringPiece& base,
    const StringPiece& path,
    const StringPiece& id,
    const StringPiece& hash,
    const StringVector& name_vector,
    const StringPiece& ext) {
  if (factory()->use_test_url_namer() &&
      !TestUrlNamer::UseNormalEncoding() &&
      !options()->domain_lawyer()->can_rewrite_domains() &&
      !path.empty()) {
    ResourceNamer namer;
    EncodePathAndLeaf(id, hash, name_vector, ext, &namer);
    GoogleUrl path_gurl(path);
    if (path_gurl.IsWebValid()) {
      return TestUrlNamer::EncodeUrl(base, path_gurl.Origin(),
                                     path_gurl.PathSansLeaf(), namer);
    } else {
      return TestUrlNamer::EncodeUrl(base, "", path, namer);
    }
  }

  return EncodeNormal(path, id, hash, name_vector, ext);
}

GoogleString RewriteTestBase::AddOptionsToEncodedUrl(
    const StringPiece& url, const StringPiece& options) {
  ResourceNamer namer;
  CHECK(rewrite_driver()->Decode(url, &namer));
  namer.set_options(options);
  return namer.Encode();
}

GoogleString RewriteTestBase::EncodeImage(
    int width, int height,
    StringPiece filename, StringPiece hash, StringPiece rewritten_ext) {
  // filename starts as just the leaf filename, ex: foo.png
  ResourceContext params;
  // Use width, height < 0 to indicate none set.
  if (width >= 0) {
    params.mutable_desired_image_dims()->set_width(width);
  }
  if (height >= 0) {
    params.mutable_desired_image_dims()->set_height(height);
  }

  // Encoder inserts image dimensions, ex: 10x20xfoo.png
  ImageUrlEncoder encoder;
  GoogleString encoded_name;
  encoder.Encode(MultiUrl(filename), &params, &encoded_name);

  // Namer encodes into .pagespeed. format,
  // ex: 10x20xfoo.png.pagespeed.ic.0.png
  ResourceNamer namer;
  namer.set_id("ic");
  namer.set_hash(hash);
  namer.set_name(encoded_name);
  namer.set_ext(rewritten_ext);

  return namer.Encode();
}

// Helper function which instantiates an encoder, collects the
// required arguments and calls the virtual Encode().
GoogleString RewriteTestBase::EncodeCssName(const StringPiece& name,
                                            bool supports_webp,
                                            bool can_inline) {
  CssUrlEncoder encoder;
  ResourceContext resource_context;
  resource_context.set_inline_images(can_inline);
  if (supports_webp) {
    // TODO(vchudnov): Deal with webp lossless.
    resource_context.set_libwebp_level(ResourceContext::LIBWEBP_LOSSY_ONLY);
  }
  StringVector urls;
  GoogleString encoded_url;
  name.CopyToString(StringVectorAdd(&urls));
  encoder.Encode(urls, &resource_context, &encoded_url);
  return encoded_url;
}

GoogleString RewriteTestBase::ChangeSuffix(
    StringPiece old_url, bool append_new_suffix,
    StringPiece old_suffix, StringPiece new_suffix) {
  if (!StringCaseEndsWith(old_url, old_suffix)) {
    ADD_FAILURE() << "Can't seem to find old extension!";
    return GoogleString();
  }

  if (append_new_suffix) {
    return StrCat(old_url, new_suffix);
  } else {
    return StrCat(
        old_url.substr(0, old_url.length() - old_suffix.length()),
        new_suffix);
  }
}

void RewriteTestBase::SetupWaitFetcher() {
  factory_->SetupWaitFetcher();
}

void RewriteTestBase::CallFetcherCallbacks() {
  factory_->CallFetcherCallbacksForDriver(rewrite_driver_);
  rewrite_driver_->Clear();
  // Since we call Clear() on the driver, give it a new request context.
  rewrite_driver_->set_request_context(CreateRequestContext());
}

void RewriteTestBase::OtherCallFetcherCallbacks() {
  other_factory_->CallFetcherCallbacksForDriver(other_rewrite_driver_);
  // This calls Clear() on the driver, so give it a new request context.
  other_rewrite_driver_->set_request_context(CreateRequestContext());
}

void RewriteTestBase::SetRewriteOptions(RewriteOptions* opts) {
  TestRewriteOptionsManager* trom = new TestRewriteOptionsManager();
  trom->set_options(opts);
  server_context()->SetRewriteOptionsManager(trom);
}

void RewriteTestBase::SetUseManagedRewriteDrivers(
    bool use_managed_rewrite_drivers) {
  use_managed_rewrite_drivers_ = use_managed_rewrite_drivers;
}

RequestContextPtr RewriteTestBase::CreateRequestContext() {
  return RequestContext::NewTestRequestContextWithTimer(
      factory_->thread_system(), timer());
}

RewriteDriver* RewriteTestBase::MakeDriver(
    ServerContext* server_context, RewriteOptions* options) {
  // We use unmanaged drivers rather than NewCustomDriver here so
  // that _test.cc files can add options after the driver was created
  // and before the filters are added.
  //
  // TODO(jmarantz): Change call-sites to make this use a more standard flow.
  RewriteDriver* rd;
  if (!use_managed_rewrite_drivers_) {
    rd = server_context->NewUnmanagedRewriteDriver(
        NULL /* custom options, so no pool*/, options,
        CreateRequestContext());
    rd->set_externally_managed(true);
  } else {
    rd = server_context->NewCustomRewriteDriver(options,
                                                CreateRequestContext());
  }

  return rd;
}

void RewriteTestBase::TestRetainExtraHeaders(
    const StringPiece& name,
    const StringPiece& filter_id,
    const StringPiece& ext) {
  GoogleString url = AbsolutifyUrl(name);

  // Add some extra headers.
  AddToResponse(url, HttpAttributes::kEtag, "Custom-Etag");
  AddToResponse(url, "extra", "attribute");
  AddToResponse(url, HttpAttributes::kSetCookie, "Custom-Cookie");

  GoogleString content;
  ResponseHeaders response;

  GoogleString rewritten_url = Encode("", filter_id, "0", name, ext);
  ASSERT_TRUE(FetchResourceUrl(StrCat(kTestDomain, rewritten_url),
                               &content, &response));

  // Extra non-blacklisted header is preserved.
  ConstStringStarVector v;
  ASSERT_TRUE(response.Lookup("extra", &v));
  ASSERT_EQ(1U, v.size());
  EXPECT_STREQ("attribute", *v[0]);

  // Note: These tests can fail if ResourceManager::FetchResource failed to
  // rewrite the resource and instead served the original.
  // TODO(sligocki): Add a check that we successfully rewrote the resource.

  // Blacklisted headers are stripped (or changed).
  EXPECT_FALSE(response.Lookup(HttpAttributes::kSetCookie, &v));

  ASSERT_TRUE(response.Lookup(HttpAttributes::kEtag, &v));
  ASSERT_EQ(1U, v.size());
  EXPECT_STREQ("W/\"0\"", *v[0]);
}

void RewriteTestBase::ClearStats() {
  statistics()->Clear();
  if (lru_cache() != NULL) {
    lru_cache()->ClearStats();
  }
  counting_url_async_fetcher()->Clear();
  counting_distributed_fetcher()->Clear();
  other_factory_->counting_url_async_fetcher()->Clear();
  other_factory_->counting_distributed_async_fetcher()->Clear();
  file_system()->ClearStats();
  rewrite_driver()->set_request_context(CreateRequestContext());
}

void RewriteTestBase::ClearRewriteDriver() {
  request_attribute_names_.clear();
  request_attribute_values_.clear();
  rewrite_driver()->Clear();
  rewrite_driver()->set_request_context(CreateRequestContext());
  other_rewrite_driver()->Clear();
  other_rewrite_driver()->set_request_context(CreateRequestContext());
}

void RewriteTestBase::SetCacheDelayUs(int64 delay_us) {
  factory_->mock_time_cache()->set_delay_us(delay_us);
}

void RewriteTestBase::SetUseTestUrlNamer(bool use_test_url_namer) {
  factory_->SetUseTestUrlNamer(use_test_url_namer);
  server_context_->set_url_namer(factory_->url_namer());
  other_factory_->SetUseTestUrlNamer(use_test_url_namer);
  other_server_context_->set_url_namer(other_factory_->url_namer());
}

namespace {

class BlockingResourceCallback : public Resource::AsyncCallback {
 public:
  explicit BlockingResourceCallback(const ResourcePtr& resource)
      : Resource::AsyncCallback(resource),
        done_(false),
        success_(false) {
  }
  virtual ~BlockingResourceCallback() {}
  virtual void Done(bool lock_failure, bool resource_ok) {
    done_ = true;
    success_ = !lock_failure && resource_ok;
  }
  bool done() const { return done_; }
  bool success() const { return success_; }

 private:
  bool done_;
  bool success_;
};

class DeferredResourceCallback : public Resource::AsyncCallback {
 public:
  explicit DeferredResourceCallback(const ResourcePtr& resource)
      : Resource::AsyncCallback(resource) {
  }
  virtual ~DeferredResourceCallback() {}
  virtual void Done(bool lock_failure, bool resource_ok) {
    CHECK(!lock_failure && resource_ok);
    delete this;
  }
};

class HttpCallback : public HTTPCache::Callback {
 public:
  explicit HttpCallback(const RequestContextPtr& request_context)
      : HTTPCache::Callback(request_context, RequestHeaders::Properties()),
        done_(false),
        options_(NULL) {
  }
  virtual ~HttpCallback() {}
  virtual bool IsCacheValid(const GoogleString& key,
                            const ResponseHeaders& headers) {
    if (options_ == NULL) {
      return true;
    }
    return OptionsAwareHTTPCacheCallback::IsCacheValid(
        key, *options_, request_context(), headers);
  }
  virtual void Done(HTTPCache::FindResult find_result) {
    done_ = true;
    result_ = find_result;
  }
  virtual ResponseHeaders::VaryOption RespectVaryOnResources() const {
    return ResponseHeaders::kRespectVaryOnResources;
  }

  bool done() const { return done_; }
  HTTPCache::FindResult result() { return result_; }
  void set_options(const RewriteOptions* options) { options_ = options; }

 private:
  bool done_;
  HTTPCache::FindResult result_;
  const RewriteOptions* options_;
};

}  // namespace

bool RewriteTestBase::ReadIfCached(const ResourcePtr& resource) {
  BlockingResourceCallback callback(resource);
  resource->LoadAsync(Resource::kReportFailureIfNotCacheable,
                      rewrite_driver()->request_context(),
                      &callback);
  CHECK(callback.done());
  if (callback.success()) {
    CHECK(resource->loaded());
  }
  return callback.success();
}

void RewriteTestBase::InitiateResourceRead(
    const ResourcePtr& resource) {
  DeferredResourceCallback* callback = new DeferredResourceCallback(resource);
  resource->LoadAsync(Resource::kReportFailureIfNotCacheable,
                      rewrite_driver()->request_context(),
                      callback);
}

HTTPCache::FindResult RewriteTestBase::HttpBlockingFindWithOptions(
    const RewriteOptions* options,
    const GoogleString& key, HTTPCache* http_cache, HTTPValue* value_out,
    ResponseHeaders* headers) {
  HttpCallback callback(CreateRequestContext());
  if (options != NULL) {
    callback.set_options(options);
  }
  callback.set_response_headers(headers);
  http_cache->Find(
      key, rewrite_driver_->CacheFragment(), message_handler(), &callback);
  CHECK(callback.done());
  value_out->Link(callback.http_value());
  return callback.result();
}

HTTPCache::FindResult RewriteTestBase::HttpBlockingFind(
    const GoogleString& key, HTTPCache* http_cache, HTTPValue* value_out,
    ResponseHeaders* headers) {
  return HttpBlockingFindWithOptions(NULL, key, http_cache, value_out, headers);
}

HTTPCache::FindResult RewriteTestBase::HttpBlockingFindStatus(
    const GoogleString& key, HTTPCache* http_cache) {
  HTTPValue value_out;
  ResponseHeaders response_headers;
  return HttpBlockingFind(key, http_cache, &value_out, &response_headers);
}

void RewriteTestBase::SetMimetype(const StringPiece& mimetype) {
  rewrite_driver()->set_response_headers_ptr(&response_headers_);
  response_headers_.Add(HttpAttributes::kContentType, mimetype);
  response_headers_.ComputeCaching();
}

void RewriteTestBase::SetupSharedCache() {
  other_server_context_->set_http_cache(
      new HTTPCache(factory_->delay_cache(), factory_->timer(),
                    factory_->hasher(), factory_->statistics()));
  other_server_context_->set_metadata_cache(factory_->delay_cache());
  // Also make sure to share the timer.
  other_server_context_->set_timer(server_context_->timer());
}

void RewriteTestBase::CheckFetchFromHttpCache(
    StringPiece url,
    StringPiece expected_contents,
    int64 expected_expiration_ms) {
  GoogleString contents;
  ResponseHeaders response;
  ClearStats();
  EXPECT_TRUE(FetchResourceUrl(url, &contents, &response)) << url;
  EXPECT_STREQ(expected_contents, contents);
  EXPECT_EQ(expected_expiration_ms, response.CacheExpirationTimeMs());
  EXPECT_TRUE(response.IsProxyCacheable(
      RequestHeaders::Properties(),
      ResponseHeaders::GetVaryOption(options()->respect_vary()),
      ResponseHeaders::kNoValidator));
  EXPECT_EQ(1, http_cache()->cache_hits()->Get());
  EXPECT_EQ(0, http_cache()->cache_misses()->Get());
  EXPECT_EQ(0, http_cache()->cache_inserts()->Get());
  EXPECT_EQ(1, static_cast<int>(lru_cache()->num_hits()));
  EXPECT_EQ(0, static_cast<int>(lru_cache()->num_misses()));
  EXPECT_EQ(0, static_cast<int>(lru_cache()->num_inserts()));
}

void RewriteTestBase::SetActiveServer(ActiveServerFlag server_to_use) {
  if (active_server_ != server_to_use) {
    factory_.swap(other_factory_);
    std::swap(server_context_, other_server_context_);
    std::swap(rewrite_driver_, other_rewrite_driver_);
    std::swap(options_, other_options_);
    active_server_ = server_to_use;

    // If we have just swapped from a driver with an initialized writer to one
    // without an initialized writer, we have to initialize the new one ourself
    // because HtmlParseTestBaseNoAlloc::SetupWriter initializes once only, so
    // won't do it for the new one, resulting in fetched content not going to
    // the output_ data member, causing ValidateExpected calls to fail horribly.
    if (html_writer_filter_.get() != NULL &&
        other_html_writer_filter_.get() == NULL) {
      other_html_writer_filter_.reset(new HtmlWriterFilter(html_parse()));
      other_html_writer_filter_->set_writer(&write_to_string_);
      html_parse()->AddFilter(other_html_writer_filter_.get());
    }
  }
}

void RewriteTestBase::AdvanceTimeUs(int64 delay_us) {
  mock_scheduler()->AdvanceTimeUs(delay_us);
}

void RewriteTestBase::SetTimeUs(int64 time_us) {
  mock_scheduler()->SetTimeUs(time_us);
}

void RewriteTestBase::AdjustTimeUsWithoutWakingAlarms(int64 time_us) {
  factory_->mock_timer()->SetTimeUs(time_us);
}

const RequestTimingInfo& RewriteTestBase::timing_info() {
  CHECK(rewrite_driver()->request_context().get() != NULL);
  return rewrite_driver()->request_context()->timing_info();
}

RequestTimingInfo* RewriteTestBase::mutable_timing_info() {
  CHECK(rewrite_driver()->request_context().get() != NULL);
  return rewrite_driver()->request_context()->mutable_timing_info();
}

LoggingInfo* RewriteTestBase::logging_info() {
  CHECK(rewrite_driver()->request_context().get() != NULL);
  return rewrite_driver()->request_context()->log_record()->logging_info();
}

GoogleString RewriteTestBase::AppliedRewriterStringFromLog() {
  CHECK(rewrite_driver()->request_context().get() != NULL);
  ScopedMutex lock(rewrite_driver()->request_context()->log_record()->mutex());
  return rewrite_driver()->request_context()->
    log_record()->AppliedRewritersString();
}

void RewriteTestBase::VerifyRewriterInfoEntry(
    AbstractLogRecord* log_record, const GoogleString& id, int url_index,
    int rewriter_info_index, int rewriter_info_size, int url_list_size,
    const GoogleString& url) {
  ScopedMutex lock(log_record->mutex());
  EXPECT_GE(log_record->logging_info()->rewriter_info_size(),
            rewriter_info_size);
  const RewriterInfo& rewriter_info =
      log_record->logging_info()->rewriter_info(rewriter_info_index);
  EXPECT_STREQ(id, rewriter_info.id());
  EXPECT_TRUE(rewriter_info.has_rewrite_resource_info());
  EXPECT_EQ(url_index,
      rewriter_info.rewrite_resource_info().original_resource_url_index());
  EXPECT_EQ(url_list_size,
            log_record->logging_info()->resource_url_info().url_size());
  EXPECT_EQ(url,
      log_record->logging_info()->resource_url_info().url(url_index));
}

bool RewriteTestBase::AddDomain(StringPiece domain) {
  bool frozen = options_->ClearSignatureForTesting();
  bool ret = options_->WriteableDomainLawyer()->AddDomain(
      domain, message_handler());
  if (frozen) {
    server_context()->ComputeSignature(options_);
  }
  return ret;
}

bool RewriteTestBase::AddOriginDomainMapping(StringPiece to_domain,
                                             StringPiece from_domain) {
  bool frozen = options_->ClearSignatureForTesting();
  bool ret = options_->WriteableDomainLawyer()->AddOriginDomainMapping(
      to_domain, from_domain, "", message_handler());
  if (frozen) {
    server_context()->ComputeSignature(options_);
  }
  return ret;
}

bool RewriteTestBase::AddRewriteDomainMapping(StringPiece to_domain,
                                              StringPiece from_domain) {
  bool frozen = options_->ClearSignatureForTesting();
  bool ret = options_->WriteableDomainLawyer()->AddRewriteDomainMapping(
      to_domain, from_domain, message_handler());
  if (frozen) {
    server_context()->ComputeSignature(options_);
  }
  return ret;
}

bool RewriteTestBase::AddShard(StringPiece domain, StringPiece shards) {
  bool frozen = options_->ClearSignatureForTesting();
  bool ret = options_->WriteableDomainLawyer()->AddShard(
      domain, shards, message_handler());
  if (frozen) {
    server_context()->ComputeSignature(options_);
  }
  return ret;
}

void RewriteTestBase::SetMockLogRecord() {
  rewrite_driver_->set_request_context(
      RequestContext::NewTestRequestContext(new MockLogRecord(
          factory()->thread_system()->NewMutex())));
}

MockLogRecord* RewriteTestBase::mock_log_record() {
  return dynamic_cast<MockLogRecord*>(rewrite_driver_->log_record());
}

GoogleString RewriteTestBase::GetLazyloadScriptHtml() {
  return StrCat(
      "<script type=\"text/javascript\" data-pagespeed-no-defer>",
      LazyloadImagesFilter::GetLazyloadJsSnippet(
          options(), server_context()->static_asset_manager()),
      "</script>");
}

GoogleString RewriteTestBase::GetLazyloadPostscriptHtml() {
  return StrCat(
      "<script type=\"text/javascript\" data-pagespeed-no-defer>",
        LazyloadImagesFilter::kOverrideAttributeFunctions,
      "</script>");
}

void RewriteTestBase::SetCacheInvalidationTimestamp() {
  options()->ClearSignatureForTesting();
  // Make sure the time is different, since otherwise we may end up with
  // re-fetches resulting in re-inserts rather than inserts.
  AdvanceTimeMs(Timer::kSecondMs);
  int64 now_ms = timer()->NowMs();
  options()->UpdateCacheInvalidationTimestampMs(now_ms);
  options()->ComputeSignature();
  AdvanceTimeMs(Timer::kSecondMs);
}

void RewriteTestBase::SetCacheInvalidationTimestampForUrl(
    StringPiece url, bool ignores_metadata_and_pcache) {
  options()->ClearSignatureForTesting();
  // Make sure the time is different, since otherwise we may end up with
  // re-fetches resulting in re-inserts rather than inserts.
  AdvanceTimeMs(Timer::kSecondMs);
  options()->AddUrlCacheInvalidationEntry(url, timer()->NowMs(),
                                          ignores_metadata_and_pcache);
  options()->ComputeSignature();
  AdvanceTimeMs(Timer::kSecondMs);
}

void RewriteTestBase::EnableCachePurge() {
  options()->ClearSignatureForTesting();
  options()->set_enable_cache_purge(true);
  options()->ComputeSignature();
}

void RewriteTestBase::EnableDebug() {
  options()->ClearSignatureForTesting();
  options()->EnableFilter(RewriteOptions::kDebug);
  options()->ComputeSignature();
}

GoogleString RewriteTestBase::DebugMessage(StringPiece url) {
  GoogleString result(debug_message_);
  GoogleUrl test_domain(kTestDomain);
  GoogleUrl gurl(test_domain, url);
  if (gurl.IsAnyValid()) {
    // Resolves vs test_domain to a valid absolute url.  Use that.
    GlobalReplaceSubstring("%url%", gurl.Spec(), &result);
  } else {
    // Couldn't resolve to a valid url, just use string as passed in.
    GlobalReplaceSubstring("%url%", url, &result);
  }
  return result;
}

GoogleString RewriteTestBase::ExpectedNonce() {
  GoogleString result;
  StringPiece nonce_piece(reinterpret_cast<char*>(&expected_nonce_),
                          sizeof(expected_nonce_));
  Web64Encode(nonce_piece, &result);
  result.resize(11);
  ++expected_nonce_;
  return result;
}

const ProcessContext& RewriteTestBase::process_context() {
  return rewrite_test_base_process_context;
}

int RewriteTestBase::TimedValue(StringPiece name) {
  return statistics()->GetTimedVariable(name)->Get(TimedVariable::START);
}

}  // namespace net_instaweb
