/*
 * 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: abliss@google.com (Adam Bliss)

// Base class for tests which want a ServerContext.

#ifndef NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_TEST_BASE_H_
#define NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_TEST_BASE_H_

#include <utility>
#include <vector>

#include "net/instaweb/http/public/http_cache.h"
#include "net/instaweb/http/public/http_value.h"
#include "net/instaweb/http/public/logging_proto.h"
#include "net/instaweb/http/public/logging_proto_impl.h"
#include "net/instaweb/http/public/mock_url_fetcher.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/rewriter/public/resource.h"
#include "net/instaweb/rewriter/public/resource_namer.h"
// We need to include rewrite_driver.h due to covariant return of html_parse()
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "net/instaweb/rewriter/public/test_distributed_fetcher.h"
#include "net/instaweb/rewriter/public/test_rewrite_driver_factory.h"
#include "net/instaweb/util/public/mock_property_page.h"
#include "net/instaweb/util/public/property_cache.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/hasher.h"
#include "pagespeed/kernel/base/md5_hasher.h"
#include "pagespeed/kernel/base/mem_file_system.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/mock_hasher.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
// We need to include mock_timer.h to allow upcast to Timer*.
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/timer.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/http_names.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/http/user_agent_matcher.h"
#include "pagespeed/kernel/util/url_segment_encoder.h"
#include "pagespeed/opt/logging/request_timing_info.h"



namespace net_instaweb {

class AbstractLogRecord;
class CountingUrlAsyncFetcher;
class DelayCache;
class LRUCache;
class MockLogRecord;
class MockScheduler;
class ProcessContext;
class RewriteFilter;
class WaitUrlAsyncFetcher;

class RewriteOptionsTestBase : public HtmlParseTestBaseNoAlloc {
 protected:
  RewriteOptionsTestBase() {
    RewriteOptions::Initialize();
  }
  ~RewriteOptionsTestBase() {
    RewriteOptions::Terminate();
  }
};

class RewriteTestBase : public RewriteOptionsTestBase {
 public:
  static const char kTestData[];    // Testdata directory.

  // Beaconing key values used when downstream caching is enabled.
  static const char kConfiguredBeaconingKey[];
  static const char kWrongBeaconingKey[];

  // Specifies which server should be "active" in that rewrites and fetches
  // will use it. The data members affected are those returned by:
  // - factory() / other_factory()
  // - server_context() / other_server_context()
  // - rewrite_driver() / other_rewrite_driver()
  // - options() / other_options()
  enum ActiveServerFlag {
    kPrimary,    // Use the normal data members.
    kSecondary,  // Use all the other_ data members.
  };

  RewriteTestBase();
  explicit RewriteTestBase(Statistics* statistics);

  // Specifies alternate factories to be initialized on construction.
  // By default, TestRewriteDriverFactory is used, but you can employ
  // your own subclass of TestRewriteDriverFactory using this
  // constructor.  If you do, you probably also want to override
  // MakeTestFactory.
  explicit RewriteTestBase(std::pair<TestRewriteDriverFactory*,
                                     TestRewriteDriverFactory*> factories);
  virtual ~RewriteTestBase();

  virtual void SetUp();
  virtual void TearDown();

  // In this set of tests, we will provide explicit body tags, so
  // the test harness should not add them in for our convenience.
  // It can go ahead and add the <html> and </html>, however.
  virtual bool AddBody() const { return false; }

  // Makes a TestRewriteDriverFactory.  This can be overridden in
  // subclasses if you need a factory with special properties.
  //
  // TODO(jmarantz): This is currently only used in
  // ServeResourceFromNewContext, but should be used for factory_ and
  // other_factory_.  This would requuire a refactor, because those
  // are created at construction; too early for subclass overrides to
  // take effect.  To deal with that, an alternate constructor is
  // provided above so that the proper sort of factories can be passed in.
  virtual TestRewriteDriverFactory* MakeTestFactory();

  // Adds kRecompressJpeg, kRecompressPng, kRecompressWebp, kConvertPngToJpeg,
  // kConvertJpegToWebp and kConvertGifToPng.
  void AddRecompressImageFilters();

  // Add a single rewrite filter to rewrite_driver_.
  void AddFilter(RewriteOptions::Filter filter);

  // Add a single rewrite filter to other_rewrite_driver_.
  void AddOtherFilter(RewriteOptions::Filter filter);

  // Add a custom rewrite filter (one without a corresponding option)
  // to rewrite_driver and enable it.
  void AddRewriteFilter(RewriteFilter* filter);

  // Adds a custom rewriter filter but does not register it for HTML
  // rewriting, only for fetches.
  void AddFetchOnlyRewriteFilter(RewriteFilter* filter);

  // Add a custom rewrite filter (one without a corresponding option)
  // to other_rewrite_driver and enable it.
  void AddOtherRewriteFilter(RewriteFilter* filter);

  // Sets the active context URL for purposes of XS checks of fetches
  // on the main rewrite driver.
  void SetBaseUrlForFetch(const StringPiece& url);

  // Populates request-headers based on the current user-agent and
  // the attributes added via AddRequestAttribute and installs them
  // into rewrite_driver_.
  void SetDriverRequestHeaders();

  // Enable downstream caching feature and set up the downstream cache
  // rebeaconing key.
  void SetDownstreamCacheDirectives(
    StringPiece downstream_cache_purge_method,
    StringPiece downstream_cache_purge_location_prefix,
    StringPiece rebeaconing_key);

  // Set ShouldBeacon request header to the specified value.
  void SetShouldBeaconHeader(StringPiece rebeaconing_key);

  ResourcePtr CreateResource(const StringPiece& base, const StringPiece& url);

  // Returns the main factory Timer*, which can be used for calling NowUs and
  // NowMs.  To set the time, use (Advance|Set)Time(Ms|Us), which wake up any
  // scheduler alarms.  See also AdjustTimeUsWithoutWakingAlarms which should
  // be used with extreme care.
  Timer* timer() { return factory()->mock_timer(); }

  // Append default headers to the given string.
  void AppendDefaultHeaders(const ContentType& content_type,
                            GoogleString* text);

  // Like above, but also include a Link: <..>; rel="canonical" header.
  void AppendDefaultHeadersWithCanonical(const ContentType& content_type,
                                         StringPiece canonical_url,
                                         GoogleString* text);

  // Append default headers to the given string, including
  // X-Original-Content-Length for tests that depend on this.
  void AppendDefaultHeaders(const ContentType& content_type,
                            int64 original_content_length,
                            GoogleString* text);

  void ServeResourceFromManyContexts(const GoogleString& resource_url,
                                     const StringPiece& expected_content);

  void ServeResourceFromManyContextsWithUA(
      const GoogleString& resource_url,
      const StringPiece& expected_content,
      const StringPiece& user_agent);

  // Test that a resource can be served from an new server that has not already
  // constructed it.
  void ServeResourceFromNewContext(
      const GoogleString& resource_url,
      const StringPiece& expected_content);

  // This definition is required by HtmlParseTestBase which defines this as
  // pure abstract, so that the test subclass can define how it instantiates
  // HtmlParse.
  virtual RewriteDriver* html_parse() { return rewrite_driver_; }

  // Set default headers for a resource with content_type and Cache ttl_sec.
  void DefaultResponseHeaders(const ContentType& content_type, int64 ttl_sec,
                              ResponseHeaders* response_headers);

  // 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 FetchResource(const StringPiece& path, const StringPiece& filter_id,
                     const StringPiece& name, const StringPiece& ext,
                     GoogleString* content);
  bool FetchResource(const StringPiece& path, const StringPiece& filter_id,
                     const StringPiece& name, const StringPiece& ext,
                     GoogleString* content, ResponseHeaders* response);

  bool FetchResourceUrl(const StringPiece& url, GoogleString* content,
                        ResponseHeaders* response);
  bool FetchResourceUrl(const StringPiece& url,
                        RequestHeaders* request_headers,
                        GoogleString* content,
                        ResponseHeaders* response_headers);
  bool FetchResourceUrl(const StringPiece& url, GoogleString* content);

  // Just check if we can fetch a resource successfully, ignore response.
  bool TryFetchResource(const StringPiece& url);

  // Use managed rewrite drivers for the test so that we see the same behavior
  // in tests that we see in real servers. By default, tests use unmanaged
  // drivers so that _test.cc files can add options after the driver was created
  // and before the filters are added.
  void SetUseManagedRewriteDrivers(bool use_managed_rewrite_drivers);

  GoogleString CssLinkHref(const StringPiece& url) {
    return StrCat("<link rel=stylesheet href=", url, ">");
  }

  // Representation for a CSS <link> tag.
  class CssLink {
   public:
    CssLink(const StringPiece& url, const StringPiece& content,
            const StringPiece& media, bool supply_mock);

    // A vector of CssLink* should know how to accumulate and add.
    class Vector : public std::vector<CssLink*> {
     public:
      ~Vector();
      void Add(const StringPiece& url, const StringPiece& content,
               const StringPiece& media, bool supply_mock);
    };

    // Parses a combined CSS elementand provides the segments from which
    // it came.
    bool DecomposeCombinedUrl(StringPiece base_url, GoogleString* base,
                              StringVector* segments, MessageHandler* handler);

    GoogleString url_;
    GoogleString content_;
    GoogleString media_;
    bool supply_mock_;
  };

  // Collects the hrefs for all CSS <link>s on the page.
  void CollectCssLinks(const StringPiece& id, const StringPiece& html,
                       StringVector* css_links);

  // Collects all information about CSS links into a CssLink::Vector.
  void CollectCssLinks(const StringPiece& id, const StringPiece& html,
                       CssLink::Vector* css_links);

  // Encode the given name (path + leaf) using the given pagespeed attributes.
  void EncodePathAndLeaf(const StringPiece& filter_id,
                         const StringPiece& hash,
                         const StringVector& name_vector,
                         const StringPiece& ext,
                         ResourceNamer* namer);

  StringVector MultiUrl(const StringPiece& url1) {
    StringVector v;
    v.push_back(url1.as_string());
    return v;
  }

  StringVector MultiUrl(const StringPiece& url1, const StringPiece& url2) {
    StringVector v;
    v.push_back(url1.as_string());
    v.push_back(url2.as_string());
    return v;
  }

  StringVector MultiUrl(const StringPiece& url1, const StringPiece& url2,
                        const StringPiece& url3) {
    StringVector v;
    v.push_back(url1.as_string());
    v.push_back(url2.as_string());
    v.push_back(url3.as_string());
    return v;
  }

  StringVector MultiUrl(const StringPiece& url1, const StringPiece& url2,
                        const StringPiece& url3, const StringPiece& url4) {
    StringVector v;
    v.push_back(url1.as_string());
    v.push_back(url2.as_string());
    v.push_back(url3.as_string());
    v.push_back(url4.as_string());
    return v;
  }

  // Helper function to encode a resource name from its pieces using whatever
  // encoding we are testing, either UrlNamer or TestUrlNamer.
  GoogleString Encode(const StringPiece& path,
                      const StringPiece& filter_id,
                      const StringPiece& hash,
                      const StringPiece& name,
                      const StringPiece& ext) {
    return Encode(path, filter_id, hash, MultiUrl(name), ext);
  }
  GoogleString Encode(const StringPiece& path,
                      const StringPiece& filter_id,
                      const StringPiece& hash,
                      const StringVector& name_vector,
                      const StringPiece& ext);

  // Same as Encode but specifically using UrlNamer not TestUrlNamer.
  GoogleString EncodeNormal(const StringPiece& path,
                            const StringPiece& filter_id,
                            const StringPiece& hash,
                            const StringPiece& name,
                            const StringPiece& ext) {
    return EncodeNormal(path, filter_id, hash, MultiUrl(name), ext);
  }
  GoogleString EncodeNormal(const StringPiece& path,
                            const StringPiece& filter_id,
                            const StringPiece& hash,
                            const StringVector& name_vector,
                            const StringPiece& ext);

  // Same as Encode but specifying the base URL (which is used by TestUrlNamer
  // but is unused by UrlNamer so for it results in exactly the same as Encode).
  GoogleString EncodeWithBase(const StringPiece& base,
                              const StringPiece& path,
                              const StringPiece& filter_id,
                              const StringPiece& hash,
                              const StringPiece& name,
                              const StringPiece& ext) {
    return EncodeWithBase(base, path, filter_id, hash, MultiUrl(name), ext);
  }
  GoogleString EncodeWithBase(const StringPiece& base,
                              const StringPiece& path,
                              const StringPiece& filter_id,
                              const StringPiece& hash,
                              const StringVector& name_vector,
                              const StringPiece& ext);

  // Encode image with width and height. Use -1 for either width or height to
  // omit it from the encoding.
  GoogleString EncodeImage(int width, int height,
                           StringPiece filename, StringPiece hash,
                           StringPiece rewritten_ext);

  // Takes an already-encoded URL and adds options to to it.
  GoogleString AddOptionsToEncodedUrl(const StringPiece& url,
                                      const StringPiece& options);

  // If append_new_suffix is true, appends new_suffix to old_url.
  // If append_new_suffix is false, replaces old_suffix at the end of old_url
  // with new_suffix.
  // Either way, precondition: old_url ends with old_suffix
  static GoogleString ChangeSuffix(
      StringPiece old_url, bool append_new_suffix,
      StringPiece old_suffix, StringPiece new_suffix);

  // Overrides the async fetcher on the primary context to be a
  // wait fetcher which permits delaying callback invocation.
  // CallFetcherCallbacks can then be called to let the fetches complete
  // and call the callbacks.
  void SetupWaitFetcher();
  void CallFetcherCallbacks();
  void OtherCallFetcherCallbacks();
  RewriteOptions* options() const { return options_; }
  RewriteOptions* other_options() const { return other_options_; }

  // Set the RewriteOptions to be returned by the RewriteOptionsManager.
  void SetRewriteOptions(RewriteOptions* opts);

  // Authorizes a domain to options()->domain_lawyer(), recomputing
  // the options signature if necessary.
  bool AddDomain(StringPiece domain);

  // Adds an origin domain mapping to options()->domain_lawyer(), recomputing
  // the options signature if necessary.
  bool AddOriginDomainMapping(StringPiece to_domain, StringPiece from_domain);

  // Adds a rewrite domain mapping to options()->domain_lawyer(), recomputing
  // the options signature if necessary.
  bool AddRewriteDomainMapping(StringPiece to_domain, StringPiece from_domain);

  // Adds a shard to options()->domain_lawyer(), recomputing the options
  // signature if necessary.
  bool AddShard(StringPiece domain, StringPiece shards);

  // Helper method to test all manner of resource serving from a filter.
  void 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);

  // Check that when we have a cache miss for a pagespeed resource we set
  // headers to reduce the chance of it being interpreted as html.
  void ValidateFallbackHeaderSanitization(StringPiece filter_id);

  TestRewriteDriverFactory* factory() { return factory_.get(); }
  TestRewriteDriverFactory* other_factory() { return other_factory_.get(); }

  void UseMd5Hasher() {
    server_context_->set_hasher(&md5_hasher_);
    server_context_->http_cache()->set_hasher(&md5_hasher_);
    other_server_context_->set_hasher(&md5_hasher_);
    other_server_context_->http_cache()->set_hasher(&md5_hasher_);
  }


  void SetDefaultLongCacheHeaders(const ContentType* content_type,
                                  ResponseHeaders* header) {
    server_context_->SetDefaultLongCacheHeaders(
        content_type, StringPiece(), StringPiece(), header);
  }

  void SetFetchResponse(const StringPiece& url,
                        const ResponseHeaders& response_header,
                        const StringPiece& response_body) {
    mock_url_fetcher()->SetResponse(url, response_header, response_body);
  }

  // Add content to mock fetcher (with default headers).
  void SetResponseWithDefaultHeaders(const StringPiece& relative_url,
                                     const ContentType& content_type,
                                     const StringPiece& content,
                                     int64 ttl_sec);

  // Load a test file (from testdata/) into 'contents', returning false on
  // failure.
  bool LoadFile(const StringPiece& filename, GoogleString* contents);

  // Add the contents of a file to mock fetcher (with default headers).
  void AddFileToMockFetcher(const StringPiece& url,
                            const StringPiece& filename,
                            const ContentType& content_type, int64 ttl_sec);

  void AddToResponse(const StringPiece& url,
                     const StringPiece& name,
                     const StringPiece& value) {
    mock_url_fetcher()->AddToResponse(url, name, value);
  }

  void SetFetchResponse404(const StringPiece& url);

  void SetFetchFailOnUnexpected(bool fail) {
    mock_url_fetcher()->set_fail_on_unexpected(fail);
  }
  void FetcherUpdateDateHeaders() {
    mock_url_fetcher()->set_timer(timer());
    mock_url_fetcher()->set_update_date_headers(true);
  }
  void ClearFetcherResponses() { mock_url_fetcher()->Clear(); }

  virtual void ClearStats();

  // Calls Clear() on the rewrite driver and does any other necessary
  // clean-up so the driver is okay for a test to reuse.
  //
  // Removes pending request-header attributes added via AddRequestAttribute.
  void ClearRewriteDriver();

  MockUrlFetcher* mock_url_fetcher() {
    return &mock_url_fetcher_;
  }
  TestDistributedFetcher* test_distributed_fetcher() {
    return &test_distributed_fetcher_;
  }
  Hasher* hasher() { return server_context_->hasher(); }
  DelayCache* delay_cache() { return factory_->delay_cache(); }
  LRUCache* lru_cache() { return factory_->lru_cache(); }
  Statistics* statistics() { return factory_->statistics(); }
  MemFileSystem* file_system() { return factory_->mem_file_system(); }
  HTTPCache* http_cache() { return server_context_->http_cache(); }
  PropertyCache* page_property_cache() {
    return server_context_->page_property_cache();
  }
  MockMessageHandler* message_handler() {
    return factory_->mock_message_handler();
  }

  // TODO(jmarantz): These abstractions are not satisfactory long-term
  // where we want to have driver-lifetime in tests be reflective of
  // how servers work.  But for now we use these accessors.
  //
  // Note that the *rewrite_driver() methods are not valid during
  // construction, so any test classes that need to use them must
  // do so from SetUp() methods.
  RewriteDriver* rewrite_driver() { return rewrite_driver_; }
  RewriteDriver* other_rewrite_driver() { return other_rewrite_driver_; }

  // The scheduler used by rewrite_driver
  MockScheduler* mock_scheduler() { return factory_->mock_scheduler(); }

  int64 start_time_ms() const { return factory_->kStartTimeMs; }

  bool ReadFile(const char* filename, GoogleString* contents) {
    return file_system()->ReadFile(filename, contents, message_handler());
  }
  bool WriteFile(const char* filename, const StringPiece& contents) {
    return file_system()->WriteFile(filename, contents, message_handler());
  }

  ServerContext* server_context() { return server_context_; }
  ServerContext* other_server_context() { return other_server_context_; }
  CountingUrlAsyncFetcher* counting_url_async_fetcher() {
    return factory_->counting_url_async_fetcher();
  }
  CountingUrlAsyncFetcher* counting_distributed_fetcher() {
    return factory_->counting_distributed_async_fetcher();
  }
  void SetMockHashValue(const GoogleString& value) {
    factory_->mock_hasher()->set_hash_value(value);
  }

  void SetCacheDelayUs(int64 delay_us);

  // Creates a RewriteDriver using the passed-in options, object, but
  // does *not* finalize the driver.  This gives individual _test.cc
  // files the chance to add filters to the options prior to calling
  // driver->AddFilters().
  RewriteDriver* MakeDriver(ServerContext* server_context,
                            RewriteOptions* options);

  // Converts a potentially relative URL off kTestDomain to absolute if needed.
  GoogleString AbsolutifyUrl(const StringPiece& in);

  // Tests that non-caching-related response-header attributes are propagated
  // to output resources.
  //
  // 'name' is the name of the resource.
  void TestRetainExtraHeaders(const StringPiece& name,
                              const StringPiece& filter_id,
                              const StringPiece& ext);

  // Find the segment-encoder for the filter found via 'id'.  Some
  // test filters are not registered with RewriteDriver so for those
  // we use the default encoder.
  const UrlSegmentEncoder* FindEncoder(const StringPiece& id) const;

  // Switch url namers as specified.
  void SetUseTestUrlNamer(bool use_test_url_namer);

  // Helper function which instantiates an encoder, collects the
  // required arguments and calls the virtual Encode().
  GoogleString EncodeCssName(const StringPiece& name,
                             bool supports_webp,
                             bool can_inline);

  // Helper function for legacy tests that used this now-extinct interface.
  // In general we don't support this flow in production but we rely on it
  // in tests for obliquely covering some cases relating to resource pathnames.
  bool ReadIfCached(const ResourcePtr& resource);

  // Variation on ReadIfCached that is used when we expect the resource
  // not to be in present in cache, but instead we are looking to
  // initiate the resource-rewrite process so that a subsequent call
  // to ReadIfCached succeeds.
  void InitiateResourceRead(const ResourcePtr& resource);

  // While our production cache model is non-blocking, we use an in-memory LRU
  // for tests that calls its callback directly from Get.  Thus we can make
  // a convenient blocking cache wrapper to make it easier to write tests.
  HTTPCache::FindResult HttpBlockingFind(
      const GoogleString& key, HTTPCache* http_cache, HTTPValue* value_out,
      ResponseHeaders* headers);

  // The same as the above function, but doesn't need an HTTPValue or
  // ResponseHeaders.
  HTTPCache::FindResult HttpBlockingFindStatus(
      const GoogleString& key, HTTPCache* http_cache);

  // Same as above, but with options (for invalidation checks)
  HTTPCache::FindResult HttpBlockingFindWithOptions(
      const RewriteOptions* options,
      const GoogleString& key, HTTPCache* http_cache, HTTPValue* value_out,
      ResponseHeaders* headers);

  // Sets the response-headers Content-Type to "application/xhtml+xml".
  void SetXhtmlMimetype() { SetMimetype("application/xhtml+xml"); }

  // Sets the response-headers Content-Type to "text/html".
  void SetHtmlMimetype() { SetMimetype("text/html"); }

  // Sets the response-headers Content-Type as specified.
  void SetMimetype(const StringPiece& mimetype);

  // Verifies that the specified URL can be fetched from HTTP cache, and that
  // its cache TTL and contents are as specified.
  void CheckFetchFromHttpCache(
      StringPiece url,
      StringPiece expected_contents,
      int64 expected_expiration_ms);

  // Setup statistics for the given cohort and add it to the give PropertyCache.
  const PropertyCache::Cohort*  SetupCohort(
      PropertyCache* cache, const GoogleString& cohort) {
    return factory()->SetupCohort(cache, cohort);
  }

  // Configure the other_server_context_ to use the same LRU cache as the
  // primary server context.
  void SetupSharedCache();

  // Returns a new mock property page for the page property cache.
  MockPropertyPage* NewMockPage(const StringPiece& url,
                                const StringPiece& options_signature_hash,
                                UserAgentMatcher::DeviceType device_type) {
    return new MockPropertyPage(
        server_context_->thread_system(),
        server_context_->page_property_cache(),
        url,
        options_signature_hash,
        UserAgentMatcher::DeviceTypeSuffix(device_type));
  }

  MockPropertyPage* NewMockPage(const StringPiece& url) {
    return NewMockPage(url, "hash", UserAgentMatcher::kDesktop);
  }

  // Sets MockLogRecord in the driver's request_context.
  void SetMockLogRecord();

  // Returns the MockLogRecord in the driver.
  MockLogRecord* mock_log_record();

  // Helper methods to return js/html snippets related to lazyload images.
  GoogleString GetLazyloadScriptHtml();
  GoogleString GetLazyloadPostscriptHtml();

  // Sets the server-scoped invalidation timestamp.  Time is advanced by
  // 1 second both before and after invalidation.  E.g. if the current time
  // is 100000 milliseconds at the time this is called, the invalidation
  // timestamp will be at 101000 milliseconds, and time will be rolled
  // forward to 102000 on exit from this function.
  void SetCacheInvalidationTimestamp();

  // Sets the invalidation timestamp for a URL pattern.  Time is advanced by
  // in the same manner as for SetCacheInvalidationTimestamp above.
  void SetCacheInvalidationTimestampForUrl(
      StringPiece url, bool ignores_metadata_and_pcache);

  // Changes the way cache-purges are implemented for non-wildcards to
  // avoid flushing the entire metadata cache and instead match each
  // metadata Input against the invalidation-set.
  void EnableCachePurge();

  // Enables the debug flag, which is often done on a test-by-test basis.
  void EnableDebug();

  // Enable debugging and set expected_debug_message used by DebugMessage.
  // Occurrences of %url% in the message will be replaced by the argument
  // to DebugMessage.
  void DebugWithMessage(StringPiece expected_debug_message) {
    EnableDebug();

    expected_debug_message.CopyToString(&debug_message_);
  }

  // Return the debug message if it was set by DebugWithMessage, empty string
  // otherwise.  Inserts url for %url% if needed, attempting to resolve it
  // against kTestDomain first, and using url exactly as passed if resolving it
  // doesn't return a valid url.
  GoogleString DebugMessage(StringPiece url);

  // Returns a process context needed for any tests to instantiate factories
  // explicitly.
  static const ProcessContext& process_context();

 protected:
  // Common values for HttpBlockingFind* result.
  const HTTPCache::FindResult kFoundResult;
  const HTTPCache::FindResult kNotFoundResult;

  void Init();

  // Override this if the test fixture needs to use a different RequestContext
  // subclass.
  virtual RequestContextPtr CreateRequestContext();

  // Calls callbacks on given wait fetcher, making sure to properly synchronize
  // with async rewrite flows given driver.
  void CallFetcherCallbacksForDriver(WaitUrlAsyncFetcher* fetcher,
                                     RewriteDriver* driver);

  // Populate the given headers based on the content type and original
  // content length information.
  void PopulateDefaultHeaders(const ContentType& content_type,
                              int64 original_content_length,
                              ResponseHeaders* headers);

  // Set the "active" server to that specified; the active server is used for
  // rewriting and serving pages.
  void SetActiveServer(ActiveServerFlag server_to_use);

  // Advances time forward using the mock scheduler.  Note that time is not
  // advanced directly in the mock_timer; the scheduler must be used.
  void AdvanceTimeUs(int64 delay_ms);
  void AdvanceTimeMs(int64 delay_ms) { AdvanceTimeUs(delay_ms * Timer::kMsUs); }
  void SetTimeUs(int64 time_us);
  void SetTimeMs(int64 time_ms) { SetTimeUs(time_ms * Timer::kMsUs); }

  // Adjusts time ignoring any scheduler callbacks.  Use with caution.
  void AdjustTimeUsWithoutWakingAlarms(int64 time_us);

  // Accessor for TimingInfo.
  const RequestTimingInfo& timing_info();
  RequestTimingInfo* mutable_timing_info();

  // Convenience method to pull the logging info proto out of the current
  // request context's log record. The request context owns the log record, and
  // if the log record has a non-NULL mutex, it will need to be locked
  // for this call.
  LoggingInfo* logging_info();

  // Convenience method to extract read-only metadata_cache_info.
  const MetadataCacheInfo& metadata_cache_info() {
    return logging_info()->metadata_cache_info();
  }

  // Convenience method for retrieving the computed applied rewriters string
  // from the current request context's log record. Thread-safe.
  GoogleString AppliedRewriterStringFromLog();

  // Convenience method for verifying that the rewriter info entries have
  // expected values.
  void 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);

  // Sets current_user_agent_
  void SetCurrentUserAgent(const StringPiece& user_agent) {
    current_user_agent_ = user_agent;
  }

  // Sets up user-agent and request-header to allow webp processing.
  void SetupForWebp() {
    SetCurrentUserAgent("webp");
    AddRequestAttribute(HttpAttributes::kAccept, "image/webp");
  }

  void SetupForWebpLossless() {
    SetCurrentUserAgent("webp-la");
    AddRequestAttribute(HttpAttributes::kAccept, "image/webp");
  }

  void SetupForWebpAnimated() {
    SetCurrentUserAgent("webp-animated");
    AddRequestAttribute(HttpAttributes::kAccept, "image/webp");
  }

  // Adds an attribute to be populated later into a RequestHeaders* object,
  // along with the user-agent.  Note that these attributes stay in the
  // test-class until ClearRewriteDriver is called.
  void AddRequestAttribute(StringPiece name, StringPiece value);

  // Populates a RequestHeaders* object with al
  void PopulateRequestHeaders(RequestHeaders* request_headers);

  // Override HtmlParseTestBaseNoAlloc::ParseUrl to populate the
  // request-headers into rewrite_driver_ before running filters.
  virtual void ParseUrl(StringPiece url, StringPiece html_input);

  GoogleString ExpectedNonce();

  // When reaching into a cache that backs an HTTP cache you need a cache key
  // that includes the fragment.
  GoogleString HttpCacheKey(StringPiece url) {
    return http_cache()->CompositeKey(url, rewrite_driver_->CacheFragment());
  }

  // Returns the value of a TimedVariable, specified by name.
  int TimedValue(StringPiece name);

  // The mock fetchers & stats are global across all Factories used in the
  // tests.
  MockUrlFetcher mock_url_fetcher_;
  TestDistributedFetcher test_distributed_fetcher_;
  scoped_ptr<Statistics> statistics_;

  // We have two independent RewriteDrivers representing two completely
  // separate servers for the same domain (say behind a load-balancer).
  //
  // Server A runs rewrite_driver_ and will be used to rewrite pages and
  // serves the rewritten resources.
  scoped_ptr<TestRewriteDriverFactory> factory_;
  scoped_ptr<TestRewriteDriverFactory> other_factory_;
  ServerContext* server_context_;
  RewriteDriver* rewrite_driver_;
  ServerContext* other_server_context_;
  RewriteDriver* other_rewrite_driver_;
  scoped_ptr<HtmlWriterFilter> other_html_writer_filter_;
  ActiveServerFlag active_server_;
  bool use_managed_rewrite_drivers_;
  StringPiece current_user_agent_;
  StringVector request_attribute_names_;
  StringVector request_attribute_values_;

  MD5Hasher md5_hasher_;

  RewriteOptions* options_;  // owned by rewrite_driver_.
  RewriteOptions* other_options_;  // owned by other_rewrite_driver_.
  UrlSegmentEncoder default_encoder_;
  ResponseHeaders response_headers_;
  const GoogleString kEtag0;  // Etag with a 0 hash.
  uint64 expected_nonce_;

  GoogleString debug_message_;  // Message used by DebugMessage

 private:
  void ValidateFallbackHeaderSanitizationHelper(
      StringPiece filter_id, StringPiece origin_content_type, bool expect_load);
};

}  // namespace net_instaweb

#endif  // NET_INSTAWEB_REWRITER_PUBLIC_REWRITE_TEST_BASE_H_
