/*
 * Copyright 2012 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: mdw@google.com (Matt Welsh)

// Unit-tests for ProxyFetch and related classes

#include "pagespeed/automatic/proxy_fetch.h"

#include "base/logging.h"
#include "net/instaweb/http/public/log_record.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/rewriter/public/rewrite_driver.h"
#include "net/instaweb/rewriter/public/rewrite_options.h"
#include "net/instaweb/rewriter/public/rewrite_test_base.h"
#include "net/instaweb/rewriter/public/server_context.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/null_message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/html/html_parse_test_base.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/thread/thread_synchronizer.h"
#include "pagespeed/kernel/thread/worker_test_base.h"
#include "pagespeed/kernel/util/platform.h"

namespace net_instaweb {

// A stripped-down mock of ProxyFetch, used for testing PropertyCacheComplete().
class MockProxyFetch : public ProxyFetch {
 public:
  MockProxyFetch(AsyncFetch* async_fetch,
                 ProxyFetchFactory* factory,
                 ServerContext* server_context)
      : ProxyFetch("http://www.google.com", false,
                   NULL,  // callback
                   async_fetch,
                   NULL,  // no original content fetch
                   GetNewRewriteDriver(server_context, async_fetch),
                   server_context,
                   NULL,  // timer
                   factory),
        complete_(false) {
    response_headers()->set_status_code(HttpStatus::kOK);
  }

  ~MockProxyFetch() { }

  static RewriteDriver* GetNewRewriteDriver(ServerContext* server_context,
                                     AsyncFetch* async_fetch) {
    RewriteDriver* driver = server_context->NewRewriteDriver(
                                async_fetch->request_context());
    RequestHeaders headers;
    driver->SetRequestHeaders(headers);
    return driver;
  }

  void PropertyCacheComplete(
      ProxyFetchPropertyCallbackCollector* callback_collector) {
    complete_ = true;
  }

  void Done(bool success) {
    HandleDone(success);
  }

  bool complete() const { return complete_; }

  RewriteDriver* driver() const { return driver_; }

 private:
  bool complete_;
  DISALLOW_COPY_AND_ASSIGN(MockProxyFetch);
};

// A wrapper around MockProxyFetch that manages all objects on the heap and
// initializes things for no parsing and then parses a token script. You must
// NOT call Done() on the MockProxyFetch object as we do it in our destructor.
class ManagedMockProxyFetch {
 public:
  ManagedMockProxyFetch(ServerContext* server_context,
                        bool allow_options_to_be_set_by_cookies,
                        StringPiece sticky_query_parameters,
                        StringPiece sticky_query_parameters_token,
                        StringPiece query_params, StringPiece option_cookies) {
    server_context->global_options()->ClearSignatureForTesting();
    server_context->global_options()->set_allow_options_to_be_set_by_cookies(
        allow_options_to_be_set_by_cookies);
    server_context->global_options()->set_sticky_query_parameters(
        sticky_query_parameters);
    // Suppresses parsing and the invocation of mock_proxy_fetch_->Done().
    server_context->global_options()->set_max_html_parse_bytes(0L);
    server_context->global_options()->ComputeSignature();
    message_handler_.reset(new NullMessageHandler());
    async_fetch_.reset(new StringAsyncFetch(
        RequestContext::NewTestRequestContext(
            server_context->thread_system())));
    async_fetch_->response_headers()->Add("Content-Type", "text/html");
    async_fetch_->response_headers()->ComputeCaching();
    async_fetch_->request_context()->set_sticky_query_parameters_token(
        sticky_query_parameters_token);
    fetch_factory_.reset(new ProxyFetchFactory(server_context));
    mock_proxy_fetch_ = new MockProxyFetch(async_fetch_.get(),
                                           fetch_factory_.get(),
                                           server_context);
    mock_proxy_fetch_->driver()->set_pagespeed_query_params(query_params);
    mock_proxy_fetch_->driver()->set_pagespeed_option_cookies(option_cookies);
    mock_proxy_fetch_->Write("<html>HTML</html>.", message_handler_.get());
    mock_proxy_fetch_->Flush(message_handler_.get());
  }

  ~ManagedMockProxyFetch() {
    mock_proxy_fetch_->Done(true);
  }

  MockProxyFetch* mock_proxy_fetch() const { return mock_proxy_fetch_; }

 private:
  scoped_ptr<NullMessageHandler> message_handler_;
  scoped_ptr<StringAsyncFetch> async_fetch_;
  scoped_ptr<ProxyFetchFactory> fetch_factory_;
  MockProxyFetch* mock_proxy_fetch_;  // Not scoped_ptr as it self-deletes.
};

class ProxyFetchPropertyCallbackCollectorTest : public RewriteTestBase {
 public:
  void PostLookupTask() {
    post_lookup_called_ = true;
  }
  void CheckPageNotNullPostLookupTask(
      ProxyFetchPropertyCallbackCollector* collector,
      WorkerTestBase::SyncPoint* sync_point) {
    EXPECT_TRUE(collector->fallback_property_page() != NULL);
    sync_point->Notify();
  }

  void AddCheckPageNotNullPostLookupTask(
      ProxyFetchPropertyCallbackCollector* collector,
      WorkerTestBase::SyncPoint* sync_point) {
    collector->AddPostLookupTask(MakeFunction(
        this,
        &ProxyFetchPropertyCallbackCollectorTest::
            CheckPageNotNullPostLookupTask,
        collector,
        sync_point));
  }

 protected:
  ProxyFetchPropertyCallbackCollectorTest() :
    thread_system_(Platform::CreateThreadSystem()),
    server_context_(server_context()),
    post_lookup_called_(false) {
  }

  scoped_ptr<ThreadSystem> thread_system_;
  ServerContext* server_context_;

  // Create a collector.
  ProxyFetchPropertyCallbackCollector* MakeCollector() {
    ProxyFetchPropertyCallbackCollector* collector =
        new ProxyFetchPropertyCallbackCollector(
            server_context_, RewriteTestBase::kTestDomain,
            RequestContext::NewTestRequestContext(thread_system_.get()),
            options(), UserAgentMatcher::kDesktop);
    // Collector should not contain any PropertyPages
    EXPECT_EQ(NULL, collector->ReleasePropertyPage(
        ProxyFetchPropertyCallback::kPropertyCachePage));

    return collector;
  }

  void EnableCollectorPrefix() {
    ThreadSynchronizer* sync = server_context()->thread_synchronizer();
    sync->EnableForPrefix(ProxyFetch::kCollectorDoneFinish);
    sync->EnableForPrefix(ProxyFetch::kCollectorDetachFinish);
    sync->EnableForPrefix(ProxyFetch::kCollectorConnectProxyFetchFinish);
    sync->EnableForPrefix(ProxyFetch::kCollectorRequestHeadersCompleteFinish);
  }

  // Add a callback to the collector.
  ProxyFetchPropertyCallback* AddCallback(
      ProxyFetchPropertyCallbackCollector* collector,
      ProxyFetchPropertyCallback::PageType page_type) {
    AbstractMutex* mutex = thread_system_->NewMutex();
    DCHECK(page_type == ProxyFetchPropertyCallback::kPropertyCachePage);
    ProxyFetchPropertyCallback* callback =
        new ProxyFetchPropertyCallback(
            page_type, page_property_cache(), RewriteTestBase::kTestDomain,
            "hash", UserAgentMatcher::kDesktop, collector, mutex);
    EXPECT_EQ(page_type, callback->page_type());
    collector->AddCallback(callback);
    return callback;
  }

  void AddPostLookupConnectProxyFetchCallDone(
      ProxyFetchPropertyCallbackCollector* collector,
      MockProxyFetch* mock_proxy_fetch,
      ProxyFetchPropertyCallback* callback) {
    collector->AddPostLookupTask(MakeFunction(
        this, &ProxyFetchPropertyCallbackCollectorTest::PostLookupTask));
    collector->ConnectProxyFetch(mock_proxy_fetch);
    callback->Done(true);
  }

  void ConnectProxyFetchAddPostLookupCallDone(
      ProxyFetchPropertyCallbackCollector* collector,
      MockProxyFetch* mock_proxy_fetch,
      ProxyFetchPropertyCallback* callback) {
    collector->ConnectProxyFetch(mock_proxy_fetch);
    collector->AddPostLookupTask(MakeFunction(
        this, &ProxyFetchPropertyCallbackCollectorTest::PostLookupTask));
    callback->Done(true);
  }

  void CallDoneAddPostLookupConnectProxyFetch(
      ProxyFetchPropertyCallbackCollector* collector,
      MockProxyFetch* mock_proxy_fetch,
      ProxyFetchPropertyCallback* callback) {
    callback->Done(true);
    collector->AddPostLookupTask(MakeFunction(
        this, &ProxyFetchPropertyCallbackCollectorTest::PostLookupTask));
    collector->ConnectProxyFetch(mock_proxy_fetch);
  }

  void TestAddPostlookupTask(bool add_before_done,
                             bool add_before_proxy_fetch) {
    EnableCollectorPrefix();
    scoped_ptr<ProxyFetchPropertyCallbackCollector> collector;
    collector.reset(MakeCollector());
    ProxyFetchPropertyCallback* page_callback = AddCallback(
        collector.get(), ProxyFetchPropertyCallback::kPropertyCachePage);
    ExpectStringAsyncFetch async_fetch(
        true, RequestContext::NewTestRequestContext(thread_system_.get()));
    ProxyFetchFactory factory(server_context_);
    MockProxyFetch* mock_proxy_fetch = new MockProxyFetch(
        &async_fetch, &factory, server_context_);
    if (add_before_done && add_before_proxy_fetch) {
      AddPostLookupConnectProxyFetchCallDone(
          collector.get(), mock_proxy_fetch, page_callback);
    } else if (add_before_done && !add_before_proxy_fetch) {
      ConnectProxyFetchAddPostLookupCallDone(
          collector.get(), mock_proxy_fetch, page_callback);
    } else if (!add_before_done && add_before_proxy_fetch) {
      CallDoneAddPostLookupConnectProxyFetch(
          collector.get(), mock_proxy_fetch, page_callback);
    } else {
      // Not handled. Make this fail.
    }
    collector->RequestHeadersComplete();
    EXPECT_TRUE(post_lookup_called_);
    mock_proxy_fetch->Done(true);
  }

 private:
  bool post_lookup_called_;

  DISALLOW_COPY_AND_ASSIGN(ProxyFetchPropertyCallbackCollectorTest);
};


// Test fixture for ProxyFetch.
class ProxyFetchTest : public RewriteTestBase {
};

TEST_F(ProxyFetchTest, TestInhibitParsing) {
  NullMessageHandler handler;
  server_context()->global_options()->ClearSignatureForTesting();
  server_context()->global_options()->set_max_html_parse_bytes(0L);
  server_context()->global_options()->ComputeSignature();
  StringAsyncFetch fetch(
      RequestContext::NewTestRequestContext(
          server_context()->thread_system()));
  fetch.response_headers()->Add("Content-Type", "text/html");
  fetch.response_headers()->ComputeCaching();
  ProxyFetchFactory factory(server_context_);
  MockProxyFetch* mock_proxy_fetch = new MockProxyFetch(
      &fetch, &factory, server_context());
  mock_proxy_fetch->Write("<html>HTML</html>.", &handler);
  mock_proxy_fetch->Flush(&handler);

  // We never parsed the HTML, but we did log HTML content type.
  EXPECT_FALSE(mock_proxy_fetch->started_parse_);
  {
    AbstractLogRecord* log_record =
        mock_proxy_fetch->request_context()->log_record();
    ScopedMutex lock(log_record->mutex());
    LoggingInfo* info = log_record->logging_info();
    EXPECT_TRUE(info->is_html_response());
  }

  mock_proxy_fetch->Done(true);
}

namespace {

class FlushLoggingStringAsyncFetch : public StringAsyncFetch {
 public:
  explicit FlushLoggingStringAsyncFetch(
      const RequestContextPtr& request_context)
      : StringAsyncFetch(request_context) {}

  virtual ~FlushLoggingStringAsyncFetch() {}

  bool HandleFlush(MessageHandler* handler) override {
    HandleWrite("|Flush|", handler);
    return true;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(FlushLoggingStringAsyncFetch);
};

}  // namespace

TEST_F(ProxyFetchTest, TestFollowFlushes) {
  NullMessageHandler handler;
  RewriteOptions* options = server_context()->global_options();
  options->ClearSignatureForTesting();
  options->DisableFilter(RewriteOptions::kAddHead);
  options->set_follow_flushes(true);
  options->ComputeSignature();
  FlushLoggingStringAsyncFetch fetch(
      RequestContext::NewTestRequestContext(
          server_context()->thread_system()));
  fetch.response_headers()->Add("Content-Type", "text/html");
  ProxyFetchFactory factory(server_context_);
  MockProxyFetch* mock_proxy_fetch = new MockProxyFetch(
      &fetch, &factory, server_context());
  mock_proxy_fetch->response_headers()->ComputeCaching();

  // To get a more predictable output with regard to flush markers, we wait
  // for flushes to be fully processed before continuing. ProxyFetch may
  // otherwise aggregate, reposition, or ignore induced flushes.
  mock_proxy_fetch->Write("<html><d>1</d>", &handler);
  mock_proxy_fetch->Flush(&handler);
  mock_scheduler()->AwaitQuiescence();
  mock_proxy_fetch->Write("<d>2</d></html>", &handler);
  mock_proxy_fetch->Flush(&handler);
  mock_scheduler()->AwaitQuiescence();

  // Verify we are parsing HTML.
  EXPECT_TRUE(mock_proxy_fetch->started_parse_);

  mock_proxy_fetch->Done(true);
  mock_scheduler()->AwaitQuiescence();
  EXPECT_EQ(0, server_context()->num_active_rewrite_drivers());
  EXPECT_EQ("<html><d>1</d>|Flush|<d>2</d></html>|Flush||Flush|",
            fetch.buffer());

  // Test following flushes off behaves as expected.
  options->ClearSignatureForTesting();
  options->set_follow_flushes(false);
  options->ComputeSignature();

  FlushLoggingStringAsyncFetch fetch_off(
      RequestContext::NewTestRequestContext(
          server_context()->thread_system()));
  fetch_off.response_headers()->Add("Content-Type", "text/html");

  mock_proxy_fetch = new MockProxyFetch(
      &fetch_off, &factory, server_context());
  mock_proxy_fetch->response_headers()->ComputeCaching();

  mock_proxy_fetch->Write("<html><d>1</d>", &handler);
  mock_proxy_fetch->Flush(&handler);
  mock_scheduler()->AwaitQuiescence();
  mock_proxy_fetch->Write("<d>2</d></html>", &handler);
  mock_proxy_fetch->Flush(&handler);
  mock_scheduler()->AwaitQuiescence();

  EXPECT_TRUE(mock_proxy_fetch->started_parse_);

  mock_proxy_fetch->Done(true);
  mock_scheduler()->AwaitQuiescence();
  EXPECT_EQ(0, server_context()->num_active_rewrite_drivers());
  EXPECT_EQ("<html><d>1</d><d>2</d></html>|Flush|", fetch_off.buffer());
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, EmptyCollectorTest) {
  // Test that creating an empty collector works.
  EnableCollectorPrefix();
  scoped_ptr<ProxyFetchPropertyCallbackCollector> collector;
  collector.reset(MakeCollector());
  // This should not fail
  collector->Detach(HttpStatus::kUnknownStatusCode);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, DoneBeforeDetach) {
  EnableCollectorPrefix();
  // Test that calling Done() before Detach() works.
  ProxyFetchPropertyCallbackCollector* collector = MakeCollector();
  ProxyFetchPropertyCallback* callback = AddCallback(
      collector, ProxyFetchPropertyCallback::kPropertyCachePage);

  // callback->IsCacheValid could be called anytime before callback->Done.
  // Will return true because there are no cache invalidation URL patterns.
  EXPECT_TRUE(callback->IsCacheValid(1L));

  // Invoke the callback.
  callback->Done(true);

  // Collector should now have a page property.
  scoped_ptr<AbstractPropertyPage> page;
  page.reset(collector->ReleaseFallbackPropertyPage());
  EXPECT_TRUE(NULL != page.get());

  // This should not fail - will also delete the collector.
  collector->Detach(HttpStatus::kUnknownStatusCode);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, UrlInvalidDoneBeforeDetach) {
  EnableCollectorPrefix();
  // Invalidate all URLs cached before timestamp 2.
  options_->AddUrlCacheInvalidationEntry("*", 2L, true);
  // Test that calling Done() before Detach() works.
  ProxyFetchPropertyCallbackCollector* collector = MakeCollector();
  ProxyFetchPropertyCallback* callback = AddCallback(
      collector, ProxyFetchPropertyCallback::kPropertyCachePage);

  // callback->IsCacheValid could be called anytime before callback->Done.
  // Will return false due to the invalidation entry.
  EXPECT_FALSE(callback->IsCacheValid(1L));

  // Invoke the callback.
  callback->Done(true);

  // Collector should now have a page property.
  scoped_ptr<AbstractPropertyPage> page;
  page.reset(collector->ReleaseFallbackPropertyPage());
  EXPECT_TRUE(NULL != page.get());

  // This should not fail - will also delete the collector.
  collector->Detach(HttpStatus::kUnknownStatusCode);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, DetachBeforeDone) {
  EnableCollectorPrefix();
  // Test that calling Detach() before Done() works.
  ProxyFetchPropertyCallbackCollector* collector = MakeCollector();
  collector->RequestHeadersComplete();
  ProxyFetchPropertyCallback* callback = AddCallback(
      collector, ProxyFetchPropertyCallback::kPropertyCachePage);

  // callback->IsCacheValid could be called anytime before callback->Done.
  // Will return true because there are no cache invalidation URL patterns.
  EXPECT_TRUE(callback->IsCacheValid(1L));

  // Will not delete the collector since we did not call Done yet.
  collector->Detach(HttpStatus::kUnknownStatusCode);

  // This call is after Detach (but before callback->Done).
  // ProxyFetchPropertyCallbackCollector::IsCacheValid returns false if
  // detached.
  EXPECT_FALSE(callback->IsCacheValid(1L));

  // This will delete the collector.
  callback->Done(true);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, DoneBeforeSetProxyFetch) {
  EnableCollectorPrefix();
  // Test that calling Done() before SetProxyFetch() works.
  scoped_ptr<ProxyFetchPropertyCallbackCollector> collector;
  collector.reset(MakeCollector());
  ProxyFetchPropertyCallback* callback = AddCallback(
      collector.get(), ProxyFetchPropertyCallback::kPropertyCachePage);

  // callback->IsCacheValid could be called anytime before callback->Done.
  // Will return true because there are no cache invalidation URL patterns.
  EXPECT_TRUE(callback->IsCacheValid(1L));

  // Invoke the callback.
  callback->Done(true);

  // Construct mock ProxyFetch to test SetProxyFetch().
  ExpectStringAsyncFetch async_fetch(
      true, RequestContext::NewTestRequestContext(thread_system_.get()));
  ProxyFetchFactory factory(server_context_);
  MockProxyFetch* mock_proxy_fetch = new MockProxyFetch(
      &async_fetch, &factory, server_context_);

  // Should not be complete since SetProxyFetch() called first.
  EXPECT_FALSE(mock_proxy_fetch->complete());

  // Collector should now have a page property.
  scoped_ptr<AbstractPropertyPage> page;
  page.reset(collector->ReleaseFallbackPropertyPage());
  EXPECT_TRUE(NULL != page.get());

  collector.get()->ConnectProxyFetch(mock_proxy_fetch);
  // Should be complete since SetProxyFetch() called after Done().
  EXPECT_TRUE(mock_proxy_fetch->complete());

  // Needed for cleanup.
  mock_proxy_fetch->Done(true);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, SetProxyFetchBeforeDone) {
  EnableCollectorPrefix();
  // Test that calling SetProxyFetch() before Done() works.
  scoped_ptr<ProxyFetchPropertyCallbackCollector> collector;
  collector.reset(MakeCollector());
  ProxyFetchPropertyCallback* callback = AddCallback(
      collector.get(), ProxyFetchPropertyCallback::kPropertyCachePage);

  // Construct mock ProxyFetch to test SetProxyFetch().
  ExpectStringAsyncFetch async_fetch(
      true, RequestContext::NewTestRequestContext(thread_system_.get()));
  ProxyFetchFactory factory(server_context_);
  MockProxyFetch* mock_proxy_fetch = new MockProxyFetch(
      &async_fetch, &factory, server_context_);

  // callback->IsCacheValid could be called anytime before callback->Done.
  // Will return true because there are no cache invalidation URL patterns.
  EXPECT_TRUE(callback->IsCacheValid(1L));

  collector.get()->ConnectProxyFetch(mock_proxy_fetch);
  // Should not be complete since SetProxyFetch() called first.
  EXPECT_FALSE(mock_proxy_fetch->complete());

  EXPECT_TRUE(callback->IsCacheValid(1L));

  // Now invoke the callback.
  callback->Done(true);

  // Collector should now have a page property.
  scoped_ptr<AbstractPropertyPage> page;
  page.reset(collector->ReleaseFallbackPropertyPage());
  EXPECT_TRUE(NULL != page.get());

  // Not yet complete since RequestHeadersComplete() not called yet.
  EXPECT_FALSE(mock_proxy_fetch->complete());

  collector->RequestHeadersComplete();

  // Should be complete since both Done() and RequestHeadersComplete() called.
  EXPECT_TRUE(mock_proxy_fetch->complete());

  // Needed for cleanup.
  mock_proxy_fetch->Done(true);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, PostLookupProxyFetchDone) {
  TestAddPostlookupTask(true, true);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, DonePostLookupProxyFetch) {
  TestAddPostlookupTask(false, true);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, ProxyFetchPostLookupDone) {
  TestAddPostlookupTask(true, false);
}

TEST_F(ProxyFetchPropertyCallbackCollectorTest, FallbackPagePostLookupRace) {
  EnableCollectorPrefix();
  // This test will check PostLookup tasks should not have Null
  // fallback_property_page.
  scoped_ptr<ProxyFetchPropertyCallbackCollector> collector;
  collector.reset(MakeCollector());
  collector->RequestHeadersComplete();
  ProxyFetchPropertyCallback* page_callback = AddCallback(
      collector.get(), ProxyFetchPropertyCallback::kPropertyCachePage);
  ExpectStringAsyncFetch async_fetch(
      true, RequestContext::NewTestRequestContext(thread_system_.get()));
  ProxyFetchFactory factory(server_context_);
  MockProxyFetch* mock_proxy_fetch = new MockProxyFetch(
      &async_fetch, &factory, server_context_);

  ThreadSystem* thread_system = server_context()->thread_system();
  QueuedWorkerPool pool(1, "test", thread_system);
  QueuedWorkerPool::Sequence* sequence = pool.NewSequence();
  WorkerTestBase::SyncPoint sync_point(thread_system);
  sequence->Add(
      MakeFunction(
          static_cast<ProxyFetchPropertyCallbackCollectorTest*>(this),
          &ProxyFetchPropertyCallbackCollectorTest::
              AddCheckPageNotNullPostLookupTask,
          collector.get(), &sync_point));
  page_callback->Done(true);
  sync_point.Wait();
  collector->ConnectProxyFetch(mock_proxy_fetch);
  mock_proxy_fetch->Done(true);
}


TEST_F(ProxyFetchPropertyCallbackCollectorTest, TestOptionsValid) {
  RewriteOptions* options = new RewriteOptions(thread_system_.get());
  ProxyFetchPropertyCallbackCollector* collector =
      new ProxyFetchPropertyCallbackCollector(
          server_context_,
          RewriteTestBase::kTestDomain,
          RequestContext::NewTestRequestContext(thread_system_.get()),
          options,
          UserAgentMatcher::kDesktop);
  ThreadSynchronizer* sync = server_context()->thread_synchronizer();
  sync->EnableForPrefix(ProxyFetch::kCollectorFinish);
  sync->EnableForPrefix(ProxyFetch::kCollectorDetachStart);
  sync->EnableForPrefix(ProxyFetch::kCollectorRequestHeadersCompleteFinish);
  collector->RequestHeadersComplete();
  ProxyFetchPropertyCallback* page_callback = AddCallback(
      collector, ProxyFetchPropertyCallback::kPropertyCachePage);

  collector->Detach(HttpStatus::kUnknownStatusCode);
  delete options;
  collector->IsCacheValid(1L);
  sync->Signal(ProxyFetch::kCollectorDetachStart);
  page_callback->Done(true);
  sync->Wait(ProxyFetch::kCollectorFinish);
}

TEST_F(ProxyFetchTest, TestStickyPageSpeedOptions) {
  // The various options we set as cookies.
  StringPieceVector pagespeed_options;
  pagespeed_options.push_back("PageSpeedImageRecompressionQuality=77");
  pagespeed_options.push_back("ModPagespeedImageLimitOptimizedPercent=55");
  pagespeed_options.push_back("ModPagespeedCssInlineMaxBytes=19");
  GoogleString cookies = JoinCollection(pagespeed_options, "&");
  // Add the sticky query param as a QP to show that it's not set as a cookie.
  GoogleString params = StrCat("PageSpeedStickyQueryParameters=on&", cookies);
  // For producing the expected response headers cookies string.
  const char kCookiesPrefix[] = "[\"";
  const char kCookieSetExpires[] = "; Expires=Tue, 02 Feb 2010 19:01:26 GMT";
  const char kCookieClearExpires[] = "; Expires=Thu, 01 Jan 1970 00:00:00 GMT";
  const char kCookieAttrs[] = "; Domain=www.google.com; Path=/; HttpOnly";
  const char kCookiesSeparator[] = "\",\"";
  const char kCookiesSuffix[] = "\"]";
  GoogleString current_cookies =
      StrCat(kCookiesPrefix,
             JoinCollection(pagespeed_options, StrCat(kCookieSetExpires,
                                                      kCookieAttrs,
                                                      kCookiesSeparator)),
             kCookieSetExpires, kCookieAttrs, kCookiesSuffix);
  GoogleString expired_cookies =
      StrCat(kCookiesPrefix,
             JoinCollection(pagespeed_options, StrCat(kCookieClearExpires,
                                                      kCookieAttrs,
                                                      kCookiesSeparator)),
             kCookieClearExpires, kCookieAttrs, kCookiesSuffix);
  // Strip out the values from the expiration cookies. Pardon the hackiness.
  GlobalReplaceSubstring("=77;", ";", &expired_cookies);
  GlobalReplaceSubstring("=55;", ";", &expired_cookies);
  GlobalReplaceSubstring("=19;", ";", &expired_cookies);

  // 0. Allow options to be set by cookie but don't allow them to be sticky.
  {
    ManagedMockProxyFetch managed_mock(server_context_, true, "", "right value",
                                       params, "");
    MockProxyFetch* mock_proxy_fetch = managed_mock.mock_proxy_fetch();
    GoogleString response_cookies;
    EXPECT_FALSE(mock_proxy_fetch->response_headers()->GetCookieString(
        &response_cookies));
    EXPECT_STREQ("", response_cookies);
  }
  // 1. Allow options to be set by cookie, allow them to be sticky, but don't
  //    ask for stickiness in the request.
  {
    ManagedMockProxyFetch managed_mock(server_context_, true, "right value", "",
                                       params, "");
    MockProxyFetch* mock_proxy_fetch = managed_mock.mock_proxy_fetch();
    GoogleString response_cookies;
    EXPECT_FALSE(mock_proxy_fetch->response_headers()->GetCookieString(
        &response_cookies));
    EXPECT_STREQ("", response_cookies);
  }
  // 2. Don't allow options to be set by cookie, allow them to be made sticky,
  //    don't ask for stickiness in the request, but pass in some already-set
  //    cookies - these should be expired for us.
  {
    ManagedMockProxyFetch managed_mock(server_context_, false, "right value",
                                       "", "", cookies);
    MockProxyFetch* mock_proxy_fetch = managed_mock.mock_proxy_fetch();
    GoogleString response_cookies;
    EXPECT_TRUE(mock_proxy_fetch->response_headers()->GetCookieString(
        &response_cookies));
    EXPECT_STREQ(expired_cookies, response_cookies);
  }
  // 3. Allow options to be set by cookie, allow them to be made sticky, and
  //    ask for stickiness in the request.
  {
    ManagedMockProxyFetch managed_mock(server_context_, true, "right value",
                                       "right value", params, "");
    MockProxyFetch* mock_proxy_fetch = managed_mock.mock_proxy_fetch();
    GoogleString response_cookies;
    EXPECT_TRUE(mock_proxy_fetch->response_headers()->GetCookieString(
        &response_cookies));
    EXPECT_STREQ(current_cookies, response_cookies);
  }
  // 4. Pass in some options-as-cookies without any query params or changes.
  //    We expect no cookies in the response as the browser has them already.
  {
    ManagedMockProxyFetch managed_mock(server_context_, true, "right value", "",
                                       "", cookies);
    MockProxyFetch* mock_proxy_fetch = managed_mock.mock_proxy_fetch();
    GoogleString response_cookies;
    EXPECT_FALSE(mock_proxy_fetch->response_headers()->GetCookieString(
        &response_cookies));
    EXPECT_STREQ("", response_cookies);
  }
  // 5. Explicitly ask for sticky options-by-cookies to be cleared.
  {
    ManagedMockProxyFetch managed_mock(server_context_, true, "right value",
                                       "different value", "", cookies);
    MockProxyFetch* mock_proxy_fetch = managed_mock.mock_proxy_fetch();
    GoogleString response_cookies;
    EXPECT_TRUE(mock_proxy_fetch->response_headers()->GetCookieString(
        &response_cookies));
    EXPECT_STREQ(expired_cookies, response_cookies);
  }
}

}  // namespace net_instaweb
