/*
 * 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: nikhilmadan@google.com (Nikhil Madan)

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

#include <vector>

#include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/counting_url_async_fetcher.h"
#include "net/instaweb/http/public/mock_url_fetcher.h"
#include "net/instaweb/http/public/rate_controller.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/http/public/wait_url_async_fetcher.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/null_message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/stl_util.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/response_headers.h"
#include "pagespeed/kernel/util/platform.h"
#include "pagespeed/kernel/util/simple_stats.h"

namespace net_instaweb {

namespace {

class MockFetch : public AsyncFetch {
 public:
  explicit MockFetch(const RequestContextPtr& ctx, bool is_background_fetch)
      : AsyncFetch(ctx),
        is_background_fetch_(is_background_fetch),
        done_(false),
        success_(false) {}
  virtual ~MockFetch() {}
  virtual void HandleHeadersComplete() {}
  virtual bool HandleWrite(const StringPiece& content,
                           MessageHandler* handler) {
    content.AppendToString(&content_);
    return true;
  }
  virtual bool HandleFlush(MessageHandler* handler) {
    return true;
  }
  virtual void HandleDone(bool success) {
    success_ = success;
    done_ = true;
  }

  virtual bool IsBackgroundFetch() const {
    return is_background_fetch_;
  }

  const GoogleString& content() { return content_; }
  bool done() { return done_; }
  bool success() { return success_; }

 private:
  GoogleString content_;
  bool is_background_fetch_;
  bool done_;
  bool success_;

  DISALLOW_COPY_AND_ASSIGN(MockFetch);
};

class RateControllingUrlAsyncFetcherTest : public ::testing::Test {
 protected:
  RateControllingUrlAsyncFetcherTest()
      : thread_system_(Platform::CreateThreadSystem()),
        stats_(thread_system_.get()),
        timer_(thread_system_->NewMutex(), MockTimer::kApr_5_2010_ms),
        domain1_url1_("http://www.d1.com/url1"),
        domain2_url1_("http://www.d2.com/url1"),
        domain3_url1_("http://www.d3.com/url1"),
        body1_("b1"),
        body2_("b2"),
        ttl_ms_(Timer::kHourMs) {
    RateController::InitStats(&stats_);
    wait_fetcher_.reset(new WaitUrlAsyncFetcher(
        &mock_fetcher_, thread_system_->NewMutex()));
    counting_fetcher_.reset(new CountingUrlAsyncFetcher((wait_fetcher_.get())));

    // At max 10 requests will be queued up, and we will have atmost 2 outgoing
    // requests for a particular domain.
    rate_controlling_fetcher_.reset(new RateControllingUrlAsyncFetcher(
        counting_fetcher_.get(), 10, 2, 4, thread_system_.get(), &stats_));

    SetupResponse(domain1_url1_, body1_);
    SetupResponse(domain2_url1_, body2_);
    SetupResponse(domain3_url1_, body3_);
  }

  void SetupResponse(const GoogleString& url, const GoogleString& body) {
    // Set fetcher result and headers.
    ResponseHeaders headers;
    headers.set_major_version(1);
    headers.set_minor_version(1);
    headers.SetStatusAndReason(HttpStatus::kOK);
    headers.SetDateAndCaching(timer_.NowMs(), ttl_ms_);
    mock_fetcher_.SetResponse(url, headers, body);
  }

  int global_fetch_queue_size() {
    return stats_.GetUpDownCounter(
        RateController::kCurrentGlobalFetchQueueSize)->Get();
  }

  MockUrlFetcher mock_fetcher_;
  scoped_ptr<ThreadSystem> thread_system_;
  SimpleStats stats_;
  scoped_ptr<RateControllingUrlAsyncFetcher> rate_controlling_fetcher_;
  scoped_ptr<WaitUrlAsyncFetcher> wait_fetcher_;
  scoped_ptr<CountingUrlAsyncFetcher> counting_fetcher_;

  MockTimer timer_;

  NullMessageHandler handler_;

  const GoogleString domain1_url1_;
  const GoogleString domain2_url1_;
  const GoogleString domain3_url1_;
  const GoogleString body1_;
  const GoogleString body2_;
  const GoogleString body3_;
  const int ttl_ms_;
};

TEST_F(RateControllingUrlAsyncFetcherTest, SingleUrlWorks) {
  MockFetch fetch(
      RequestContext::NewTestRequestContext(thread_system_.get()), true);
  rate_controlling_fetcher_->Fetch(domain1_url1_, &handler_, &fetch);
  // Call callback immediately.
  wait_fetcher_->CallCallbacks();
  EXPECT_TRUE(fetch.done());
  EXPECT_TRUE(fetch.success());
  EXPECT_EQ(HttpStatus::kOK, fetch.response_headers()->status_code());
  EXPECT_STREQ(body1_, fetch.content());
}

TEST_F(RateControllingUrlAsyncFetcherTest,
       MultipleBackgroundRequestsForSingleHost) {
  std::vector<MockFetch*> fetch_vector;

  // Trigger 100 background requests all for the same domain.
  for (int i = 0; i < 100; ++i) {
    MockFetch* fetch = new MockFetch(
        RequestContext::NewTestRequestContext(thread_system_.get()), true);
    fetch_vector.push_back(fetch);
    rate_controlling_fetcher_->Fetch(domain1_url1_, &handler_, fetch);
  }

  // 2 fetches get triggered, while 4 get queued up since the per host threshold
  // is 4. None of these are done yet.
  for (int i = 0; i < 6; ++i) {
    EXPECT_FALSE(fetch_vector[i]->done());
  }
  EXPECT_EQ(4, global_fetch_queue_size());

  // The next 94 fetches get shedded due to load.
  for (int i = 6; i < 100; ++i) {
    EXPECT_TRUE(fetch_vector[i]->done());
    EXPECT_FALSE(fetch_vector[i]->success());
    EXPECT_EQ("", fetch_vector[i]->content());
    EXPECT_TRUE(fetch_vector[i]->response_headers()->Has(
                    HttpAttributes::kXPsaLoadShed));
  }

  // We need 3 calls to WaitUrlAsyncFetcher::CallCallbacks since the queued
  // fetches haven't been triggered yet.
  for (int i = 0; i < 3; ++i) {
    wait_fetcher_->CallCallbacks();
    for (int j = 0; j < 6; ++j) {
      MockFetch* fetch = fetch_vector[j];
      if (j < 2 * (i + 1)) {
        EXPECT_TRUE(fetch->done());
        EXPECT_TRUE(fetch->success());
        EXPECT_EQ(HttpStatus::kOK, fetch->response_headers()->status_code());
        EXPECT_STREQ(body1_, fetch->content());
        EXPECT_FALSE(fetch_vector[i]->response_headers()->Has(
                         HttpAttributes::kXPsaLoadShed));
      } else {
        EXPECT_FALSE(fetch->done());
        EXPECT_FALSE(fetch->success());
      }
    }
  }

  EXPECT_EQ(4, stats_.GetTimedVariable(
      RateController::kQueuedFetchCount)->Get(
          TimedVariable::START));
  EXPECT_EQ(94, stats_.GetTimedVariable(
      RateController::kDroppedFetchCount)->Get(
          TimedVariable::START));
  EXPECT_EQ(0, global_fetch_queue_size());

  STLDeleteContainerPointers(fetch_vector.begin(), fetch_vector.end());
}

TEST_F(RateControllingUrlAsyncFetcherTest, MultipleRequestsForSingleHost) {
  std::vector<MockFetch*> fetch_vector;

  // Trigger 100 user-facing requests all for the same domain.
  for (int i = 0; i < 100; ++i) {
    MockFetch* fetch = new MockFetch(  // User-facing requests.
        RequestContext::NewTestRequestContext(thread_system_.get()), false);
    fetch_vector.push_back(fetch);
    rate_controlling_fetcher_->Fetch(domain1_url1_, &handler_, fetch);
  }

  // Trigger 200 background requests all for the same domain.
  for (int i = 0; i < 200; ++i) {
    MockFetch* fetch = new MockFetch(  // Background requests.
        RequestContext::NewTestRequestContext(thread_system_.get()), true);
    fetch_vector.push_back(fetch);
    rate_controlling_fetcher_->Fetch(domain1_url1_, &handler_, fetch);
  }

  // 100 fetches get triggered, while 4 get queued up. The next 196 requests
  // are dropped.
  for (int i = 0; i < 104; ++i) {
    EXPECT_FALSE(fetch_vector[i]->done());
  }
  EXPECT_EQ(4, global_fetch_queue_size());

  for (int i = 104; i < 300; ++i) {
    EXPECT_TRUE(fetch_vector[i]->done());
    EXPECT_FALSE(fetch_vector[i]->success());
    EXPECT_EQ("", fetch_vector[i]->content());
    EXPECT_TRUE(fetch_vector[i]->response_headers()->Has(
                    HttpAttributes::kXPsaLoadShed));
  }

  wait_fetcher_->CallCallbacks();
  // The first 100 fetches complete.
  for (int i = 0; i < 100; ++i) {
    MockFetch* fetch = fetch_vector[i];
    EXPECT_TRUE(fetch->done());
    EXPECT_TRUE(fetch->success());
    EXPECT_EQ(HttpStatus::kOK, fetch->response_headers()->status_code());
    EXPECT_STREQ(body1_, fetch->content());
    EXPECT_FALSE(fetch_vector[i]->response_headers()->Has(
                     HttpAttributes::kXPsaLoadShed));
  }

  // The next 4 are queued up.
  for (int i = 100; i < 104; ++i) {
    EXPECT_FALSE(fetch_vector[i]->done());
  }

  // We need 2 calls to WaitUrlAsyncFetcher::CallCallbacks since the queued
  // fetches haven't been triggered yet.
  for (int i = 0; i < 2; ++i) {
    wait_fetcher_->CallCallbacks();
    for (int j = 100; j < 104; ++j) {
      MockFetch* fetch = fetch_vector[j];
      if (j < 100 + 2 * (i + 1)) {
        EXPECT_TRUE(fetch->done());
        EXPECT_TRUE(fetch->success());
        EXPECT_EQ(HttpStatus::kOK, fetch->response_headers()->status_code());
        EXPECT_STREQ(body1_, fetch->content());
        EXPECT_FALSE(fetch_vector[i]->response_headers()->Has(
                         HttpAttributes::kXPsaLoadShed));
      } else {
        EXPECT_FALSE(fetch->done());
        EXPECT_FALSE(fetch->success());
      }
    }
  }

  EXPECT_EQ(4, stats_.GetTimedVariable(
      RateController::kQueuedFetchCount)->Get(
          TimedVariable::START));
  EXPECT_EQ(196, stats_.GetTimedVariable(
      RateController::kDroppedFetchCount)->Get(
          TimedVariable::START));
  EXPECT_EQ(0, global_fetch_queue_size());

  STLDeleteContainerPointers(fetch_vector.begin(), fetch_vector.end());
}


TEST_F(RateControllingUrlAsyncFetcherTest,
       MultipleBackgroundRequestsForMultipleHosts) {
  std::vector<MockFetch*> fetch_vector;

  // Trigger a total of 100 requests, alternately for domain1 and domain2.
  // For each domain, 2 fetches get triggered while 4 get queued up.
  for (int i = 0; i < 50; ++i) {
    MockFetch* fetch = new MockFetch(
        RequestContext::NewTestRequestContext(thread_system_.get()), true);
    fetch_vector.push_back(fetch);
    rate_controlling_fetcher_->Fetch(domain1_url1_, &handler_, fetch);
    fetch = new MockFetch(
        RequestContext::NewTestRequestContext(thread_system_.get()), true);
    fetch_vector.push_back(fetch);
    rate_controlling_fetcher_->Fetch(domain2_url1_, &handler_, fetch);
  }

  // Send another 10 requests for domain3. 2 fetches get triggered, 2 get
  // enqueued and 6 get dropped.
  for (int i = 0; i < 10; ++i) {
    MockFetch* fetch = new MockFetch(
        RequestContext::NewTestRequestContext(thread_system_.get()), true);
    fetch_vector.push_back(fetch);
    rate_controlling_fetcher_->Fetch(domain3_url1_, &handler_, fetch);
  }

  // 6 fetches get triggered, while 10 get queued up. None of these are done
  // yet.
  for (int i = 0; i < 12; ++i) {
    EXPECT_FALSE(fetch_vector[i]->done());
  }
  for (int i = 100; i < 104; ++i) {
    EXPECT_FALSE(fetch_vector[i]->done());
  }
  EXPECT_EQ(10, global_fetch_queue_size());

  // 94 fetches get shedded due to load.
  for (int i = 12; i < 100; ++i) {
    EXPECT_TRUE(fetch_vector[i]->done());
    EXPECT_FALSE(fetch_vector[i]->success());
    EXPECT_EQ("", fetch_vector[i]->content());
    EXPECT_TRUE(fetch_vector[i]->response_headers()->Has(
                    HttpAttributes::kXPsaLoadShed));
  }
  for (int i = 104; i < 110; ++i) {
    EXPECT_TRUE(fetch_vector[i]->done());
    EXPECT_FALSE(fetch_vector[i]->success());
    EXPECT_EQ("", fetch_vector[i]->content());
    EXPECT_TRUE(fetch_vector[i]->response_headers()->Has(
                    HttpAttributes::kXPsaLoadShed));
  }

  // We need 3 calls to WaitUrlAsyncFetcher::CallCallbacks since the queued
  // fetches haven't been triggered yet.
  for (int i = 0; i < 3; ++i) {
    wait_fetcher_->CallCallbacks();
    for (int j = 0; j < 12; ++j) {
      MockFetch* fetch = fetch_vector[j];
      if (j < 4 * (i + 1)) {
        EXPECT_TRUE(fetch->done());
        EXPECT_TRUE(fetch->success());
        EXPECT_EQ(HttpStatus::kOK, fetch->response_headers()->status_code());
        EXPECT_STREQ(j % 2 == 0 ? body1_ : body2_, fetch->content());
        EXPECT_FALSE(fetch_vector[i]->response_headers()->Has(
                         HttpAttributes::kXPsaLoadShed));
      } else {
        EXPECT_FALSE(fetch->done());
        EXPECT_FALSE(fetch->success());
      }
    }
    for (int j = 100; j < 104; ++j) {
      MockFetch* fetch = fetch_vector[j];
      if (j < 100  + 2 * (i + 1)) {
        EXPECT_TRUE(fetch->done());
        EXPECT_TRUE(fetch->success());
        EXPECT_EQ(HttpStatus::kOK, fetch->response_headers()->status_code());
        EXPECT_STREQ(body3_, fetch->content());
        EXPECT_FALSE(fetch_vector[i]->response_headers()->Has(
                         HttpAttributes::kXPsaLoadShed));
      } else {
        EXPECT_FALSE(fetch->done());
        EXPECT_FALSE(fetch->success());
      }
    }
  }

  // Domain3's request gets fetched correctly.
  MockFetch* fetch = fetch_vector[100];
  EXPECT_TRUE(fetch->done());
  EXPECT_TRUE(fetch->success());
  EXPECT_EQ(HttpStatus::kOK, fetch->response_headers()->status_code());
  EXPECT_STREQ(body3_, fetch->content());
  EXPECT_FALSE(
      fetch->response_headers()->Has(HttpAttributes::kXPsaLoadShed));

  EXPECT_EQ(10, stats_.GetTimedVariable(
      RateController::kQueuedFetchCount)->Get(
          TimedVariable::START));
  EXPECT_EQ(94, stats_.GetTimedVariable(
      RateController::kDroppedFetchCount)->Get(
          TimedVariable::START));
  EXPECT_EQ(0, global_fetch_queue_size());

  STLDeleteContainerPointers(fetch_vector.begin(), fetch_vector.end());
}

}  // namespace

}  // namespace net_instaweb
