// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// 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.

#include <algorithm>
#include <memory>
#include <vector>

#include "base/json/json_reader.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/testing/stub_window.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/script/javascript_engine.h"
#include "cobalt/webdriver/script_executor.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::DefaultValue;
using ::testing::Return;

namespace cobalt {
namespace webdriver {
namespace {

class MockElementMapping : public ElementMapping {
 public:
  MOCK_METHOD1(ElementToId,
               protocol::ElementId(const scoped_refptr<dom::Element>&));
  MOCK_METHOD1(IdToElement,
               scoped_refptr<dom::Element>(const protocol::ElementId& id));
};

class MockScriptExecutorResult : public ScriptExecutorResult::ResultHandler {
 public:
  MOCK_METHOD1(OnResult, void(const std::string&));
  MOCK_METHOD0(OnTimeout, void());
};

class JSONScriptExecutorResult : public ScriptExecutorResult::ResultHandler {
 public:
  void OnResult(const std::string& result) {
    json_result_ = base::JSONReader::Read(result.c_str());
  }
  void OnTimeout() { NOTREACHED(); }
  base::Value* json_result() { return json_result_.get(); }

 private:
  std::unique_ptr<base::Value> json_result_;
};

class ScriptExecutorTest : public ::testing::Test {
 protected:
  void SetUp() override {
    stub_window_.reset(new dom::testing::StubWindow());
    script_executor_ =
        ScriptExecutor::Create(&element_mapping_, global_environment());

    ON_CALL(element_mapping_, IdToElement(_))
        .WillByDefault(Return(scoped_refptr<dom::Element>()));
    ON_CALL(element_mapping_, ElementToId(_))
        .WillByDefault(Return(protocol::ElementId("bad-id")));
  }

  scoped_refptr<dom::Window> window() { return stub_window_->window(); }
  scoped_refptr<script::GlobalEnvironment> global_environment() {
    return stub_window_->global_environment();
  }

 protected:
  std::unique_ptr<dom::testing::StubWindow> stub_window_;
  MockElementMapping element_mapping_;
  scoped_refptr<ScriptExecutor> script_executor_;
};

}  // namespace

TEST_F(ScriptExecutorTest, CreateSyncScript) {
  auto gc_prevented_params =
      ScriptExecutorParams::Create(global_environment(), "return 5;", "[]");
  ASSERT_TRUE(gc_prevented_params.params);
  EXPECT_NE(
      reinterpret_cast<intptr_t>(gc_prevented_params.params->function_object()),
      NULL);
  EXPECT_STREQ(gc_prevented_params.params->json_args().c_str(), "[]");
  EXPECT_EQ(gc_prevented_params.params->async_timeout(), base::nullopt);
}

TEST_F(ScriptExecutorTest, CreateAsyncScript) {
  auto gc_prevented_params =
      ScriptExecutorParams::Create(global_environment(), "return 5;", "[]",
                                   base::TimeDelta::FromMilliseconds(5));
  ASSERT_TRUE(gc_prevented_params.params);
  EXPECT_NE(
      reinterpret_cast<intptr_t>(gc_prevented_params.params->function_object()),
      NULL);
  EXPECT_STREQ(gc_prevented_params.params->json_args().c_str(), "[]");
  EXPECT_EQ(gc_prevented_params.params->async_timeout(), 5);
}

TEST_F(ScriptExecutorTest, CreateInvalidScript) {
  auto gc_prevented_params =
      ScriptExecutorParams::Create(global_environment(), "retarn 5ish;", "[]");
  ASSERT_TRUE(gc_prevented_params.params);
  EXPECT_EQ(
      reinterpret_cast<intptr_t>(gc_prevented_params.params->function_object()),
      NULL);
}

TEST_F(ScriptExecutorTest, ExecuteSync) {
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(), "return \"retval\";", "[]");
  ASSERT_TRUE(gc_prevented_params.params);
  MockScriptExecutorResult result_handler;
  EXPECT_CALL(result_handler, OnResult(std::string("\"retval\"")));
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
}

TEST_F(ScriptExecutorTest, FLAKY_ExecuteAsync) {
  // Create a script that will call the async callback after 50 ms, with
  // an async timeout of 100 ms.
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(),
      "var callback = arguments[0];"
      "window.setTimeout(function() { callback(72); }, 50);",
      "[]", base::TimeDelta::FromMilliseconds(100));
  ASSERT_TRUE(gc_prevented_params.params);
  MockScriptExecutorResult result_handler;
  EXPECT_CALL(result_handler, OnResult(std::string("72")));
  EXPECT_CALL(result_handler, OnTimeout()).Times(0);

  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));

  // Let the message loop run for 200ms to allow enough time for the async
  // script to fire the callback.
  base::RunLoop run_loop;
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, run_loop.QuitClosure(),
      base::TimeDelta::FromMilliseconds(200));
  run_loop.Run();
}

TEST_F(ScriptExecutorTest, AsyncTimeout) {
  // Create a script that will call the async callback after 10 seconds, with
  // an async timeout of 100 ms.
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(),
      "var callback = arguments[0];"
      "window.setTimeout(function() { callback(72); }, 10000);",
      "[]", base::TimeDelta::FromMilliseconds(100));
  ASSERT_TRUE(gc_prevented_params.params);
  MockScriptExecutorResult result_handler;
  EXPECT_CALL(result_handler, OnResult(_)).Times(0);
  EXPECT_CALL(result_handler, OnTimeout()).Times(1);

  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));

  // Let the message loop run for 200ms to allow enough time for the async
  // timeout to fire.
  base::RunLoop run_loop;
  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE, run_loop.QuitClosure(),
      base::TimeDelta::FromMilliseconds(200));
  run_loop.Run();
}

TEST_F(ScriptExecutorTest, ScriptThrowsException) {
  auto gc_prevented_params =
      ScriptExecutorParams::Create(global_environment(), "throw Error()", "[]");
  ASSERT_TRUE(gc_prevented_params.params);
  MockScriptExecutorResult result_handler;
  EXPECT_FALSE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
}

TEST_F(ScriptExecutorTest, ConvertBoolean) {
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(), "return arguments[0];", "[true]");
  ASSERT_TRUE(gc_prevented_params.params);
  MockScriptExecutorResult result_handler;
  EXPECT_CALL(result_handler, OnResult(std::string("true")));
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));

  gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(), "return arguments[0];", "[false]");
  ASSERT_TRUE(gc_prevented_params.params);
  EXPECT_CALL(result_handler, OnResult(std::string("false")));
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
}

TEST_F(ScriptExecutorTest, ConvertNull) {
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(), "return arguments[0];", "[null]");
  ASSERT_TRUE(gc_prevented_params.params);
  MockScriptExecutorResult result_handler;
  EXPECT_CALL(result_handler, OnResult(std::string("null")));
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
}

TEST_F(ScriptExecutorTest, ConvertNumericType) {
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(), "return arguments[0];", "[6]");
  ASSERT_TRUE(gc_prevented_params.params);
  MockScriptExecutorResult result_handler;
  EXPECT_CALL(result_handler, OnResult(std::string("6")));
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));

  gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(), "return arguments[0];", "[-6.4]");
  ASSERT_TRUE(gc_prevented_params.params);
  EXPECT_CALL(result_handler, OnResult(std::string("-6.4")));
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
}

TEST_F(ScriptExecutorTest, ConvertString) {
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(), "return arguments[0];", "[\"Mr. T\"]");
  ASSERT_TRUE(gc_prevented_params.params);
  MockScriptExecutorResult result_handler;
  EXPECT_CALL(result_handler, OnResult(std::string("\"Mr. T\"")));
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
}

TEST_F(ScriptExecutorTest, ConvertWebElement) {
  // Create a dom::Element for the MockElementMapping to return.
  scoped_refptr<dom::Element> element =
      window()->document()->CreateElement("p");
  EXPECT_CALL(element_mapping_, IdToElement(protocol::ElementId("id123")))
      .WillRepeatedly(Return(element));
  EXPECT_CALL(element_mapping_, ElementToId(element))
      .WillRepeatedly(Return(protocol::ElementId("id123")));

  // Create a script that will pass a web element argument as a parameter, and
  // return it back. This will invoke the lookup to and from an id.
  auto gc_prevented_params =
      ScriptExecutorParams::Create(global_environment(), "return arguments[0];",
                                   "[ {\"ELEMENT\": \"id123\"} ]");
  ASSERT_TRUE(gc_prevented_params.params);

  // Execute the script and parse the result as JSON, ensuring we got the same
  // web element.
  JSONScriptExecutorResult result_handler;
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
  ASSERT_TRUE(result_handler.json_result());

  std::string element_id;
  base::DictionaryValue* dictionary_value;
  ASSERT_TRUE(result_handler.json_result()->GetAsDictionary(&dictionary_value));
  EXPECT_TRUE(dictionary_value->GetString(protocol::ElementId::kElementKey,
                                          &element_id));
  EXPECT_STREQ(element_id.c_str(), "id123");
}

TEST_F(ScriptExecutorTest, ConvertArray) {
  // Create a script that takes an array of numbers as input, and returns an
  // array of those numbers incremented by one.
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(),
      "return [ (arguments[0][0]+1), (arguments[0][1]+1) ];", "[ [5, 6] ]");
  ASSERT_TRUE(gc_prevented_params.params);

  JSONScriptExecutorResult result_handler;
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
  ASSERT_TRUE(result_handler.json_result());

  base::ListValue* list_value;
  ASSERT_TRUE(result_handler.json_result()->GetAsList(&list_value));
  ASSERT_EQ(list_value->GetSize(), 2);

  int value;
  EXPECT_TRUE(list_value->GetInteger(0, &value));
  EXPECT_EQ(value, 6);
  EXPECT_TRUE(list_value->GetInteger(1, &value));
  EXPECT_EQ(value, 7);
}

TEST_F(ScriptExecutorTest, ConvertObject) {
  // Create a script that takes an Object with two properties as input, and
  // returns an Object with one property that is the sum of the other Object's
  // properties.
  auto gc_prevented_params = ScriptExecutorParams::Create(
      global_environment(),
      "return {\"sum\": arguments[0].a + arguments[0].b};",
      "[ {\"a\":5, \"b\":6} ]");
  ASSERT_TRUE(gc_prevented_params.params);

  JSONScriptExecutorResult result_handler;
  EXPECT_TRUE(
      script_executor_->Execute(gc_prevented_params.params, &result_handler));
  ASSERT_TRUE(result_handler.json_result());

  int value;
  base::DictionaryValue* dictionary_value;
  ASSERT_TRUE(result_handler.json_result()->GetAsDictionary(&dictionary_value));
  EXPECT_TRUE(dictionary_value->GetInteger("sum", &value));
  EXPECT_EQ(value, 11);
}

}  // namespace webdriver
}  // namespace cobalt
