/*
 * 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_selector_finder.h"

#include "net/instaweb/rewriter/critical_keys.pb.h"
#include "net/instaweb/rewriter/public/critical_finder_support_util.h"
#include "net/instaweb/rewriter/public/property_cache_util.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/mock_property_page.h"
#include "net/instaweb/util/public/property_cache.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/timer.h"

namespace net_instaweb {

namespace {

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

class CriticalSelectorFinderTest : public RewriteTestBase {
 protected:
  CriticalSelectorFinderTest() { }

  virtual void SetUp() {
    RewriteTestBase::SetUp();
    const PropertyCache::Cohort* beacon_cohort =
        SetupCohort(page_property_cache(), RewriteDriver::kBeaconCohort);
    server_context()->set_beacon_cohort(beacon_cohort);
    finder_ = CreateFinder(beacon_cohort);
    server_context()->set_critical_selector_finder(finder_);
    candidates_.insert("#bar");
    candidates_.insert(".a");
    candidates_.insert(".b");
    candidates_.insert("#c");
    candidates_.insert(".foo");
    ResetDriver();
  }

  virtual CriticalSelectorFinder* CreateFinder(
      const PropertyCache::Cohort* cohort) {
    return new BeaconCriticalSelectorFinder(
        cohort, factory()->nonce_generator(), statistics());
  }

  void ResetDriver() {
    ClearRewriteDriver();
    MockPropertyPage* page = NewMockPage(kRequestUrl);
    rewrite_driver()->set_property_page(page);
    PropertyCache* pcache = server_context_->page_property_cache();
    pcache->Read(page);
  }

  void WriteToPropertyCache() {
    rewrite_driver()->property_page()->WriteCohort(
        server_context()->beacon_cohort());
  }

  void WriteBackAndResetDriver() {
    WriteToPropertyCache();
    ResetDriver();
    SetDriverRequestHeaders();
  }

  int TimedValue(StringPiece name) {
    return statistics()->GetTimedVariable(name)->Get(TimedVariable::START);
  }

  void CheckCriticalSelectorFinderStats(int hits, int expiries, int not_found) {
    EXPECT_EQ(hits, TimedValue(
        CriticalSelectorFinder::kCriticalSelectorsValidCount));
    EXPECT_EQ(expiries, TimedValue(
        CriticalSelectorFinder::kCriticalSelectorsExpiredCount));
    EXPECT_EQ(not_found, TimedValue(
        CriticalSelectorFinder::kCriticalSelectorsNotFoundCount));
  }

  GoogleString CriticalSelectorsString() {
    WriteBackAndResetDriver();
    const StringSet& critical_selectors =
        finder_->GetCriticalSelectors(rewrite_driver());
    return JoinCollection(critical_selectors, ",");
  }

  // Write a raw critical selector set to pcache, used to test legacy
  // compatibility since new code won't create legacy protos.
  void WriteCriticalSelectorSetToPropertyCache(
      const CriticalKeys& selector_set) {
    PropertyCacheUpdateResult result = UpdateInPropertyCache(
        selector_set, server_context()->beacon_cohort(),
        CriticalSelectorFinder::kCriticalSelectorsPropertyName, true,
        rewrite_driver()->property_page());
    ASSERT_EQ(kPropertyCacheUpdateOk, result);
  }

  void WriteCriticalSelectorsToPropertyCache(const StringSet& selectors) {
    finder_->WriteCriticalSelectorsToPropertyCache(
        selectors, last_beacon_metadata_.nonce, rewrite_driver());
  }

  virtual BeaconStatus ExpectedBeaconStatus() {
    return kBeaconWithNonce;
  }

  // Simulate beacon insertion, with candidates_.
  void Beacon() {
    WriteBackAndResetDriver();
    factory()->mock_timer()->AdvanceMs(
        options()->beacon_reinstrument_time_sec() * Timer::kSecondMs);
    VerifyBeaconStatus(ExpectedBeaconStatus());
  }

  // Verify that no beacon injection occurs.
  void VerifyNoBeaconing() {
    VerifyBeaconStatus(kDoNotBeacon);
  }

  // Verify that beacon injection occurs.
  void VerifyBeaconing() {
    VerifyBeaconStatus(kBeaconWithNonce);
  }

  // Helper method used for verifying beacon injection status.
  void VerifyBeaconStatus(BeaconStatus status) {
    last_beacon_metadata_ =
        finder_->PrepareForBeaconInsertion(candidates_, rewrite_driver());
    EXPECT_EQ(status, last_beacon_metadata_.status);
    if (status == kBeaconWithNonce) {
      EXPECT_STREQ(ExpectedNonce(), last_beacon_metadata_.nonce);
    } else {
      EXPECT_TRUE(last_beacon_metadata_.nonce.empty());
    }
  }

  CriticalKeys* RawCriticalSelectorSet(int expected_size) {
    WriteBackAndResetDriver();
    finder_->GetCriticalSelectors(rewrite_driver());
    CriticalKeys* selectors =
        &rewrite_driver()->critical_selector_info()->proto;
    if (selectors != NULL) {
      EXPECT_EQ(expected_size, selectors->key_evidence_size());
    } else {
      EXPECT_EQ(expected_size, 0);
    }
    return selectors;
  }

  void CheckFooBarBeaconSupport(int support) {
    CheckFooBarBeaconSupport(support, support);
  }

  void CheckFooBarBeaconSupport(int foo_support, int bar_support) {
    // Check for .foo and #bar support, with no support for other beaconed
    // candidates.
    CriticalKeys* read_selectors = RawCriticalSelectorSet(5);
    ASSERT_TRUE(read_selectors != NULL);
    EXPECT_EQ("#bar", read_selectors->key_evidence(0).key());
    EXPECT_EQ(bar_support, read_selectors->key_evidence(0).support());
    EXPECT_EQ("#c", read_selectors->key_evidence(1).key());
    EXPECT_EQ(0, read_selectors->key_evidence(1).support());
    EXPECT_EQ(".a", read_selectors->key_evidence(2).key());
    EXPECT_EQ(0, read_selectors->key_evidence(2).support());
    EXPECT_EQ(".b", read_selectors->key_evidence(3).key());
    EXPECT_EQ(0, read_selectors->key_evidence(3).support());
    EXPECT_EQ(".foo", read_selectors->key_evidence(4).key());
    EXPECT_EQ(foo_support, read_selectors->key_evidence(4).support());
  }

  CriticalSelectorFinder* finder_;
  StringSet candidates_;
  BeaconMetadata last_beacon_metadata_;
};

TEST_F(CriticalSelectorFinderTest, StoreRestore) {
  // Before beacon insertion, nothing in pcache.
  CheckCriticalSelectorFinderStats(0, 0, 0);
  CriticalSelectorInfo* read_selectors =
      rewrite_driver()->critical_selector_info();
  EXPECT_TRUE(read_selectors == NULL);
  StringSet critical_selectors =
      finder_->GetCriticalSelectors(rewrite_driver());
  read_selectors = rewrite_driver()->critical_selector_info();
  EXPECT_TRUE(read_selectors != NULL);
  EXPECT_TRUE(critical_selectors.empty());
  CheckCriticalSelectorFinderStats(0, 0, 1);

  Beacon();
  CheckCriticalSelectorFinderStats(0, 0, 2);
  StringSet selectors;
  selectors.insert(".foo");
  selectors.insert("#bar");
  WriteCriticalSelectorsToPropertyCache(selectors);
  CheckFooBarBeaconSupport(finder_->SupportInterval());
  CheckCriticalSelectorFinderStats(1, 0, 2);

  // Now test expiration.
  WriteBackAndResetDriver();
  AdvanceTimeMs(2 * options()->finder_properties_cache_expiration_time_ms());
  read_selectors = rewrite_driver()->critical_selector_info();
  EXPECT_TRUE(read_selectors == NULL);
  critical_selectors = finder_->GetCriticalSelectors(rewrite_driver());
  CheckCriticalSelectorFinderStats(1, 1, 2);
}

// Verify that writing multiple beacon results are stored and aggregated. The
// critical selector set should contain all selectors seen in the last
// SupportInterval() beacon responses.  After SupportInterval() responses,
// beacon results only seen once should no longer be considered critical.
TEST_F(CriticalSelectorFinderTest, StoreMultiple) {
  Beacon();
  StringSet selectors;
  selectors.insert(".a");
  WriteCriticalSelectorsToPropertyCache(selectors);
  EXPECT_STREQ(".a", CriticalSelectorsString());

  selectors.clear();
  selectors.insert(".b");
  for (int i = 0; i < finder_->SupportInterval() - 1; ++i) {
    Beacon();
    WriteCriticalSelectorsToPropertyCache(selectors);
    EXPECT_STREQ(".a,.b", CriticalSelectorsString());
    // We are sending enough beacons with the same selector set here that we
    // will enter low frequency beaconing mode, so advance time more to ensure
    // rebeaconing actually occurs.
    factory()->mock_timer()->AdvanceMs(
        options()->beacon_reinstrument_time_sec() * Timer::kSecondMs *
        kLowFreqBeaconMult);
  }

  // We send one more beacon response, which should kick .a out of the critical
  // selector set.
  Beacon();
  selectors.clear();
  selectors.insert("#c");
  WriteCriticalSelectorsToPropertyCache(selectors);
  EXPECT_STREQ("#c,.b", CriticalSelectorsString());
}

// Make sure beacon results can arrive out of order (so long as the nonce
// doesn't time out).
TEST_F(CriticalSelectorFinderTest, OutOfOrder) {
  // Make sure that the rebeaconing time is less than the time a nonce is valid,
  // so that we can test having multiple outstanding nonces.
  options()->set_beacon_reinstrument_time_sec(kBeaconTimeoutIntervalMs /
                                              Timer::kSecondMs / 2);
  Beacon();
  GoogleString initial_nonce(last_beacon_metadata_.nonce);
  // A second beacon occurs and the result comes back first.
  Beacon();
  StringSet selectors;
  selectors.insert(".a");
  WriteCriticalSelectorsToPropertyCache(selectors);
  EXPECT_STREQ(".a", CriticalSelectorsString());
  // Now the first beacon result comes back out of order.  It should still work.
  selectors.clear();
  selectors.insert(".b");
  finder_->WriteCriticalSelectorsToPropertyCache(
      selectors, initial_nonce, rewrite_driver());
  EXPECT_STREQ(".a,.b", CriticalSelectorsString());
  // A duplicate beacon nonce will be dropped.
  selectors.clear();
  selectors.insert("#c");
  finder_->WriteCriticalSelectorsToPropertyCache(
      selectors, initial_nonce, rewrite_driver());
  EXPECT_STREQ(".a,.b", CriticalSelectorsString());
  // As will an entirely bogus nonce (here we use non-base64 characters).
  const char kBogusNonce[] = "*&*";
  finder_->WriteCriticalSelectorsToPropertyCache(
      selectors, kBogusNonce, rewrite_driver());
  EXPECT_STREQ(".a,.b", CriticalSelectorsString());
}

TEST_F(CriticalSelectorFinderTest, NonceTimeout) {
  // Make sure that beacons time out after kBeaconTimeoutIntervalMs.
  Beacon();
  GoogleString initial_nonce(last_beacon_metadata_.nonce);
  // beacon_reinstrument_time_sec() passes (in mock time) before the next call
  // completes:
  Beacon();
  factory()->mock_timer()->AdvanceMs(kBeaconTimeoutIntervalMs);
  StringSet selectors;
  selectors.insert(".a");
  // This beacon arrives right at its deadline, and is OK.
  WriteCriticalSelectorsToPropertyCache(selectors);
  EXPECT_STREQ(".a", CriticalSelectorsString());
  // The first beacon arrives after its deadline, and is dropped.
  selectors.clear();
  selectors.insert(".b");
  finder_->WriteCriticalSelectorsToPropertyCache(
      selectors, initial_nonce, rewrite_driver());
  EXPECT_STREQ(".a", CriticalSelectorsString());
}

// Make sure that inserting a non-candidate critical selector has no effect.
TEST_F(CriticalSelectorFinderTest, StoreNonCandidate) {
  Beacon();
  StringSet selectors;
  selectors.insert(".a");
  selectors.insert(".noncandidate");
  selectors.insert("#noncandidate");
  WriteCriticalSelectorsToPropertyCache(selectors);
  EXPECT_STREQ(".a", CriticalSelectorsString());
}

// Make sure we aggregate duplicate beacon results.
TEST_F(CriticalSelectorFinderTest, DuplicateEntries) {
  Beacon();
  StringSet beacon_result;
  beacon_result.insert("#bar");
  beacon_result.insert(".foo");
  beacon_result.insert(".a");
  WriteCriticalSelectorsToPropertyCache(beacon_result);
  Beacon();
  beacon_result.clear();
  beacon_result.insert("#bar");
  beacon_result.insert(".foo");
  beacon_result.insert(".b");
  WriteCriticalSelectorsToPropertyCache(beacon_result);

  // Now cross-check the critical selector set.
  CriticalKeys* read_selectors = RawCriticalSelectorSet(5);
  ASSERT_TRUE(read_selectors != NULL);
  EXPECT_EQ("#bar", read_selectors->key_evidence(0).key());
  EXPECT_EQ("#c", read_selectors->key_evidence(1).key());
  EXPECT_EQ(".a", read_selectors->key_evidence(2).key());
  EXPECT_EQ(".b", read_selectors->key_evidence(3).key());
  EXPECT_EQ(".foo", read_selectors->key_evidence(4).key());
  EXPECT_EQ(2 * finder_->SupportInterval() - 1,
            read_selectors->key_evidence(0).support());
  EXPECT_EQ(0, read_selectors->key_evidence(1).support());
  EXPECT_EQ(finder_->SupportInterval() - 1,
            read_selectors->key_evidence(2).support());
  EXPECT_EQ(finder_->SupportInterval(),
            read_selectors->key_evidence(3).support());
  EXPECT_EQ(2 * finder_->SupportInterval() - 1,
            read_selectors->key_evidence(4).support());
}

// Make sure overflow of evidence can't happen, otherwise an attacker can
// convince us CSS is so critical it's not critical at all.
TEST_F(CriticalSelectorFinderTest, EvidenceOverflow) {
  // Set up pcache entry to be ready to overflow.
  CriticalKeys selectors;
  CriticalKeys::KeyEvidence* evidence = selectors.add_key_evidence();
  evidence->set_key(".a");
  evidence->set_support(kint32max);
  WriteCriticalSelectorSetToPropertyCache(selectors);
  // Now create a new critical selector set and add it repeatedly.
  StringSet new_selectors;
  new_selectors.insert(".a");
  for (int i = 0; i < finder_->SupportInterval(); ++i) {
    Beacon();
    WriteCriticalSelectorsToPropertyCache(new_selectors);
    EXPECT_STREQ(".a", CriticalSelectorsString());
    // We are sending enough beacons with the same selector set here that we
    // will enter low frequency beaconing mode, so advance time more to ensure
    // rebeaconing actually occurs.
    factory()->mock_timer()->AdvanceMs(
        options()->beacon_reinstrument_time_sec() * Timer::kSecondMs *
        kLowFreqBeaconMult);
  }
}

// Make sure we don't beacon if we have an empty set of candidate selectors.
TEST_F(CriticalSelectorFinderTest, NoCandidatesNoBeacon) {
  WriteBackAndResetDriver();
  StringSet empty;
  BeaconMetadata last_beacon_metadata =
      finder_->PrepareForBeaconInsertion(empty, rewrite_driver());
  EXPECT_EQ(kDoNotBeacon, last_beacon_metadata.status);
}

TEST_F(CriticalSelectorFinderTest, DontRebeaconBeforeTimeout) {
  Beacon();
  // Now simulate a beacon insertion attempt without timing out.
  WriteBackAndResetDriver();
  factory()->mock_timer()->AdvanceMs(options()->beacon_reinstrument_time_sec() *
                                     Timer::kSecondMs / 2);
  BeaconMetadata last_beacon_metadata =
      finder_->PrepareForBeaconInsertion(candidates_, rewrite_driver());
  EXPECT_EQ(kDoNotBeacon, last_beacon_metadata.status);
  // But we'll re-beacon if some more time passes.
  Beacon();  // beacon_reinstrument_time_sec() passes in Beacon() call.
}

TEST_F(CriticalSelectorFinderTest, RebeaconBeforeTimeoutWithHeader) {
  Beacon();

  // Write a dummy value to the property cache.
  WriteToPropertyCache();

  // If downstream caching is disabled, any beaconing key configuration and/or
  // presence of PS-ShouldBeacon header should be ignored. In such situations,
  // unless the reinstrumentation time interval is exceeded, beacon injection
  // should not happen.
  ResetDriver();
  SetDownstreamCacheDirectives("", "", kConfiguredBeaconingKey);
  SetShouldBeaconHeader(kConfiguredBeaconingKey);
  VerifyNoBeaconing();
  // Advance the timer past the beacon interval.
  factory()->mock_timer()->AdvanceMs(options()->beacon_reinstrument_time_sec() *
                                     Timer::kSecondMs + 1);
  // When the reinstrumentation time interval is exceeded, beacon injection
  // should happen as usual.
  ResetDriver();
  SetDownstreamCacheDirectives("", "", kConfiguredBeaconingKey);
  SetShouldBeaconHeader(kConfiguredBeaconingKey);
  VerifyBeaconing();

  // Beacon injection should not happen when rebeaconing key is not configured.
  ResetDriver();
  SetDownstreamCacheDirectives("", "localhost:80", "");
  SetShouldBeaconHeader(kConfiguredBeaconingKey);
  VerifyNoBeaconing();

  // Beacon injection should not happen when the PS-ShouldBeacon header is
  // absent and both downstream caching and the associated rebeaconing key
  // are configured.
  ResetDriver();
  SetDownstreamCacheDirectives("", "localhost:80", kConfiguredBeaconingKey);
  SetDriverRequestHeaders();
  VerifyNoBeaconing();

  // Beacon injection should not happen when the PS-ShouldBeacon header is
  // incorrect.
  ResetDriver();
  SetDownstreamCacheDirectives("", "localhost:80", kConfiguredBeaconingKey);
  SetShouldBeaconHeader(kWrongBeaconingKey);
  VerifyNoBeaconing();

  // Beacon injection happens when the PS-ShouldBeacon header is present even
  // when the pcache value has not expired and the reinstrumentation time
  // interval has not been exceeded.
  ResetDriver();
  SetDownstreamCacheDirectives("", "localhost:80", kConfiguredBeaconingKey);
  SetShouldBeaconHeader(kConfiguredBeaconingKey);
  VerifyBeaconing();

  // Advance the timer past the beacon interval.
  factory()->mock_timer()->AdvanceMs(
      options()->beacon_reinstrument_time_sec() * Timer::kSecondMs + 1);
  // Beacon injection should happen after reinstrumentation time interval has
  // passed when downstream caching is enabled but rebeaconing key is not
  // configured.
  ResetDriver();
  SetDownstreamCacheDirectives("", "localhost:80", "");
  SetShouldBeaconHeader(kConfiguredBeaconingKey);
  VerifyBeaconing();

  // Advance the timer past the beacon interval.
  factory()->mock_timer()->AdvanceMs(
      options()->beacon_reinstrument_time_sec() * Timer::kSecondMs + 1);
  // Beacon injection should not happen when the PS-ShouldBeacon header is
  // incorrect even if the reinstrumentation time interval has been exceeded.
  ResetDriver();
  SetDownstreamCacheDirectives("", "localhost:80", kConfiguredBeaconingKey);
  SetShouldBeaconHeader(kWrongBeaconingKey);
  VerifyNoBeaconing();
}

// If ShouldReplacePriorResult returns true, then a beacon result
// replaces any previous results.
class UnverifiedCriticalSelectorFinder : public CriticalSelectorFinder {
 public:
  UnverifiedCriticalSelectorFinder(const PropertyCache::Cohort* cohort,
                                   Statistics* stats)
      : CriticalSelectorFinder(cohort, NULL, stats) {}
  virtual ~UnverifiedCriticalSelectorFinder() {}

  virtual int SupportInterval() const { return 10; }

 protected:
  virtual bool ShouldReplacePriorResult() const { return true; }

 private:
  DISALLOW_COPY_AND_ASSIGN(UnverifiedCriticalSelectorFinder);
};

// Test that unverified results apply.
class UnverifiedSelectorsTest : public CriticalSelectorFinderTest {
 protected:
  virtual BeaconStatus ExpectedBeaconStatus() {
    return kBeaconNoNonce;
  }
  virtual CriticalSelectorFinder* CreateFinder(
      const PropertyCache::Cohort* cohort) {
    return new UnverifiedCriticalSelectorFinder(cohort, statistics());
  }
};

TEST_F(UnverifiedSelectorsTest, NonCandidatesAreStored) {
  Beacon();
  StringSet selectors;
  selectors.insert(".a");
  selectors.insert(".noncandidate");
  selectors.insert("#noncandidate");
  finder_->WriteCriticalSelectorsToPropertyCache(
      selectors, NULL /* no nonce */, rewrite_driver());
  EXPECT_STREQ("#noncandidate,.a,.noncandidate", CriticalSelectorsString());
}

// Each beacon replaces previous results.
TEST_F(UnverifiedSelectorsTest, MultipleResultsReplace) {
  Beacon();
  StringSet selectors;
  selectors.insert(".noncandidate");
  finder_->WriteCriticalSelectorsToPropertyCache(
      selectors, NULL /* no nonce */, rewrite_driver());
  EXPECT_STREQ(".noncandidate", CriticalSelectorsString());

  selectors.clear();
  selectors.insert(".another");
  Beacon();
  finder_->WriteCriticalSelectorsToPropertyCache(
      selectors, NULL /* no nonce */, rewrite_driver());
  EXPECT_STREQ(".another", CriticalSelectorsString());
}

}  // namespace

}  // namespace net_instaweb
