blob: 0e226a8351e17a249eaa6c60768e4bb04ea085fb [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.
#include <cstdint>
#include <limits>
#include <memory>
#include <vector>
#include "src/developer/shell/common/ast_builder.h"
#include "src/developer/shell/interpreter/test/interpreter_test.h"
// - String ----------------------------------------------------------------------------------------
TEST_F(InterpreterTest, StringAdditionOk) {
constexpr uint64_t kFileId = 1;
InterpreterTestContext* context = CreateContext();
ASSERT_CALL_OK(shell()->CreateExecutionContext(context->id));
shell::console::AstBuilder builder(kFileId);
builder.AddVariableDeclaration("marx", builder.TypeString(), builder.AddStringLiteral("Marx"),
false, true);
// Checks s1 + (s2 + s3).
builder.AddVariableDeclaration(
"groucho1", builder.TypeString(),
builder.AddAddition(
/*with_exceptions=*/true, builder.AddStringLiteral("A "),
builder.AddAddition(/*with_exceptions=*/true, builder.AddVariable("marx"),
builder.AddStringLiteral(" brother"))),
false, true);
// Checks (s1 + s2) + s3.
builder.AddVariableDeclaration(
"groucho2", builder.TypeString(),
builder.AddAddition(
/*with_exceptions=*/true,
builder.AddAddition(/*with_exceptions=*/true, builder.AddStringLiteral("A "),
builder.AddVariable("marx")),
builder.AddStringLiteral(" brother")),
false, true);
builder.AddEmitResult(builder.AddVariable("groucho1"));
builder.AddEmitResult(builder.AddVariable("groucho2"));
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, "\"A Marx brother\"");
CHECK_RESULT(1, "\"A Marx brother\"");
}
TEST_F(InterpreterTest, StringAdditionEmpty) {
constexpr uint64_t kFileId = 1;
InterpreterTestContext* context = CreateContext();
ASSERT_CALL_OK(shell()->CreateExecutionContext(context->id));
shell::console::AstBuilder builder(kFileId);
builder.AddVariableDeclaration("foo", builder.TypeString(), builder.AddStringLiteral("foo"),
false, true);
builder.AddVariableDeclaration(
"foo1", builder.TypeString(),
builder.AddAddition(/*with_exceptions=*/true, builder.AddVariable("foo"),
builder.AddStringLiteral("")),
false, true);
builder.AddVariableDeclaration(
"foo2", builder.TypeString(),
builder.AddAddition(/*with_exceptions=*/true, builder.AddStringLiteral(""),
builder.AddVariable("foo")),
false, true);
builder.AddEmitResult(builder.AddVariable("foo1"));
builder.AddEmitResult(builder.AddVariable("foo2"));
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, "\"foo\"");
CHECK_RESULT(1, "\"foo\"");
}
// - Helpers ---------------------------------------------------------------------------------------
#define ExecuteAddition(type, with_exceptions, left, right) \
constexpr uint64_t kFileId = 1; \
InterpreterTestContext* context = CreateContext(); \
ASSERT_CALL_OK(shell()->CreateExecutionContext(context->id)); \
\
shell::console::AstBuilder builder(kFileId); \
builder.AddVariableDeclaration("x", type, \
(left < 0) ? builder.AddIntegerLiteral(-left, true) \
: builder.AddIntegerLiteral(left, false), \
false, true); \
builder.AddVariableDeclaration( \
"y", type, \
builder.AddAddition(with_exceptions, builder.AddVariable("x"), \
(right < 0) ? builder.AddIntegerLiteral(-right, true) \
: builder.AddIntegerLiteral(right, false)), \
false, true); \
\
builder.AddEmitResult(builder.AddVariable("y")); \
\
ASSERT_CALL_OK(shell()->AddNodes(context->id, builder.DefsAsVectorView())); \
ASSERT_CALL_OK(shell()->ExecuteExecutionContext(context->id)); \
Finish(kExecute);
#define DoAdditionTest(name, type, with_exceptions, left, right, result) \
TEST_F(InterpreterTest, name) { \
ExecuteAddition(builder.type, with_exceptions, left, right); \
\
ASSERT_EQ(fuchsia_shell::wire::ExecuteResult::kOk, context->GetResult()); \
\
std::string string_result = std::to_string(result); \
CHECK_RESULT(0, string_result); \
}
#define DoAdditionTestException(name, type, left, right, errors) \
TEST_F(InterpreterTest, name) { \
ExecuteAddition(builder.type, /*with_exceptions=*/true, left, right); \
\
ASSERT_EQ(fuchsia_shell::wire::ExecuteResult::kExecutionError, context->result); \
\
std::string error_result = context->error_stream.str(); \
ASSERT_EQ(errors, error_result); \
}
#define AdditionTest(name, type, left, right, result) \
DoAdditionTest(name, type, /*with_exceptions=*/true, left, right, result)
#define AdditionTestWithException(name, type, left, right, result, errors) \
DoAdditionTest(name, type, /*with_exceptions=*/false, left, right, result) \
DoAdditionTestException(name##Exception, type, left, right, errors)
// - Int8 ------------------------------------------------------------------------------------------
AdditionTest(Int8AdditionOk1, TypeInt8(), 1, 3, 4)
AdditionTest(Int8AdditionOk2, TypeInt8(), -1, 3, 2)
AdditionTest(Int8AdditionOk3, TypeInt8(), 1, -3, -2)
AdditionTestWithException(Int8AdditionOverflowException, TypeInt8(), 127, 1, -128,
"Int8 overflow when adding 127 and 1.\n")
AdditionTestWithException(Int8AdditionUnderflow, TypeInt8(), -128, -1, 127,
"Int8 underflow when adding -128 and -1.\n")
// - Uint8 -----------------------------------------------------------------------------------------
AdditionTest(Uint8AdditionOk, TypeUint8(), 1, 3, 4)
AdditionTestWithException(Uint8AdditionOverflow, TypeUint8(), 250, 6, 0,
"Uint8 overflow when adding 250 and 6.\n")
// - Int16 -----------------------------------------------------------------------------------------
AdditionTest(Int16AdditionOk1, TypeInt16(), 1000, 3000, 4000)
AdditionTest(Int16AdditionOk2, TypeInt16(), -1000, 3000, 2000)
AdditionTest(Int16AdditionOk3, TypeInt16(), 1000, -3000, -2000)
AdditionTestWithException(Int16AdditionOverflow, TypeInt16(), 32000, 768, -32768,
"Int16 overflow when adding 32000 and 768.\n")
AdditionTestWithException(Int16AdditionUnderflow, TypeInt16(), -32000, -769, 32767,
"Int16 underflow when adding -32000 and -769.\n")
// - Uint16 ----------------------------------------------------------------------------------------
AdditionTest(Uint16AdditionOk, TypeUint16(), 1000, 3000, 4000)
AdditionTestWithException(Uint16AdditionOverflow, TypeUint16(), 65000, 536, 0,
"Uint16 overflow when adding 65000 and 536.\n")
// - Int32 -----------------------------------------------------------------------------------------
AdditionTest(Int32AdditionOk1, TypeInt32(), 100000, 300000, 400000)
AdditionTest(Int32AdditionOk2, TypeInt32(), -100000, 300000, 200000)
AdditionTest(Int32AdditionOk3, TypeInt32(), 100000, -300000, -200000)
AdditionTestWithException(Int32AdditionOverflow, TypeInt32(), 2147480000, 3648, -2147483648,
"Int32 overflow when adding 2147480000 and 3648.\n")
AdditionTestWithException(Int32AdditionUnderflow, TypeInt32(), -2147480000, -3649, 2147483647,
"Int32 underflow when adding -2147480000 and -3649.\n")
// - Uint32 ----------------------------------------------------------------------------------------
AdditionTest(Uint32AdditionOk, TypeUint32(), 1000000, 3000000, 4000000)
AdditionTestWithException(Uint32AdditionOverflow, TypeUint32(), 4294960000, 7296, 0,
"Uint32 overflow when adding 4294960000 and 7296.\n")
// - Int64 -----------------------------------------------------------------------------------------
AdditionTest(Int64AdditionOk1, TypeInt64(), 100000000000L, 300000000000L, 400000000000L)
AdditionTest(Int64AdditionOk2, TypeInt64(), -100000000000L, 300000000000L, 200000000000L)
AdditionTest(Int64AdditionOk3, TypeInt64(), 100000000000L, -300000000000L, -200000000000L)
AdditionTestWithException(Int64AdditionOverflow, TypeInt64(), 9223372036854770000LL, 5808,
std::numeric_limits<int64_t>::min(),
"Int64 overflow when adding 9223372036854770000 and 5808.\n")
AdditionTestWithException(Int64AdditionUnderflow, TypeInt64(), -9223372036854770000LL, -5809,
std::numeric_limits<int64_t>::max(),
"Int64 underflow when adding -9223372036854770000 and -5809.\n")
// - Uint64 ----------------------------------------------------------------------------------------
AdditionTest(Uint64AdditionOk, TypeUint64(), 100000000000L, 300000000000L, 400000000000L)
AdditionTestWithException(Uint64AdditionOverflow, TypeUint64(), 18446744073709550000ULL, 1616, 0,
"Uint64 overflow when adding 18446744073709550000 and 1616.\n")