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

// Copymodified_value 2020 The Fuchsia Authors. All modified_values reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <cstdint>
#include <limits>
#include <memory>
#include <vector>

#include "src/developer/shell/interpreter/test/interpreter_test.h"

TEST_F(InterpreterTest, AssignUnknown) {
  constexpr uint64_t kFileId = 1;
  InterpreterTestContext* context = CreateContext();
  shell().CreateExecutionContext(context->id);

  shell::console::AstBuilder builder(kFileId);
  builder.AddAssignment(builder.AddVariable("unknown"), builder.AddStringLiteral("something"));

  shell().AddNodes(context->id, builder.DefsAsVectorView());
  shell().ExecuteExecutionContext(context->id);
  Finish(kExecute);

  ASSERT_EQ(fuchsia_shell::wire::ExecuteResult::kAnalysisError, context->GetResult());
  std::string error_result = context->error_stream.str();
  ASSERT_EQ("node 1:1 Can't infer type for assignment's destination.\n", error_result);
}

TEST_F(InterpreterTest, AssignConstant) {
  constexpr uint64_t kFileId = 1;
  InterpreterTestContext* context = CreateContext();
  shell().CreateExecutionContext(context->id);

  shell::console::AstBuilder builder(kFileId);
  builder.AddVariableDeclaration("hello", builder.TypeString(), builder.AddStringLiteral("Hello"),
                                 true, true);
  builder.AddAssignment(builder.AddVariable("hello"), builder.AddStringLiteral("something"));

  shell().AddNodes(context->id, builder.DefsAsVectorView());
  shell().ExecuteExecutionContext(context->id);
  Finish(kExecute);

  ASSERT_EQ(fuchsia_shell::wire::ExecuteResult::kAnalysisError, context->GetResult());
  std::string error_result = context->error_stream.str();
  ASSERT_EQ("node 1:3 Can't assign constant hello.\n", error_result);
}

TEST_F(InterpreterTest, AssignString) {
  constexpr uint64_t kFileId = 1;
  InterpreterTestContext* context = CreateContext();
  shell().CreateExecutionContext(context->id);

  shell::console::AstBuilder builder(kFileId);
  builder.AddVariableDeclaration("good", builder.TypeString(), builder.AddStringLiteral("not good"),
                                 false, true);
  builder.AddEmitResult(builder.AddVariable("good"));
  builder.AddAssignment(builder.AddVariable("good"), builder.AddStringLiteral("now good"));
  builder.AddEmitResult(builder.AddVariable("good"));

  shell().AddNodes(context->id, builder.DefsAsVectorView());
  shell().ExecuteExecutionContext(context->id);
  Finish(kExecute);

  ASSERT_EQ(fuchsia_shell::wire::ExecuteResult::kOk, context->GetResult());

  CHECK_RESULT(0, "\"not good\"");
  CHECK_RESULT(1, "\"now good\"");
}

#define ASSIGN_TEST(name, type, initial_value, modified_value)                            \
  TEST_F(InterpreterTest, name) {                                                         \
    constexpr uint64_t kFileId = 1;                                                       \
    InterpreterTestContext* context = CreateContext();                                    \
    shell().CreateExecutionContext(context->id);                                          \
                                                                                          \
    shell::console::AstBuilder builder(kFileId);                                          \
    builder.AddVariableDeclaration("x", type,                                             \
                                   (initial_value < 0)                                    \
                                       ? builder.AddIntegerLiteral(-initial_value, true)  \
                                       : builder.AddIntegerLiteral(initial_value, false), \
                                   false, true);                                          \
    builder.AddEmitResult(builder.AddVariable("x"));                                      \
    builder.AddAssignment(builder.AddVariable("x"),                                       \
                          (modified_value < 0)                                            \
                              ? builder.AddIntegerLiteral(-modified_value, true)          \
                              : builder.AddIntegerLiteral(modified_value, false));        \
    builder.AddEmitResult(builder.AddVariable("x"));                                      \
                                                                                          \
    shell().AddNodes(context->id, builder.DefsAsVectorView());                            \
    shell().ExecuteExecutionContext(context->id);                                         \
    Finish(kExecute);                                                                     \
                                                                                          \
    ASSERT_EQ(fuchsia_shell::wire::ExecuteResult::kOk, context->GetResult());             \
                                                                                          \
    CHECK_RESULT(0, #initial_value);                                                      \
    CHECK_RESULT(1, #modified_value);                                                     \
  }

ASSIGN_TEST(AssignInt8, builder.TypeInt8(), 10, -30);
ASSIGN_TEST(AssignUint8, builder.TypeUint8(), 10, 30);

ASSIGN_TEST(AssignInt16, builder.TypeInt16(), 1000, -3000);
ASSIGN_TEST(AssignUint16, builder.TypeUint16(), 1000, 3000);

ASSIGN_TEST(AssignInt32, builder.TypeInt32(), 100000, -300000);
ASSIGN_TEST(AssignUint32, builder.TypeUint32(), 100000, 300000);

ASSIGN_TEST(AssignInt64, builder.TypeInt64(), 10000000000, -30000000000);
ASSIGN_TEST(AssignUint64, builder.TypeUint64(), 10000000000, 30000000000);

TEST_F(InterpreterTest, AssignObject) {
  constexpr uint64_t kFileId = 1;
  InterpreterTestContext* context = CreateContext();
  ASSERT_CALL_OK(shell().CreateExecutionContext(context->id));
  shell::console::AstBuilder builder(kFileId);

  {
    std::vector<std::string> names{"alpha", "beta"};
    std::vector<shell::console::AstBuilder::NodeId> values{builder.AddIntegerLiteral(10, false),
                                                           builder.AddIntegerLiteral(20, false)};
    std::vector<fuchsia_shell::wire::ShellType> types;
    types.emplace_back(builder.TypeUint64());
    types.emplace_back(builder.TypeUint64());
    shell::console::AstBuilder::NodePair object_pair =
        AddObject(builder, names, values, std::move(types));
    builder.AddVariableDeclaration("obj", builder.TypeObject(object_pair.schema_node),
                                   object_pair.value_node, /*is_const=*/false, /*is_root=*/true);
    builder.AddEmitResult(builder.AddVariable("obj"));
  }

  {
    std::vector<std::string> names{"alpha", "beta"};
    std::vector<shell::console::AstBuilder::NodeId> values{builder.AddIntegerLiteral(4, false),
                                                           builder.AddIntegerLiteral(5, false)};
    std::vector<fuchsia_shell::wire::ShellType> types;
    types.emplace_back(builder.TypeUint64());
    types.emplace_back(builder.TypeUint64());
    shell::console::AstBuilder::NodePair object_pair =
        AddObject(builder, names, values, std::move(types));
    builder.AddAssignment(builder.AddVariable("obj"), object_pair.value_node);
    builder.AddEmitResult(builder.AddVariable("obj"));
  }

  ASSERT_CALL_OK(shell().AddNodes(context->id, builder.DefsAsVectorView()));
  ASSERT_CALL_OK(shell().ExecuteExecutionContext(context->id));
  Finish(kExecute);

  ASSERT_EQ(fuchsia_shell::wire::ExecuteResult::kOk, context->GetResult());

  CHECK_RESULT(0, "{alpha: uint64(10), beta: uint64(20)}");
  CHECK_RESULT(1, "{alpha: uint64(4), beta: uint64(5)}");
}
