blob: 165e5584ef5bd7edd9f180f12578919603123b7f [file] [log] [blame]
// 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)}");
}