// Copyright 2015 the V8 project 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 "src/compiler/common-operator.h"
#include "src/compiler/node-properties.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock/include/gmock/gmock.h"

using testing::AnyOf;
using testing::ElementsAre;
using testing::IsNull;

namespace v8 {
namespace internal {
namespace compiler {
namespace node_properties_unittest {

class NodePropertiesTest : public TestWithZone {
 public:
  Node* NewMockNode(const Operator* op) {
    return Node::New(zone(), 0, op, 0, nullptr, false);
  }
  Node* NewMockNode(const Operator* op, Node* n1) {
    Node* nodes[] = {n1};
    return Node::New(zone(), 0, op, arraysize(nodes), nodes, false);
  }
  Node* NewMockNode(const Operator* op, Node* n1, Node* n2) {
    Node* nodes[] = {n1, n2};
    return Node::New(zone(), 0, op, arraysize(nodes), nodes, false);
  }
};

namespace {

const Operator kMockOperator(IrOpcode::kDead, Operator::kNoProperties,
                             "MockOperator", 0, 0, 0, 1, 1, 2);
const Operator kMockCallOperator(IrOpcode::kCall, Operator::kNoProperties,
                                 "MockCallOperator", 0, 0, 0, 0, 0, 2);

}  // namespace


TEST_F(NodePropertiesTest, ReplaceUses) {
  CommonOperatorBuilder common(zone());
  Node* node = NewMockNode(&kMockOperator);
  Node* effect = NewMockNode(&kMockOperator);
  Node* use_value = NewMockNode(common.Return(), node);
  Node* use_effect = NewMockNode(common.EffectPhi(1), node);
  Node* use_success = NewMockNode(common.IfSuccess(), node);
  Node* use_exception = NewMockNode(common.IfException(), effect, node);
  Node* r_value = NewMockNode(&kMockOperator);
  Node* r_effect = NewMockNode(&kMockOperator);
  Node* r_success = NewMockNode(&kMockOperator);
  Node* r_exception = NewMockNode(&kMockOperator);
  NodeProperties::ReplaceUses(node, r_value, r_effect, r_success, r_exception);
  EXPECT_EQ(r_value, use_value->InputAt(0));
  EXPECT_EQ(r_effect, use_effect->InputAt(0));
  EXPECT_EQ(r_success, use_success->InputAt(0));
  EXPECT_EQ(r_exception, use_exception->InputAt(1));
  EXPECT_EQ(0, node->UseCount());
  EXPECT_EQ(1, r_value->UseCount());
  EXPECT_EQ(1, r_effect->UseCount());
  EXPECT_EQ(1, r_success->UseCount());
  EXPECT_EQ(1, r_exception->UseCount());
  EXPECT_THAT(r_value->uses(), ElementsAre(use_value));
  EXPECT_THAT(r_effect->uses(), ElementsAre(use_effect));
  EXPECT_THAT(r_success->uses(), ElementsAre(use_success));
  EXPECT_THAT(r_exception->uses(), ElementsAre(use_exception));
}


TEST_F(NodePropertiesTest, FindProjection) {
  CommonOperatorBuilder common(zone());
  Node* start = NewMockNode(common.Start(1));
  Node* proj0 = NewMockNode(common.Projection(0), start);
  Node* proj1 = NewMockNode(common.Projection(1), start);
  EXPECT_EQ(proj0, NodeProperties::FindProjection(start, 0));
  EXPECT_EQ(proj1, NodeProperties::FindProjection(start, 1));
  EXPECT_THAT(NodeProperties::FindProjection(start, 2), IsNull());
  EXPECT_THAT(NodeProperties::FindProjection(start, 1234567890), IsNull());
}


TEST_F(NodePropertiesTest, CollectControlProjections_Branch) {
  Node* result[2];
  CommonOperatorBuilder common(zone());
  Node* branch = NewMockNode(common.Branch());
  Node* if_false = NewMockNode(common.IfFalse(), branch);
  Node* if_true = NewMockNode(common.IfTrue(), branch);
  NodeProperties::CollectControlProjections(branch, result, arraysize(result));
  EXPECT_EQ(if_true, result[0]);
  EXPECT_EQ(if_false, result[1]);
}


TEST_F(NodePropertiesTest, CollectControlProjections_Call) {
  Node* result[2];
  CommonOperatorBuilder common(zone());
  Node* call = NewMockNode(&kMockCallOperator);
  Node* if_ex = NewMockNode(common.IfException(), call, call);
  Node* if_ok = NewMockNode(common.IfSuccess(), call);
  NodeProperties::CollectControlProjections(call, result, arraysize(result));
  EXPECT_EQ(if_ok, result[0]);
  EXPECT_EQ(if_ex, result[1]);
}


TEST_F(NodePropertiesTest, CollectControlProjections_Switch) {
  Node* result[3];
  CommonOperatorBuilder common(zone());
  Node* sw = NewMockNode(common.Switch(3));
  Node* if_default = NewMockNode(common.IfDefault(), sw);
  Node* if_value1 = NewMockNode(common.IfValue(1), sw);
  Node* if_value2 = NewMockNode(common.IfValue(2), sw);
  NodeProperties::CollectControlProjections(sw, result, arraysize(result));
  EXPECT_THAT(result[0], AnyOf(if_value1, if_value2));
  EXPECT_THAT(result[1], AnyOf(if_value1, if_value2));
  EXPECT_EQ(if_default, result[2]);
}

}  // namespace node_properties_unittest
}  // namespace compiler
}  // namespace internal
}  // namespace v8
