/*
 * 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: sligocki@google.com (Shawn Ligocki)

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

#include "net/instaweb/rewriter/public/domain_lawyer.h"
#include "net/instaweb/rewriter/public/resource.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 "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/html/html_node.h"
#include "pagespeed/kernel/http/google_url.h"

namespace net_instaweb {

namespace {

class CountingFilter : public CommonFilter {
 public:
  explicit CountingFilter(RewriteDriver* driver) : CommonFilter(driver),
                                                   start_doc_calls_(0),
                                                   start_element_calls_(0),
                                                   end_element_calls_(0) {}

  virtual void StartDocumentImpl() { ++start_doc_calls_; }
  virtual void StartElementImpl(HtmlElement* element) {
    ++start_element_calls_;
  }
  virtual void EndElementImpl(HtmlElement* element) { ++end_element_calls_; }

  virtual const char* Name() const { return "CommonFilterTest.CountingFilter"; }

  int start_doc_calls_;
  int start_element_calls_;
  int end_element_calls_;
};

class CommonFilterTest : public RewriteTestBase {
 protected:
  virtual void SetUp() {
    RewriteTestBase::SetUp();
    filter_.reset(new CountingFilter(rewrite_driver()));
    rewrite_driver()->AddFilter(filter_.get());
  }

  void ExpectUrl(const GoogleString& expected_url,
                 const GoogleUrl& actual_gurl) {
    EXPECT_EQ(expected_url, actual_gurl.Spec());
  }

  bool CanRewriteResource(CommonFilter* filter, const StringPiece& url) {
    bool unused;
    ResourcePtr resource(filter->CreateInputResource(
        url, RewriteDriver::InputRole::kUnknown, &unused));
    return (resource.get() != NULL);
  }

  CommonFilter* MakeFilter(const StringPiece& base_url,
                           const StringPiece& domain,
                           RewriteOptions* options,
                           RewriteDriver* driver) {
    options->WriteableDomainLawyer()->AddDomain(domain, message_handler());
    CountingFilter* filter = new CountingFilter(driver);
    driver->AddOwnedPostRenderFilter(filter);
    driver->AddFilters();
    driver->StartParse(base_url);
    driver->Flush();
    return filter;
  }

  scoped_ptr<CountingFilter> filter_;
};

TEST_F(CommonFilterTest, DoesCallImpls) {
  EXPECT_EQ(0, filter_->start_doc_calls_);
  filter_->StartDocument();
  EXPECT_EQ(1, filter_->start_doc_calls_);

  RewriteDriver* driver = rewrite_driver();
  HtmlElement* element = driver->NewElement(NULL, "foo");
  EXPECT_EQ(0, filter_->start_element_calls_);
  filter_->StartElement(element);
  EXPECT_EQ(1, filter_->start_element_calls_);

  EXPECT_EQ(0, filter_->end_element_calls_);
  filter_->EndElement(element);
  EXPECT_EQ(1, filter_->end_element_calls_);
}

TEST_F(CommonFilterTest, StoresCorrectBaseUrl) {
  GoogleString doc_url = "http://www.example.com/";
  RewriteDriver* driver = rewrite_driver();
  driver->AddFilters();
  driver->StartParse(doc_url);
  driver->Flush();
  // Base URL starts out as document URL.
  ExpectUrl(doc_url, driver->google_url());
  ExpectUrl(doc_url, filter_->base_url());

  driver->ParseText(
      "<html><head><link rel='stylesheet' href='foo.css'>");
  driver->Flush();
  ExpectUrl(doc_url, filter_->base_url());

  GoogleString base_url = "http://www.baseurl.com/foo/";
  driver->ParseText("<base href='");
  driver->ParseText(base_url);
  driver->ParseText("' />");
  driver->Flush();
  // Update to base URL.
  ExpectUrl(base_url, filter_->base_url());
  // Make sure we didn't change the document URL.
  ExpectUrl(doc_url, driver->google_url());

  driver->ParseText("<link rel='stylesheet' href='foo.css'>");
  driver->Flush();
  ExpectUrl(base_url, filter_->base_url());

  GoogleString new_base_url = "http://www.somewhere-else.com/";
  driver->ParseText("<base href='");
  driver->ParseText(new_base_url);
  driver->ParseText("' />");
  driver->Flush();
  EXPECT_EQ(1, message_handler()->TotalMessages());

  // Uses old base URL.
  ExpectUrl(base_url, filter_->base_url());

  driver->ParseText("</head></html>");
  driver->Flush();
  ExpectUrl(base_url, filter_->base_url());
  driver->FinishParse();
  ExpectUrl(doc_url, driver->google_url());
}

TEST_F(CommonFilterTest, ResolveUrl) {
  GoogleUrl out;

  // Normal parse, no <base>
  GoogleString doc_url = "http://www.example.com/";
  RewriteDriver* driver = rewrite_driver();
  driver->AddFilters();
  driver->StartParse(doc_url);
  filter_->ResolveUrl("a.css", &out);
  ExpectUrl("http://www.example.com/a.css", out);
  driver->FinishParse();

  // Refs from base
  driver->StartParse(doc_url);
  driver->ParseText("<base href='https://www.example.org/' >");
  driver->Flush();
  filter_->ResolveUrl("a.css", &out);
  ExpectUrl("https://www.example.org/a.css", out);
  driver->FinishParse();

  // Nasty case: refs before base.
  driver->StartParse(doc_url);
  driver->set_refs_before_base();
  driver->ParseText("<html>");  // Establish non-AMP, allowing filters to run.
  driver->Flush();
  filter_->ResolveUrl("a.css", &out);
  EXPECT_FALSE(out.IsAnyValid());
  driver->ParseText("<base href='https://www.example.org/' ></html>");
  driver->Flush();
  filter_->ResolveUrl("a.css", &out);
  ExpectUrl("https://www.example.org/a.css", out);
  driver->FinishParse();
}

TEST_F(CommonFilterTest, DetectsNoScriptCorrectly) {
  GoogleString doc_url = "http://www.example.com/";
  RewriteDriver* driver = rewrite_driver();
  driver->AddFilters();
  driver->StartParse(doc_url);
  driver->Flush();
  EXPECT_TRUE(filter_->noscript_element() == NULL);

  driver->ParseText("<html><head><title>Example Site");
  driver->Flush();
  EXPECT_TRUE(filter_->noscript_element() == NULL);

  driver->ParseText("</title><noscript>");
  driver->Flush();
  EXPECT_TRUE(filter_->noscript_element() != NULL);

  // Nested <noscript> elements
  driver->ParseText("Blah blah blah <noscript><noscript> do-de-do-do ");
  driver->Flush();
  EXPECT_TRUE(filter_->noscript_element() != NULL);

  driver->ParseText("<link href='style.css'>");
  driver->Flush();
  EXPECT_TRUE(filter_->noscript_element() != NULL);

  // Close inner <noscript>s
  driver->ParseText("</noscript></noscript>");
  driver->Flush();
  EXPECT_TRUE(filter_->noscript_element() != NULL);

  // Close outter <noscript>
  driver->ParseText("</noscript>");
  driver->Flush();
  EXPECT_TRUE(filter_->noscript_element() == NULL);

  driver->ParseText("</head></html>");
  driver->FinishParse();
  EXPECT_TRUE(filter_->noscript_element() == NULL);
}

TEST_F(CommonFilterTest, TestTwoDomainLawyers) {
  static const char kBaseUrl[] = "http://www.base.com/";
  CommonFilter* a = MakeFilter(kBaseUrl, "a.com", options(), rewrite_driver());
  CommonFilter* b = MakeFilter(kBaseUrl, "b.com", other_options(),
                               other_rewrite_driver());

  // Either filter can rewrite resources from the base URL
  EXPECT_TRUE(CanRewriteResource(a, StrCat(kBaseUrl, "base.css")));
  EXPECT_TRUE(CanRewriteResource(b, StrCat(kBaseUrl, "base.css")));

  // But the other domains are specific to the two different drivers/filters
  EXPECT_TRUE(CanRewriteResource(a, "http://a.com/a.css"));
  EXPECT_FALSE(CanRewriteResource(a, "http://b.com/b.css"));
  EXPECT_FALSE(CanRewriteResource(b, "http://a.com/a.css"));
  EXPECT_TRUE(CanRewriteResource(b, "http://b.com/b.css"));
}

const char kEndDocumentComment[] = "<!--test comment-->";

class EndDocumentInserterFilter : public CommonFilter {
 public:
  explicit EndDocumentInserterFilter(RewriteDriver* driver)
      : CommonFilter(driver)
  {}

  virtual void EndDocument() {
    InsertNodeAtBodyEnd(driver()->NewCommentNode(NULL, "test comment"));
  }

  virtual void StartDocumentImpl() {}
  virtual void StartElementImpl(HtmlElement* element) {}
  virtual void EndElementImpl(HtmlElement* element) {}

  virtual const char* Name() const {
    return "CommonFilterTest.EndDocumentInserterFilter";
  }
};

class CommonFilterInsertNodeAtBodyEndTest : public RewriteTestBase {
 protected:
  virtual void SetUp() {
    RewriteTestBase::SetUp();
    filter_.reset(new EndDocumentInserterFilter(rewrite_driver()));
    rewrite_driver()->AddFilter(filter_.get());
    SetupWriter();
  }

  void StartTest(StringPiece pre_comment) {
    GoogleString url = "http://www.example.com/";
    rewrite_driver()->StartParse(url);
    rewrite_driver()->ParseText(pre_comment);
  }

  const GoogleString FinishTest(StringPiece pre_comment,
                                StringPiece post_comment) {
    const GoogleString expected_html =
        StrCat(pre_comment, kEndDocumentComment, post_comment);
    rewrite_driver()->ParseText(post_comment);
    rewrite_driver()->FinishParse();
    return expected_html;
  }

  const GoogleString FullTest(StringPiece pre_comment,
                              StringPiece post_comment) {
    StartTest(pre_comment);
    return FinishTest(pre_comment, post_comment);
  }

  const GoogleString FlushTest(StringPiece pre_flush, StringPiece pre_comment,
                               StringPiece post_comment) {
    StartTest(pre_flush);
    rewrite_driver()->Flush();
    rewrite_driver()->ParseText(pre_comment);
    GoogleString full_pre_comment = StrCat(pre_flush, pre_comment);
    return FinishTest(full_pre_comment, post_comment);
  }

  scoped_ptr<EndDocumentInserterFilter> filter_;
};

TEST_F(CommonFilterInsertNodeAtBodyEndTest, OneBody) {
  GoogleString expected =
      FullTest("<html><head></head><body>", "</body></html>");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, WhiteSpace) {
  GoogleString expected =
      FullTest("<html><head></head><body>", "</body>\n</html>");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, NoBody) {
  GoogleString expected =
      FullTest("some content without body tag\n</html>", "");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, NoCloseBody) {
  GoogleString expected =
      FullTest("<html><head></head><body><img src=\"a.jpg\">", "</html>");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, FlushInBody) {
  GoogleString expected =
      FlushTest("<html><head></head><body>", "", "</body></html>");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, FlushBeforeBody) {
  GoogleString expected =
      FlushTest("<html><head></head>", "<body>", "</body></html>");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, FlushAfterCloseBody) {
  // kEndDocumentComment gets inserted after </body> since both the open and
  // close tags have been flushed already.
  GoogleString expected =
      FlushTest("<html><head></head><body></body>", "", "</html>");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, FlushAtEnd) {
  // This causes us to append to the end of document after the flush.
  GoogleString expected =
      FlushTest("<html><head></head><body></body></html>", "", "");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, TwoBodies) {
  GoogleString expected =
      FullTest("<html><head></head><body></body><body>", "</body></html>");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, TextAfterCloseBody) {
  GoogleString expected =
      FullTest("<html><head></head><body></body>extra text", "</html>");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, TextAfterCloseHtml) {
  GoogleString expected =
      FullTest("<html><head></head><body></body></html>extra text", "");
  EXPECT_STREQ(expected, output_buffer_);
}

TEST_F(CommonFilterInsertNodeAtBodyEndTest, BodyInNoscript) {
  GoogleString expected = FullTest(
      "<html><head></head><noscript><body></body></noscript>", "</html>");
  EXPECT_STREQ(expected, output_buffer_);
}

}  // namespace

}  // namespace net_instaweb
