/*
 * Copyright 2013 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: morlovich@google.com (Maksim Orlovich)

#include "net/instaweb/rewriter/public/cacheable_resource_base.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/mock_url_fetcher.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/rewriter/cached_result.pb.h"
#include "net/instaweb/rewriter/public/mock_resource_callback.h"
#include "net/instaweb/rewriter/public/resource.h"  // for Resource, etc
#include "net/instaweb/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_test_base.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
#include "pagespeed/kernel/base/ref_counted_ptr.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string.h"  // for GoogleString
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/cache/lru_cache.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"

namespace net_instaweb {

namespace {

const char kTestUrl[] = "http://www.example.com/";
const char kTestRef[] = "http://www.example.com/some_page";
const char kContent[] = "content!";

class TestResource : public CacheableResourceBase {
 public:
  explicit TestResource(RewriteDriver* rewrite_driver)
      : CacheableResourceBase("test", kTestUrl, kTestUrl, NULL, rewrite_driver),
        cache_key_(kTestUrl),
        do_prepare_request_(false),
        do_prepare_response_(false) {
  }

  static void InitStats(Statistics* stats) {
    CacheableResourceBase::InitStats("test", stats);
  }

  virtual GoogleString cache_key() const { return cache_key_; }
  void set_cache_key(StringPiece ck) {
    ck.CopyToString(&cache_key_);
  }

  virtual void PrepareRequest(const RequestContextPtr& request_context,
                              RequestHeaders* headers) {
    if (do_prepare_request_) {
      // To test that this gets invoked properly, we set the referer header
      // since MockUrlFetcher records those.
      headers->Replace(HttpAttributes::kReferer, kTestRef);
      request_context->AddSessionAuthorizedFetchOrigin(kTestUrl);
    }
  }

  virtual void PrepareResponseHeaders(ResponseHeaders* headers) {
    if (do_prepare_response_) {
      headers->Remove(HttpAttributes::kCacheControl, "private");
    }
  }

  void set_do_prepare_request(bool x) {
    do_prepare_request_ = x;
  }

  void set_do_prepare_response(bool x) {
    do_prepare_response_ = x;
  }

  // Wipe any loaded values, but not the configuration.
  void Reset() {
    HTTPValue empty_value;
    // Don't want it to totally empty, or it won't get set.
    empty_value.Write("", server_context()->message_handler());
    Link(&empty_value, server_context()->message_handler());
    LinkFallbackValue(&empty_value);
  }

 protected:
  GoogleString cache_key_;
  bool do_prepare_request_;
  bool do_prepare_response_;
};

class MockFreshenCallback : public Resource::FreshenCallback {
 public:
  MockFreshenCallback(const ResourcePtr& resource,
                      InputInfo* input_info)
      : FreshenCallback(resource),
        input_info_(input_info),
        done_(false),
        extend_success_(false) {
  }

  virtual InputInfo* input_info() { return input_info_; }

  virtual void Done(bool lock_failure, bool extend_success) {
    done_ = true;
    extend_success_ = extend_success;
  }

  bool done() const { return done_; }
  bool extend_success() const { return extend_success_; }

 private:
  InputInfo* input_info_;
  bool done_;
  bool extend_success_;
};

}  // namespace

class CacheableResourceBaseTest : public RewriteTestBase {
 protected:
  virtual void SetUp() {
    RewriteTestBase::SetUp();
    TestResource::InitStats(server_context()->statistics());

    resource_.reset(new TestResource(rewrite_driver()));
  }

  void CheckStats(TestResource* resource,
                  int expect_hits,
                  int expect_recent_fetch_failures,
                  int expect_recent_uncacheables_miss,
                  int expect_recent_uncacheables_failure,
                  int expect_misses) {
    EXPECT_EQ(expect_hits,
              resource->hits_->Get());
    EXPECT_EQ(expect_recent_fetch_failures,
              resource->recent_fetch_failures_->Get());
    EXPECT_EQ(expect_recent_uncacheables_miss,
              resource->recent_uncacheables_miss_->Get());
    EXPECT_EQ(expect_recent_uncacheables_failure,
              resource->recent_uncacheables_failure_->Get());
    EXPECT_EQ(expect_misses,
              resource->misses_->Get());
  }

  RefCountedPtr<TestResource> resource_;
};

TEST_F(CacheableResourceBaseTest, BasicCached) {
  SetResponseWithDefaultHeaders(kTestUrl, kContentTypeText,
                                kContent, 1000);

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_TRUE(callback.done());
  EXPECT_TRUE(callback.success());
  EXPECT_EQ(kContent, resource_->ExtractUncompressedContents());
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 0, 0, 0, 0, 1);

  // 2nd read should be cached.
  resource_->Reset();
  MockResourceCallback callback2(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback2);
  EXPECT_TRUE(callback2.done());
  EXPECT_TRUE(callback2.success());
  EXPECT_EQ(kContent, resource_->ExtractUncompressedContents());
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 1, 0, 0, 0, 1);

  // Make sure freshening happens. The rest resource is set to 1000 sec ttl,
  // so forward time 900 seconds ahead.
  AdvanceTimeMs(900 * Timer::kSecondMs);
  resource_->Reset();
  MockResourceCallback callback3(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback3);
  EXPECT_TRUE(callback3.done());
  EXPECT_TRUE(callback3.success());
  EXPECT_EQ(kContent, resource_->ExtractUncompressedContents());
  // Freshening resulted in an extra fetch
  EXPECT_EQ(2, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 2, 0, 0, 0, 1);
}

TEST_F(CacheableResourceBaseTest, Fallback) {
  options()->set_serve_stale_if_fetch_error(true);
  mock_url_fetcher()->Disable();
  mock_url_fetcher()->set_error_message("oww!");

  ResponseHeaders ok_response_headers;
  SetDefaultLongCacheHeaders(&kContentTypeText, &ok_response_headers);

  HTTPValue fallback;
  fallback.SetHeaders(&ok_response_headers);
  EXPECT_TRUE(fallback.Write("fallback", server_context()->message_handler()));
  EXPECT_TRUE(fallback.Flush(server_context()->message_handler()));
  resource_->LinkFallbackValue(&fallback);

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_TRUE(callback.done());
  EXPECT_TRUE(callback.success());
  EXPECT_STREQ("fallback", resource_->ExtractUncompressedContents());
  EXPECT_EQ(kFetchStatusOtherError, resource_->fetch_response_status());
}

TEST_F(CacheableResourceBaseTest, FallbackEmpty) {
  // Regression test. This used to CHECK-fail in some intermediate revisions.
  options()->set_serve_stale_if_fetch_error(true);
  mock_url_fetcher()->Disable();
  mock_url_fetcher()->set_error_message("oww!");

  ResponseHeaders ok_response_headers;
  SetDefaultLongCacheHeaders(&kContentTypeText, &ok_response_headers);

  HTTPValue fallback;
  fallback.SetHeaders(&ok_response_headers);
  EXPECT_TRUE(fallback.Write("", server_context()->message_handler()));
  EXPECT_TRUE(fallback.Flush(server_context()->message_handler()));
  resource_->LinkFallbackValue(&fallback);

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_TRUE(callback.done());
  EXPECT_TRUE(callback.success());
  EXPECT_STREQ("", resource_->ExtractUncompressedContents());
  EXPECT_EQ(kFetchStatusOtherError, resource_->fetch_response_status());
}

TEST_F(CacheableResourceBaseTest, Private) {
  ResponseHeaders response_headers;
  SetDefaultLongCacheHeaders(&kContentTypeText, &response_headers);
  response_headers.Add(HttpAttributes::kCacheControl, "private");
  SetFetchResponse(kTestUrl, response_headers, kContent);

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());

  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_TRUE(callback.done());
  EXPECT_FALSE(callback.success());
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 0, 0, 0, 0, 1);

  // The non-cacheability should be cached.
  resource_->Reset();
  MockResourceCallback callback2(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback2);
  EXPECT_TRUE(callback2.done());
  EXPECT_FALSE(callback2.success());
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 0, 0, 0, 1, 1);
}

TEST_F(CacheableResourceBaseTest, PrivateForFetch) {
  // This test private + kLoadEvenIfNotCacheable.
  ResponseHeaders response_headers;
  SetDefaultLongCacheHeaders(&kContentTypeText, &response_headers);
  response_headers.Add(HttpAttributes::kCacheControl, "private");
  SetFetchResponse(kTestUrl, response_headers, kContent);

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());

  resource_->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_TRUE(callback.done());
  EXPECT_TRUE(callback.success());
  EXPECT_EQ(kContent, resource_->ExtractUncompressedContents());
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 0, 0, 0, 0, 1);

  // Since it's non-cacheable, but we have kLoadEvenIfNotCacheable
  // set, we should re-fetch it.
  resource_->Reset();
  MockResourceCallback callback2(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  resource_->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback2);
  EXPECT_TRUE(callback2.done());
  EXPECT_TRUE(callback2.success());
  EXPECT_EQ(kContent, resource_->ExtractUncompressedContents());
  EXPECT_EQ(2, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 0, 0, 1, 0, 1);
}

TEST_F(CacheableResourceBaseTest, FetchFailure) {
  SetFetchFailOnUnexpected(false);
  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());

  resource_->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_TRUE(callback.done());
  EXPECT_FALSE(callback.success());
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 0, 0, 0, 0, 1);

  // Failure should get cached, and we should take advantage of it.
  resource_->Reset();
  MockResourceCallback callback2(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  resource_->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback2);
  EXPECT_TRUE(callback2.done());
  EXPECT_FALSE(callback2.success());
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 0, 1, 0, 0, 1);

  // Now advance time, should force a refetch.
  int64 remember_sec = server_context()->http_cache()->failure_caching_ttl_sec(
                           kFetchStatusOtherError);
  AdvanceTimeMs(2 * remember_sec * Timer::kSecondMs);
  resource_->Reset();
  MockResourceCallback callback3(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  resource_->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback3);
  EXPECT_TRUE(callback3.done());
  EXPECT_FALSE(callback3.success());
  EXPECT_EQ(2, counting_url_async_fetcher()->fetch_count());
  CheckStats(resource_.get(), 0, 1, 0, 0, 2);
}

TEST_F(CacheableResourceBaseTest, DropHandling) {
  // First have mock fetcher emulate a drop.
  ResponseHeaders not_found;
  SetDefaultLongCacheHeaders(&kContentTypeHtml, &not_found);
  not_found.SetStatusAndReason(HttpStatus::kUnavailable);
  not_found.Add(HttpAttributes::kXPsaLoadShed, "1");
  SetFetchResponse("http://www.example.com/", not_found, "hmm");

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());

  resource_->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_TRUE(callback.done());
  EXPECT_FALSE(resource_->IsValidAndCacheable());

  resource_->Reset();

  // Now have the fetch result in a 200.
  ResponseHeaders found;
  SetDefaultLongCacheHeaders(&kContentTypeCss, &found);
  found.SetStatusAndReason(HttpStatus::kOK);
  SetFetchResponse("http://www.example.com/", found, "* {display: stylish; }");

  // Still cached since background fetch.
  MockResourceCallback callback2(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());

  resource_->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback2);
  EXPECT_TRUE(callback2.done());
  EXPECT_FALSE(resource_->IsValidAndCacheable());
  resource_->Reset();

  // Marked as a non-background, will retry.
  resource_->set_is_background_fetch(false);
  MockResourceCallback callback3(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());

  resource_->LoadAsync(Resource::kLoadEvenIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback3);
  EXPECT_TRUE(callback3.done());
  EXPECT_TRUE(resource_->IsValidAndCacheable());
}

TEST_F(CacheableResourceBaseTest, FreshenInfo) {
  SetResponseWithDefaultHeaders(kTestUrl, kContentTypeText,
                                kContent, 1000);

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  EXPECT_TRUE(callback.done());
  EXPECT_TRUE(callback.success());

  InputInfo input_info;
  resource_->FillInPartitionInputInfo(Resource::kIncludeInputHash,
                                      &input_info);
  InputInfo input_info2 = input_info;

  // Move time ahead so freshening actually does something.
  AdvanceTimeMs(900 * Timer::kSecondMs);

  MockFreshenCallback freshen_cb(ResourcePtr(resource_.get()), &input_info);
  resource_->Freshen(&freshen_cb, message_handler());
  EXPECT_EQ(2, counting_url_async_fetcher()->fetch_count());

  EXPECT_TRUE(freshen_cb.done());
  EXPECT_TRUE(freshen_cb.extend_success());

  // Expiration time must have moved ahead, too.
  EXPECT_EQ(1000 * Timer::kSecondMs + timer()->NowMs(),
            input_info.expiration_time_ms());

  // The above freshened from fetches, now we should be able to do it
  // from cache as well.
  MockFreshenCallback freshen_cb2(ResourcePtr(resource_.get()), &input_info2);
  resource_->Freshen(&freshen_cb2, message_handler());
  EXPECT_EQ(2, counting_url_async_fetcher()->fetch_count());
  EXPECT_TRUE(freshen_cb.done());
  EXPECT_TRUE(freshen_cb.extend_success());
  EXPECT_EQ(1000 * Timer::kSecondMs + timer()->NowMs(),
            input_info2.expiration_time_ms());
}

TEST_F(CacheableResourceBaseTest, SameUrlDifferentKey) {
  SetResponseWithDefaultHeaders(kTestUrl, kContentTypeText,
                                kContent, 1000);

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback);
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());
  EXPECT_TRUE(callback.done());
  EXPECT_TRUE(callback.success());

  RefCountedPtr<TestResource> resource2(new TestResource(rewrite_driver()));
  resource2->set_cache_key("http://other_key.org/");
  MockResourceCallback callback2(ResourcePtr(resource2.get()),
                                server_context()->thread_system());
  resource2->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback2);
  // 2 fetches, since we are using different keys.
  EXPECT_EQ(2, counting_url_async_fetcher()->fetch_count());
  EXPECT_TRUE(callback2.done());
  EXPECT_TRUE(callback2.success());

  // Both should be cached successfully now.
  resource_->Reset();
  MockResourceCallback callback3(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback3);
  EXPECT_EQ(2, counting_url_async_fetcher()->fetch_count());
  EXPECT_TRUE(callback3.done());
  EXPECT_TRUE(callback3.success());

  // Delete resource's cache entry to make sure that #2 is really using
  // something different.
  lru_cache()->Delete(HttpCacheKey(kTestUrl));

  // Re-fetch r1, to make sure the delete worked
  resource_->Reset();
  MockResourceCallback callback4(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback4);
  EXPECT_EQ(3, counting_url_async_fetcher()->fetch_count());
  EXPECT_TRUE(callback4.done());
  EXPECT_TRUE(callback4.success());

  // Now fetch r2, should still be hashed.
  resource2->Reset();
  MockResourceCallback callback5(ResourcePtr(resource2.get()),
                                 server_context()->thread_system());
  resource2->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback5);
  EXPECT_EQ(3, counting_url_async_fetcher()->fetch_count());
  EXPECT_TRUE(callback.done());
  EXPECT_TRUE(callback.success());

  // Now test freshening, with both ops happening simultaneously to make
  // sure the locking is correct.
  SetupWaitFetcher();
  InputInfo input_info, input2_info;
  resource_->FillInPartitionInputInfo(Resource::kIncludeInputHash,
                                      &input_info);
  resource2->FillInPartitionInputInfo(Resource::kIncludeInputHash,
                                      &input2_info);

  AdvanceTimeMs(900 * Timer::kSecondMs);

  MockFreshenCallback freshen_cb(ResourcePtr(resource_.get()), &input_info);
  resource_->Freshen(&freshen_cb, message_handler());

  MockFreshenCallback freshen2_cb(ResourcePtr(resource2.get()), &input2_info);
  resource2->Freshen(&freshen2_cb, message_handler());

  CallFetcherCallbacks();

  EXPECT_EQ(5, counting_url_async_fetcher()->fetch_count());
  EXPECT_EQ(1000 * Timer::kSecondMs + timer()->NowMs(),
            input_info.expiration_time_ms());

  EXPECT_EQ(1000 * Timer::kSecondMs + timer()->NowMs(),
            input2_info.expiration_time_ms());
}

TEST_F(CacheableResourceBaseTest, PrepareHooks) {
  // Test to see that PrepareRequest works.
  SetResponseWithDefaultHeaders(kTestUrl, kContentTypeText,
                                kContent, 1000);

  MockResourceCallback callback(ResourcePtr(resource_.get()),
                                server_context()->thread_system());
  RequestContextPtr request_context(
      RequestContext::NewTestRequestContext(server_context()->thread_system()));
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       request_context, &callback);
  EXPECT_TRUE(callback.done());
  EXPECT_TRUE(callback.success());
  EXPECT_EQ(kContent, resource_->ExtractUncompressedContents());
  EXPECT_EQ(1, counting_url_async_fetcher()->fetch_count());

  // w/o the hook
  EXPECT_EQ("", mock_url_fetcher()->last_referer());
  EXPECT_FALSE(request_context->IsSessionAuthorizedFetchOrigin(kTestUrl));

  // now turn the hook on.
  resource_->Reset();
  resource_->set_do_prepare_request(true);
  lru_cache()->Delete(HttpCacheKey(kTestUrl));
  MockResourceCallback callback2(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());
  RequestContextPtr request_context2(
      RequestContext::NewTestRequestContext(server_context()->thread_system()));
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       request_context2, &callback2);
  EXPECT_TRUE(callback2.done());
  EXPECT_TRUE(callback2.success());
  EXPECT_EQ(kContent, resource_->ExtractUncompressedContents());
  EXPECT_EQ(2, counting_url_async_fetcher()->fetch_count());

  // the PrepareRequest() hook should have changed the referrer.
  EXPECT_EQ(kTestRef, mock_url_fetcher()->last_referer());

  // ... And authorized a domain
  EXPECT_TRUE(request_context2->IsSessionAuthorizedFetchOrigin(kTestUrl));

  // Now test with and without PrepareResponseHeaders

  // Set up a private resource.
  ResponseHeaders response_headers;
  SetDefaultLongCacheHeaders(&kContentTypeText, &response_headers);
  response_headers.Add(HttpAttributes::kCacheControl, "private");
  SetFetchResponse(kTestUrl, response_headers, kContent);

  MockResourceCallback callback3(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());

  resource_->Reset();
  lru_cache()->Delete(HttpCacheKey(kTestUrl));
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback3);
  EXPECT_TRUE(callback3.done());
  // By default, fetch fails.
  EXPECT_FALSE(callback3.success());
  EXPECT_EQ(3, counting_url_async_fetcher()->fetch_count());
  // Note: can't check response_headers here since resource wasn't loaded.

  // Now try with a PrepareResponseHeaders removing cache-control: private
  lru_cache()->Delete(HttpCacheKey(kTestUrl));
  resource_->set_do_prepare_response(true);
  MockResourceCallback callback4(ResourcePtr(resource_.get()),
                                 server_context()->thread_system());

  resource_->Reset();
  resource_->LoadAsync(Resource::kReportFailureIfNotCacheable,
                       RequestContext::NewTestRequestContext(
                           server_context()->thread_system()),
                       &callback4);
  EXPECT_TRUE(callback4.done());
  EXPECT_TRUE(callback4.success());  // due to messing with headers.
  EXPECT_FALSE(resource_->response_headers()->HasValue(
                   HttpAttributes::kCacheControl, "private"));
  EXPECT_EQ(4, counting_url_async_fetcher()->fetch_count());
}

}  // namespace net_instaweb
