// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "gn/operators.h"

#include <stdint.h>

#include <memory>
#include <utility>

#include "gn/parse_tree.h"
#include "gn/pattern.h"
#include "gn/test_with_scope.h"
#include "util/test/test.h"

namespace {

bool IsValueIntegerEqualing(const Value& v, int64_t i) {
  if (v.type() != Value::INTEGER)
    return false;
  return v.int_value() == i;
}

bool IsValueStringEqualing(const Value& v, const char* s) {
  if (v.type() != Value::STRING)
    return false;
  return v.string_value() == s;
}

// This parse node is for passing to tests. It returns a canned value for
// Execute().
class TestParseNode : public ParseNode {
 public:
  TestParseNode(const Value& v) : value_(v) {}

  Value Execute(Scope* scope, Err* err) const override { return value_; }
  LocationRange GetRange() const override { return LocationRange(); }
  Err MakeErrorDescribing(const std::string& msg,
                          const std::string& help) const override {
    return Err(this, msg);
  }
  base::Value GetJSONNode() const override { return base::Value(); }

 private:
  Value value_;
};

// Sets up a BinaryOpNode for testing.
class TestBinaryOpNode : public BinaryOpNode {
 public:
  // Input token value string must outlive class.
  TestBinaryOpNode(Token::Type op_token_type, const char* op_token_value)
      : BinaryOpNode(),
        op_token_ownership_(Location(), op_token_type, op_token_value) {
    set_op(op_token_ownership_);
  }

  void SetLeftToValue(const Value& value) {
    set_left(std::make_unique<TestParseNode>(value));
  }

  // Sets the left-hand side of the operator to an identifier node, this is
  // used for testing assignments. Input string must outlive class.
  void SetLeftToIdentifier(const char* identifier) {
    left_identifier_token_ownership_ =
        Token(Location(), Token::IDENTIFIER, identifier);
    set_left(
        std::make_unique<IdentifierNode>(left_identifier_token_ownership_));
  }

  void SetRightToValue(const Value& value) {
    set_right(std::make_unique<TestParseNode>(value));
  }
  void SetRightToListOfValue(const Value& value) {
    Value list(nullptr, Value::LIST);
    list.list_value().push_back(value);
    set_right(std::make_unique<TestParseNode>(list));
  }
  void SetRightToListOfValue(const Value& value1, const Value& value2) {
    Value list(nullptr, Value::LIST);
    list.list_value().push_back(value1);
    list.list_value().push_back(value2);
    set_right(std::make_unique<TestParseNode>(list));
  }

 private:
  // The base class takes the Token by reference, this manages the lifetime.
  Token op_token_ownership_;

  // When setting the left to an identifier, this manages the lifetime of
  // the identifier token.
  Token left_identifier_token_ownership_;
};

}  // namespace

TEST(Operators, SourcesAppend) {
  Err err;
  TestWithScope setup;

  // Set up "sources" with an empty list.
  const char sources[] = "sources";
  setup.scope()->SetValue(sources, Value(nullptr, Value::LIST), nullptr);

  // Set up the operator.
  TestBinaryOpNode node(Token::PLUS_EQUALS, "+=");
  node.SetLeftToIdentifier(sources);

  // Append an integer.
  node.SetRightToListOfValue(Value(nullptr, static_cast<int64_t>(5)));
  node.Execute(setup.scope(), &err);
  EXPECT_SUCCESS(err);

  // Append a string that doesn't match the pattern, it should get appended.
  const char string1[] = "good";
  node.SetRightToListOfValue(Value(nullptr, string1));
  node.Execute(setup.scope(), &err);
  EXPECT_SUCCESS(err);

  // Append a list with the two strings from above.
  node.SetRightToListOfValue(Value(nullptr, string1));
  node.Execute(setup.scope(), &err);
  EXPECT_SUCCESS(err);

  // The sources variable in the scope should now have: [ 5, "good", "good" ]
  const Value* value = setup.scope()->GetValue(sources);
  ASSERT_TRUE(value);
  ASSERT_EQ(Value::LIST, value->type());
  ASSERT_EQ(3u, value->list_value().size());
  EXPECT_TRUE(IsValueIntegerEqualing(value->list_value()[0], 5));
  EXPECT_TRUE(IsValueStringEqualing(value->list_value()[1], "good"));
  EXPECT_TRUE(IsValueStringEqualing(value->list_value()[2], "good"));
}

// Note that the SourcesAppend test above tests the basic list + list features,
// this test handles the other cases.
TEST(Operators, ListAppend) {
  Err err;
  TestWithScope setup;

  // Set up "foo" with an empty list.
  const char foo[] = "foo";
  setup.scope()->SetValue(foo, Value(nullptr, Value::LIST), nullptr);

  // Set up the operator to append to "foo".
  TestBinaryOpNode node(Token::PLUS_EQUALS, "+=");
  node.SetLeftToIdentifier(foo);

  // Append a list with a list, the result should be a nested list.
  Value inner_list(nullptr, Value::LIST);
  inner_list.list_value().push_back(Value(nullptr, static_cast<int64_t>(12)));
  node.SetRightToListOfValue(inner_list);

  Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
                                    node.right(), &err);
  EXPECT_SUCCESS(err);

  // Return from the operator should always be "none", it should update the
  // value only.
  EXPECT_EQ(Value::NONE, ret.type());

  // The value should be updated with "[ [ 12 ] ]"
  Value result = *setup.scope()->GetValue(foo);
  ASSERT_EQ(Value::LIST, result.type());
  ASSERT_EQ(1u, result.list_value().size());
  ASSERT_EQ(Value::LIST, result.list_value()[0].type());
  ASSERT_EQ(1u, result.list_value()[0].list_value().size());
  ASSERT_EQ(Value::INTEGER, result.list_value()[0].list_value()[0].type());
  ASSERT_EQ(12, result.list_value()[0].list_value()[0].int_value());

  // Try to append an integer and a string directly (e.g. foo += "hi").
  // This should fail.
  const char str_str[] = "\"hi\"";
  Token str(Location(), Token::STRING, str_str);
  node.set_right(std::make_unique<LiteralNode>(str));
  ExecuteBinaryOperator(setup.scope(), &node, node.left(), node.right(), &err);
  EXPECT_TRUE(err.has_error());
  err = Err();

  node.SetRightToValue(Value(nullptr, static_cast<int64_t>(12)));
  ExecuteBinaryOperator(setup.scope(), &node, node.left(), node.right(), &err);
  EXPECT_TRUE(err.has_error());
}

TEST(Operators, ListRemove) {
  Err err;
  TestWithScope setup;

  const char foo_str[] = "foo";
  const char bar_str[] = "bar";
  Value test_list(nullptr, Value::LIST);
  test_list.list_value().push_back(Value(nullptr, foo_str));
  test_list.list_value().push_back(Value(nullptr, bar_str));
  test_list.list_value().push_back(Value(nullptr, foo_str));

  // Set up "var" with an the test list.
  const char var[] = "var";
  setup.scope()->SetValue(var, test_list, nullptr);

  TestBinaryOpNode node(Token::MINUS_EQUALS, "-=");
  node.SetLeftToIdentifier(var);

  // Subtract a list consisting of "foo".
  node.SetRightToListOfValue(Value(nullptr, foo_str));
  Value result = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
                                       node.right(), &err);
  EXPECT_SUCCESS(err);

  // -= returns an empty value to reduce the possibility of writing confusing
  // cases like foo = bar += 1.
  EXPECT_EQ(Value::NONE, result.type());

  // The "var" variable should have been updated. Both instances of "foo" are
  // deleted.
  const Value* new_value = setup.scope()->GetValue(var);
  ASSERT_TRUE(new_value);
  ASSERT_EQ(Value::LIST, new_value->type());
  ASSERT_EQ(1u, new_value->list_value().size());
  ASSERT_EQ(Value::STRING, new_value->list_value()[0].type());
  EXPECT_EQ("bar", new_value->list_value()[0].string_value());
}

TEST(Operators, ListSubtractWithScope) {
  Err err;
  TestWithScope setup;

  Scope* scope_a = new Scope(setup.settings());
  Value scopeval_a(nullptr, std::unique_ptr<Scope>(scope_a));
  scope_a->SetValue("a", Value(nullptr, "foo"), nullptr);

  Scope* scope_b = new Scope(setup.settings());
  Value scopeval_b(nullptr, std::unique_ptr<Scope>(scope_b));
  scope_b->SetValue("b", Value(nullptr, "bar"), nullptr);

  Value lval(nullptr, Value::LIST);
  lval.list_value().push_back(scopeval_a);
  lval.list_value().push_back(scopeval_b);

  Scope* scope_a_other = new Scope(setup.settings());
  Value scopeval_a_other(nullptr, std::unique_ptr<Scope>(scope_a_other));
  scope_a_other->SetValue("a", Value(nullptr, "foo"), nullptr);

  Value rval(nullptr, Value::LIST);
  rval.list_value().push_back(scopeval_a_other);

  TestBinaryOpNode node(Token::MINUS, "-");
  node.SetLeftToValue(lval);
  node.SetRightToValue(rval);
  Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
                                    node.right(), &err);
  ASSERT_SUCCESS(err);
  ASSERT_EQ(Value::LIST, ret.type());

  std::vector<Value> expected;
  Scope* scope_expected = new Scope(setup.settings());
  Value scopeval_expected(nullptr, std::unique_ptr<Scope>(scope_expected));
  scope_expected->SetValue("b", Value(nullptr, "bar"), nullptr);
  expected.push_back(scopeval_expected);
  EXPECT_EQ(expected, ret.list_value());
}

TEST(Operators, IntegerAdd) {
  Err err;
  TestWithScope setup;

  TestBinaryOpNode node(Token::PLUS, "+");
  node.SetLeftToValue(Value(nullptr, static_cast<int64_t>(123)));
  node.SetRightToValue(Value(nullptr, static_cast<int64_t>(456)));
  Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
                                    node.right(), &err);
  ASSERT_SUCCESS(err);
  ASSERT_EQ(Value::INTEGER, ret.type());
  EXPECT_EQ(579, ret.int_value());
}

TEST(Operators, IntegerSubtract) {
  Err err;
  TestWithScope setup;

  TestBinaryOpNode node(Token::MINUS, "-");
  node.SetLeftToValue(Value(nullptr, static_cast<int64_t>(123)));
  node.SetRightToValue(Value(nullptr, static_cast<int64_t>(456)));
  Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
                                    node.right(), &err);
  ASSERT_SUCCESS(err);
  ASSERT_EQ(Value::INTEGER, ret.type());
  EXPECT_EQ(-333, ret.int_value());
}

TEST(Operators, ShortCircuitAnd) {
  Err err;
  TestWithScope setup;

  // Set a && operator with the left to false.
  TestBinaryOpNode node(Token::BOOLEAN_AND, "&&");
  node.SetLeftToValue(Value(nullptr, false));

  // Set right as foo, but don't define a value for it.
  const char foo[] = "foo";
  Token identifier_token(Location(), Token::IDENTIFIER, foo);
  node.set_right(std::make_unique<IdentifierNode>(identifier_token));

  Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
                                    node.right(), &err);
  EXPECT_SUCCESS(err);
}

TEST(Operators, ShortCircuitOr) {
  Err err;
  TestWithScope setup;

  // Set a || operator with the left to true.
  TestBinaryOpNode node(Token::BOOLEAN_OR, "||");
  node.SetLeftToValue(Value(nullptr, true));

  // Set right as foo, but don't define a value for it.
  const char foo[] = "foo";
  Token identifier_token(Location(), Token::IDENTIFIER, foo);
  node.set_right(std::make_unique<IdentifierNode>(identifier_token));

  Value ret = ExecuteBinaryOperator(setup.scope(), &node, node.left(),
                                    node.right(), &err);
  EXPECT_SUCCESS(err);
}

// Overwriting nonempty lists and scopes with other nonempty lists and scopes
// should be disallowed.
TEST(Operators, NonemptyOverwriting) {
  Err err;
  TestWithScope setup;

  // Set up "foo" with a nonempty list.
  const char foo[] = "foo";
  Value old_value(nullptr, Value::LIST);
  old_value.list_value().push_back(Value(nullptr, "string"));
  setup.scope()->SetValue(foo, old_value, nullptr);

  TestBinaryOpNode node(Token::EQUAL, "=");
  node.SetLeftToIdentifier(foo);

  // Assigning a nonempty list should fail.
  node.SetRightToListOfValue(Value(nullptr, "string"));
  node.Execute(setup.scope(), &err);
  ASSERT_TRUE(err.has_error());
  EXPECT_EQ("Replacing nonempty list.", err.message());
  err = Err();

  // Assigning an empty list should succeed.
  node.SetRightToValue(Value(nullptr, Value::LIST));
  node.Execute(setup.scope(), &err);
  ASSERT_SUCCESS(err);
  const Value* new_value = setup.scope()->GetValue(foo);
  ASSERT_TRUE(new_value);
  ASSERT_EQ(Value::LIST, new_value->type());
  ASSERT_TRUE(new_value->list_value().empty());

  // Set up "foo" with a nonempty scope.
  const char bar[] = "bar";
  old_value = Value(nullptr, std::make_unique<Scope>(setup.settings()));
  old_value.scope_value()->SetValue(bar, Value(nullptr, "bar"), nullptr);
  setup.scope()->SetValue(foo, old_value, nullptr);

  // Assigning a nonempty scope should fail (re-use old_value copy).
  node.SetRightToValue(old_value);
  node.Execute(setup.scope(), &err);
  ASSERT_TRUE(err.has_error());
  EXPECT_EQ("Replacing nonempty scope.", err.message());
  err = Err();

  // Assigning an empty list should succeed.
  node.SetRightToValue(
      Value(nullptr, std::make_unique<Scope>(setup.settings())));
  node.Execute(setup.scope(), &err);
  ASSERT_SUCCESS(err);
  new_value = setup.scope()->GetValue(foo);
  ASSERT_TRUE(new_value);
  ASSERT_EQ(Value::SCOPE, new_value->type());
  ASSERT_FALSE(new_value->scope_value()->HasValues(Scope::SEARCH_CURRENT));
}

// Tests this case:
//  foo = 1
//  target(...) {
//    foo += 1
//
// This should mark the outer "foo" as used, and the inner "foo" as unused.
TEST(Operators, PlusEqualsUsed) {
  Err err;
  TestWithScope setup;

  // Outer "foo" definition, it should be unused.
  const char foo[] = "foo";
  Value old_value(nullptr, static_cast<int64_t>(1));
  setup.scope()->SetValue(foo, old_value, nullptr);
  EXPECT_TRUE(setup.scope()->IsSetButUnused(foo));

  // Nested scope.
  Scope nested(setup.scope());

  // Run "foo += 1".
  TestBinaryOpNode node(Token::PLUS_EQUALS, "+=");
  node.SetLeftToIdentifier(foo);
  node.SetRightToValue(Value(nullptr, static_cast<int64_t>(1)));
  node.Execute(&nested, &err);
  ASSERT_SUCCESS(err);

  // Outer foo should be used, inner foo should not be.
  EXPECT_FALSE(setup.scope()->IsSetButUnused(foo));
  EXPECT_TRUE(nested.IsSetButUnused(foo));
}
