/*
 * 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/rewriter/public/redirect_on_size_limit_filter.h"

#include <algorithm>

#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/test_rewrite_driver_factory.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/string_writer.h"

namespace net_instaweb {

namespace {

static const char kScript[] = "<script type=\"text/javascript\">"
    "window.location=\"http://test.com/in.html?PageSpeed=off\";"
    "</script>";

}  // namespace

class RedirectOnSizeLimitFilterTest : public RewriteTestBase {
 public:
  RedirectOnSizeLimitFilterTest() : writer_(&output_) {}

 protected:
  virtual void SetUp() {}

  void SetupDriver(int size_limit) {
    options_->set_max_html_parse_bytes(size_limit);
    options_->EnableFilter(RewriteOptions::kHtmlWriterFilter);
    RewriteTestBase::SetUp();
    rewrite_driver()->AddFilters();
    rewrite_driver()->SetWriter(&writer_);
  }

  void ClearAndResetDriver(int size_limit) {
    delete rewrite_driver();
    delete other_rewrite_driver();
    output_.clear();
    options_ = new RewriteOptions(factory()->thread_system());
    other_options_ = new RewriteOptions(factory()->thread_system());
    SetupDriver(size_limit);
  }

  void CheckOutput(int start_index, int end_index,
                   bool should_flush_before_size,
                   const GoogleString& input,
                   const GoogleString& expected_output) {
    for (int i = start_index; i < end_index; ++i) {
      ClearAndResetDriver(i);
      if (should_flush_before_size && i > 2) {
        html_parse()->StartParse("http://test.com/in.html");
        int split = std::min(static_cast<int>(input.size()) - 1, i);
        html_parse()->ParseText(input.substr(0, split));
        html_parse()->Flush();
        html_parse()->ParseText(input.substr(split, input.size() - 1));
        html_parse()->FinishParse();
      } else {
        Parse("in", input);
      }
      EXPECT_EQ(expected_output, output_);
    }
  }

  virtual bool AddHtmlTags() const { return false; }
  virtual bool AddBody() const { return false; }

  GoogleString output_;

 private:
  StringWriter writer_;

  DISALLOW_COPY_AND_ASSIGN(RedirectOnSizeLimitFilterTest);
};

TEST_F(RedirectOnSizeLimitFilterTest, TestOneFlushWindow) {
  static const char input[] =
      "<html>"  // 6 chars
      "<input type=\"text\"/>"  // 20 chars
      "<script type=\"text/javascript\">alert('123');</script>"  // 53 chars
      "<!--[if IE]>...<![endif]-->"  // 27 chars
      "<table><tr><td>blah</td></tr></table>"  // 37 chars
      "</html>";  // 7 chars

  SetupDriver(-1);
  Parse("in", input);
  EXPECT_EQ(input, output_);

  CheckOutput(0, 1, false, input, input);

  CheckOutput(1, 149, false, input,  StringPrintf("<html>%s</html>", kScript));

  CheckOutput(150, 180, false, input, input);
}

TEST_F(RedirectOnSizeLimitFilterTest, TestFlushBeforeLimit) {
  const char input[] =
      "<html>"  // 6 chars
      "<input type=\"text\"/>"  // 20 chars
      "<script type=\"text/javascript\">alert('123');</script>"  // 53 chars
      "<!--[if IE]>...<![endif]-->"  // 27 chars
      "<table><tr><td>blah</td></tr></table>"  // 37 chars
      "</html>";  // 7 chars

  SetupDriver(-1);
  Parse("in", input);
  EXPECT_EQ(input, output_);

  CheckOutput(0, 1, true, input, input);

  CheckOutput(1, 6, true, input,  StringPrintf("<html>%s</html>", kScript));

  CheckOutput(6, 26, true, input,
              StringPrintf("<html>%s<input type=\"text\"/></html>",  kScript));

  CheckOutput(26, 57, true, input,
      StringPrintf("<html><input type=\"text\"/>%s"
                   "<script type=\"text/javascript\"></script></html>",
                   kScript));

  CheckOutput(57, 79, true, input,
      StringPrintf("<html><input type=\"text\"/>"
                   "%s<script type=\"text/javascript\">alert('123');</script>"
                   "</html>", kScript));

  CheckOutput(79, 113, true, input,
      StringPrintf("<html><input type=\"text\"/>"
                   "<script type=\"text/javascript\">alert('123');</script>"
                   "<!--[if IE]>...<![endif]-->%s<table></table></html>",
                   kScript));

  CheckOutput(113, 117, true, input,
      StringPrintf("<html><input type=\"text\"/>"
      "<script type=\"text/javascript\">alert('123');</script>"
      "<!--[if IE]>...<![endif]-->"
      "<table>%s<tr></tr></table></html>", kScript));

  CheckOutput(117, 121, true, input,
      StringPrintf("<html><input type=\"text\"/>"
                   "<script type=\"text/javascript\">alert('123');</script>"
                   "<!--[if IE]>...<![endif]-->"
                   "<table><tr>%s<td></td></tr></table></html>", kScript));

  CheckOutput(121, 130, true, input,
      StringPrintf("<html><input type=\"text\"/>"
                   "<script type=\"text/javascript\">alert('123');</script>"
                   "<!--[if IE]>...<![endif]-->"
                   "<table><tr><td>blah</td>%s</tr></table></html>", kScript));

  CheckOutput(130, 135, true, input,
      StringPrintf("<html><input type=\"text\"/>"
                   "<script type=\"text/javascript\">alert('123');</script>"
                   "<!--[if IE]>...<![endif]-->"
                   "<table><tr><td>blah</td></tr>%s</table></html>", kScript));

  CheckOutput(135, 150, true, input,
      StringPrintf("<html><input type=\"text\"/>"
                   "<script type=\"text/javascript\">alert('123');</script>"
                   "<!--[if IE]>...<![endif]-->"
                   "<table><tr><td>blah</td></tr></table>%s</html>", kScript));

  CheckOutput(150, 160, true, input, input);
}

TEST_F(RedirectOnSizeLimitFilterTest, TestEscapingAndFlush) {
  SetupDriver(100);
  // Depending on the version of Chromium GURL used, we get different quoting
  // for a single-quote.  Either is acceptable.
  static const char kOutput[] =
      "<html>"
      "<input type=\"text\"/>"
      "<script type=\"text/javascript\">"
      "window.location=\"http://test.com/in.html?%27(&PageSpeed=off\";"
      "</script>"
      "<script type=\"text/javascript\">alert('123');</script>"
      "</html>";

  static const char kOutputAlt[] =
      "<html>"
      "<input type=\"text\"/>"
      "<script type=\"text/javascript\">"
      "window.location=\"http://test.com/in.html?\\'(&PageSpeed=off\";"
      "</script>"
      "<script type=\"text/javascript\">alert('123');</script>"
      "</html>";

  html_parse()->StartParse("http://test.com/in.html?'(");
  html_parse()->ParseText(
      "<html><input type=\"text\"/>"
      "<script type=\"text/javascript\">");
  html_parse()->Flush();
  html_parse()->ParseText(
      "alert('123');</script>"
      "<!--[if IE]>...<![endif]-->"
      "<table><tr><td>blah</td></tr></table></html>");
  html_parse()->FinishParse();

  EXPECT_TRUE((kOutput == output_) || (kOutputAlt == output_)) << output_;
}

}  // namespace net_instaweb
