/*
 * 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: jud@google.com (Jud Porter)

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

#include <map>

#include "net/instaweb/rewriter/critical_line_info.pb.h"
#include "net/instaweb/rewriter/public/critical_finder_support_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_message_handler.h"
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/string.h"

namespace net_instaweb {

namespace {
const char kRequestUrl[] = "http://www.test.com";
}  // namespace

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

  virtual ~BeaconCriticalLineInfoFinderTest() {}

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

  virtual void SetUp() {
    RewriteTestBase::SetUp();
    ResetDriver();
    // Setup the beacon_cohort. ServerContext will take ownership.
    const PropertyCache::Cohort* beacon_cohort =
        SetupCohort(page_property_cache(), RewriteDriver::kBeaconCohort);
    server_context()->set_beacon_cohort(beacon_cohort);
    // Create a new finder with the beacon_cohort. ServerContext will take
    // ownership.
    server_context()->set_critical_line_info_finder(
        new BeaconCriticalLineInfoFinder(beacon_cohort,
                                         factory()->nonce_generator()));
    // Setup the property page. ServerContext will take ownership.
    MockPropertyPage* page = NewMockPage(kRequestUrl);
    rewrite_driver()->set_property_page(page);
    server_context()->page_property_cache()->Read(page);
  }

  void WriteXPathsWithBeacon(const StringSet& xpaths,
                             BeaconStatus expected_beacon_status) {
    BeaconMetadata metadata = server_context()
                                  ->critical_line_info_finder()
                                  ->PrepareForBeaconInsertion(rewrite_driver());
    ASSERT_EQ(expected_beacon_status, metadata.status);
    BeaconCriticalLineInfoFinder::WriteXPathsToPropertyCacheFromBeacon(
        xpaths, metadata.nonce, page_property_cache(),
        server_context()->beacon_cohort(), rewrite_driver()->property_page(),
        message_handler(), factory()->mock_timer());
    rewrite_driver()->property_page()->WriteCohort(
        server_context()->beacon_cohort());
    ResetDriver();
  }

  void VerifyCriticalLineInfo(const StringSet& xpath_set) {
    const CriticalLineInfo* info =
        server_context()->critical_line_info_finder()->GetCriticalLine(
            rewrite_driver());
    ASSERT_TRUE(info != NULL);
    ASSERT_EQ(xpath_set.size(), info->panels_size());
    for (int i = 0; i < xpath_set.size(); ++i) {
      Panel panel = info->panels(i);
      GoogleString panel_str = panel.start_xpath();
      if (!panel.end_marker_xpath().empty()) {
        panel_str += ":" + panel.end_marker_xpath();
      }
      EXPECT_TRUE(xpath_set.find(panel_str) != xpath_set.end());
    }
  }
};

TEST_F(BeaconCriticalLineInfoFinderTest, NoCriticalLines) {
  EXPECT_TRUE(rewrite_driver()->critical_line_info() == NULL);
  EXPECT_TRUE(rewrite_driver()->beacon_critical_line_info() == NULL);
  EXPECT_TRUE(server_context()->critical_line_info_finder()->GetCriticalLine(
                  rewrite_driver()) == NULL);
  EXPECT_TRUE(rewrite_driver()->critical_line_info() == NULL);
  EXPECT_TRUE(rewrite_driver()->beacon_critical_line_info() != NULL);
}

TEST_F(BeaconCriticalLineInfoFinderTest, CriticalLinesFromBeacon) {
  StringSet xpaths;
  xpaths.insert("div[1]:div[2]");
  xpaths.insert("div[4]");
  WriteXPathsWithBeacon(xpaths, kBeaconWithNonce);

  VerifyCriticalLineInfo(xpaths);
  EXPECT_TRUE(rewrite_driver()->critical_line_info() != NULL);
  EXPECT_TRUE(rewrite_driver()->beacon_critical_line_info() != NULL);
}

TEST_F(BeaconCriticalLineInfoFinderTest, CriticalLinesFromConfig) {
  // Verify that if a manual split_html config is set, it still gets used
  // instead of any beacon data.
  GoogleString config = "div[@id='a']:div[1]";
  options()->set_critical_line_config(config);
  StringSet config_xpaths, beacon_xpaths;
  config_xpaths.insert(config);
  beacon_xpaths.insert("div[2]:div[3]");
  WriteXPathsWithBeacon(beacon_xpaths, kDoNotBeacon);
  VerifyCriticalLineInfo(config_xpaths);
}

}  // namespace net_instaweb
