/*
 * 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: jmarantz@google.com (Joshua Marantz)

// Unit-test the http dump fetcher, using a mock fetcher.  Note that
// the HTTP Dump Fetcher is, in essence, a caching fetcher except that:
//    1. It ignores caching headers completely
//    2. It uses file-based storage with no expectation of ever evicting
//       anything.
//
// TODO(jmarantz): consider making this class a special case of the
// combination of HTTPCache, FileCache, and HttpDumpUrlFetcher.

#include "net/instaweb/http/public/http_dump_url_fetcher.h"

#include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/request_context.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/google_message_handler.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/stdio_file_system.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/base/timer.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/util/platform.h"

namespace net_instaweb {

namespace {

class HttpDumpUrlFetcherTest : public testing::Test {
 public:
  HttpDumpUrlFetcherTest()
      : thread_system_(Platform::CreateThreadSystem()),
        mock_timer_(thread_system_->NewMutex(), 0),
        http_dump_fetcher_(
            GTestSrcDir() + "/net/instaweb/http/testdata",
            &file_system_,
            &mock_timer_) {
  }

 protected:
  scoped_ptr<ThreadSystem> thread_system_;
  MockTimer mock_timer_;
  StdioFileSystem file_system_;
  GoogleString content_;
  HttpDumpUrlFetcher http_dump_fetcher_;
  GoogleMessageHandler message_handler_;

 private:
  DISALLOW_COPY_AND_ASSIGN(HttpDumpUrlFetcherTest);
};

TEST_F(HttpDumpUrlFetcherTest, TestReadWithGzip) {
  ResponseHeaders response;
  RequestHeaders request;
  request.Add(HttpAttributes::kAcceptEncoding, HttpAttributes::kGzip);
  StringAsyncFetch fetch(
      RequestContext::NewTestRequestContext(thread_system_.get()), &content_);
  fetch.set_response_headers(&response);
  fetch.set_request_headers(&request);

  http_dump_fetcher_.Fetch(
      "http://www.google.com", &message_handler_, &fetch);
  ASSERT_TRUE(fetch.done());
  ASSERT_TRUE(fetch.success());
  ConstStringStarVector v;
  ASSERT_TRUE(response.Lookup(HttpAttributes::kContentEncoding, &v));
  ASSERT_EQ(1, v.size());
  EXPECT_EQ(GoogleString(HttpAttributes::kGzip), *(v[0]));
  EXPECT_EQ(5513, content_.size());
  v.clear();
  ASSERT_TRUE(response.Lookup(HttpAttributes::kContentLength, &v));
  ASSERT_EQ(1, v.size());
  EXPECT_EQ(GoogleString("5513"), *(v[0]));
}

TEST_F(HttpDumpUrlFetcherTest, TestReadUncompressedFromGzippedDump) {
  ResponseHeaders response;
  StringAsyncFetch fetch(
      RequestContext::NewTestRequestContext(thread_system_.get()), &content_);
  fetch.set_response_headers(&response);

  http_dump_fetcher_.Fetch(
      "http://www.google.com", &message_handler_, &fetch);
  ASSERT_TRUE(fetch.done());
  ASSERT_TRUE(fetch.success());
  ConstStringStarVector v;
  if (response.Lookup(HttpAttributes::kContentEncoding, &v)) {
    ASSERT_EQ(1, v.size());
    EXPECT_NE(GoogleString(HttpAttributes::kGzip), *(v[0]));
  }
  EXPECT_EQ(14450, content_.size());
  v.clear();
  ASSERT_TRUE(response.Lookup(HttpAttributes::kContentLength, &v));
  ASSERT_EQ(1, v.size());
  EXPECT_EQ(GoogleString("14450"), *(v[0]));
}

// Helper that checks the Date: field as it starts writing.
class CheckDateHeaderFetch : public StringAsyncFetch {
 public:
  CheckDateHeaderFetch(const MockTimer* timer, ThreadSystem* threads)
      : StringAsyncFetch(RequestContext::NewTestRequestContext(threads)),
        headers_complete_called_(false), timer_(timer) {}
  virtual ~CheckDateHeaderFetch() {}

  virtual void HandleHeadersComplete() {
    headers_complete_called_ = true;
    response_headers()->ComputeCaching();
    EXPECT_EQ(timer_->NowMs(), response_headers()->date_ms());
  }

  bool headers_complete_called() const { return headers_complete_called_; }

 private:
  bool headers_complete_called_;
  const MockTimer* timer_;
  DISALLOW_COPY_AND_ASSIGN(CheckDateHeaderFetch);
};


TEST_F(HttpDumpUrlFetcherTest, TestDateAdjustment) {
  // Set a time in 2030s, which should be bigger than the time of the slurp,
  // which is a prerequisite for date adjustment
  mock_timer_.SetTimeUs(60 * Timer::kYearMs * Timer::kMsUs);

  // Make sure that date fixing up works in time for first write ---
  // which is needed for adapting it into an async fetcher.
  CheckDateHeaderFetch check_date(&mock_timer_, thread_system_.get());

  http_dump_fetcher_.Fetch("http://www.google.com", &message_handler_,
                           &check_date);
  EXPECT_TRUE(check_date.done());
  EXPECT_TRUE(check_date.success());
  EXPECT_TRUE(check_date.headers_complete_called());
}

}  // namespace

}  // namespace net_instaweb
