| // 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") |