/*
 * 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: slamm@google.com (Stephen Lamm)

#include "net/instaweb/rewriter/public/critical_css_finder.h"

#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/rewriter/critical_css.pb.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 "net/instaweb/rewriter/public/test_rewrite_driver_factory.h"
#include "net/instaweb/util/public/fallback_property_page.h"
#include "net/instaweb/util/public/mock_property_page.h"
#include "net/instaweb/util/public/property_cache.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"

namespace net_instaweb {

namespace {

const char kFallbackUrl[] = "http://www.test.com?a=b";

// Provide stub implementation of abstract base class for testing purposes.
// Note: Not using the implementation from mock_critical_css_finder.h, so that
// we can test with property cache.
class TestCriticalCssFinder : public CriticalCssFinder {
 public:
  TestCriticalCssFinder(Statistics* stats, const PropertyCache::Cohort* cohort)
      : CriticalCssFinder(cohort, stats) {}

  // Provide stub instantions for pure virtual functions.
  virtual void ComputeCriticalCss(RewriteDriver* driver) {}
};

}  // namespace

const char kCriticalCssCohort[] = "critical_css";

class CriticalCssFinderTest : public RewriteTestBase {
 protected:
  virtual void SetUp() {
    RewriteTestBase::SetUp();
    SetupCohort(page_property_cache(), kCriticalCssCohort);
    finder_.reset(new TestCriticalCssFinder(
        statistics(), page_property_cache()->GetCohort(kCriticalCssCohort)));
    ResetDriver();
  }

  void ResetDriver() {
    rewrite_driver()->Clear();
    rewrite_driver()->set_request_context(
        RequestContext::NewTestRequestContext(factory()->thread_system()));
    PropertyCache* pcache = server_context_->page_property_cache();
    MockPropertyPage* page = NewMockPage(kRequestUrl);
    MockPropertyPage* page_with_fallback_values =
        NewMockPage(kFallbackUrl);
    rewrite_driver()->set_fallback_property_page(
        new FallbackPropertyPage(page, page_with_fallback_values));
    pcache->Read(page_with_fallback_values);
    pcache->Read(page);
  }

  const PropertyValue* GetUpdatedValue() {
    AbstractPropertyPage* page = rewrite_driver()->property_page();
    const PropertyCache::Cohort* cohort = finder_->cohort();
    if (cohort != NULL && page != NULL) {
      return page->GetProperty(cohort,
                               CriticalCssFinder::kCriticalCssPropertyName);
    }
    return NULL;
  }

  void CheckCriticalCssFinderStats(int hits, int expiries, int not_found) {
    EXPECT_EQ(hits, TimedValue(CriticalCssFinder::kCriticalCssValidCount));
    EXPECT_EQ(expiries,
              TimedValue(CriticalCssFinder::kCriticalCssExpiredCount));
    EXPECT_EQ(not_found,
              TimedValue(CriticalCssFinder::kCriticalCssNotFoundCount));
  }

 protected:
  scoped_ptr<TestCriticalCssFinder> finder_;
  static const char kRequestUrl[];
};

const char CriticalCssFinderTest::kRequestUrl[] = "http://www.test.com";

TEST_F(CriticalCssFinderTest, UpdateCacheOnSuccess) {
  // Include an actual value in the RPC result to induce a cache write.
  CriticalCssResult result;
  CriticalCssResult_LinkRules* link_rules = result.add_link_rules();
  link_rules->set_link_url(GoogleString("http://test.com/a.css"));
  link_rules->set_critical_rules(GoogleString("a_critical {color: black;}"));
  link_rules->set_original_size(100);
  EXPECT_TRUE(finder_->UpdateCache(rewrite_driver(), result));
  // Property present in actual page.
  EXPECT_TRUE(GetUpdatedValue()->has_value());
  // Property present in page containing fallback values.
  EXPECT_TRUE(rewrite_driver()->fallback_property_page()->GetFallbackProperty(
      finder_->cohort(), CriticalCssFinder::kCriticalCssPropertyName));
}

TEST_F(CriticalCssFinderTest,
       UpdateCriticalCssCacheEntrySuccessEmptySet) {
  // Include an actual value in the RPC result to induce a cache write.
  CriticalCssResult result;
  EXPECT_TRUE(finder_->UpdateCache(rewrite_driver(), result));
  EXPECT_TRUE(GetUpdatedValue()->has_value());
}

TEST_F(CriticalCssFinderTest,
       UpdateCriticalCssCacheEntryPropertyPageMissing) {
  // No cache insert if PropertyPage is not set in RewriteDriver.
  rewrite_driver()->set_property_page(NULL);
  CriticalCssResult result;
  EXPECT_FALSE(finder_->UpdateCache(rewrite_driver(), result));
  EXPECT_EQ(NULL, GetUpdatedValue());
}

TEST_F(CriticalCssFinderTest, CheckCacheHandling) {
  {
    scoped_ptr<CriticalCssResult> result(
        finder_->GetCriticalCssFromCache(rewrite_driver()));
    EXPECT_TRUE(result == NULL);
    CheckCriticalCssFinderStats(0, 0, 1);  // hits, expiries, not_found
    ClearStats();
  }

  GoogleString result_str;
  {
    CriticalCssResult result;

    // Insert a rewritten url.
    CriticalCssResult_LinkRules* link_rules = result.add_link_rules();
    link_rules->set_link_url(
        GoogleString("http://test.com/I.b.css.pagespeed.cf.0.css"));
    link_rules->set_critical_rules(
        GoogleString("b_critical {color: black }"));
    link_rules->set_original_size(999);

    link_rules = result.add_link_rules();
    link_rules->set_link_url(
        GoogleString("http://test.com/c.css"));
    link_rules->set_critical_rules(
        GoogleString("c_critical {color: cyan }"));
    link_rules->set_original_size(100);

    result.SerializeToString(&result_str);

    EXPECT_TRUE(finder_->UpdateCache(rewrite_driver(), result));
    // Write the updated value for both actual property page and page with
    // fallback values to the pcache.
    rewrite_driver()->property_page()->WriteCohort(finder_->cohort());
    EXPECT_TRUE(GetUpdatedValue()->has_value());
    // Property present in page containing fallback values.
    EXPECT_TRUE(rewrite_driver()->fallback_property_page()->GetFallbackProperty(
        finder_->cohort(), CriticalCssFinder::kCriticalCssPropertyName));
  }

  {
    ResetDriver();
    scoped_ptr<CriticalCssResult> cached_result(
        finder_->GetCriticalCssFromCache(rewrite_driver()));
    EXPECT_TRUE(cached_result.get() != NULL);
    EXPECT_EQ(2, cached_result->link_rules_size());
    GoogleString cached_result_str;
    EXPECT_TRUE(cached_result->SerializeToString(&cached_result_str));
    EXPECT_EQ(result_str, cached_result_str);
    CheckCriticalCssFinderStats(1, 0, 0);  // hits, expiries, not_found
    ClearStats();
  }

  {
    // Advance past expiry. Result is unavailable.
    ResetDriver();
    AdvanceTimeMs(2 * options()->finder_properties_cache_expiration_time_ms());
    scoped_ptr<CriticalCssResult> cached_result(
        finder_->GetCriticalCssFromCache(rewrite_driver()));
    EXPECT_TRUE(cached_result.get() == NULL);
    CheckCriticalCssFinderStats(0, 1, 0);  // hits, expiries, not_found
  }
}

TEST_F(CriticalCssFinderTest, EmptyResultWritesValueToCache) {
  CriticalCssResult result;
  EXPECT_TRUE(finder_->UpdateCache(rewrite_driver(), result));
  // Write the updated value to the pcache.
  rewrite_driver()->property_page()->WriteCohort(finder_->cohort());
  EXPECT_TRUE(GetUpdatedValue()->has_value());
}

}  // namespace net_instaweb
