blob: de7724f2b112e325ab4c282b180b0eeed080b106 [file] [log] [blame]
// Copyright 2018 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 <sstream>
#include <gtest/gtest.h>
#include "tools/fidl/fidlc/src/diagnostics.h"
#include "tools/fidl/fidlc/tests/test_library.h"
namespace fidlc {
namespace {
template <class PrimitiveType>
void CheckConstEq(TestLibrary& library, std::string_view name, PrimitiveType expected_value,
Constant::Kind expected_constant_kind,
ConstantValue::Kind expected_constant_value_kind) {
auto const_decl = library.LookupConstant(name);
ASSERT_NE(const_decl, nullptr);
ASSERT_EQ(expected_constant_kind, const_decl->value->kind);
ASSERT_EQ(expected_constant_value_kind, const_decl->value->Value().kind);
auto& numeric_const_value =
static_cast<const NumericConstantValue<PrimitiveType>&>(const_decl->value->Value());
EXPECT_EQ(expected_value, numeric_const_value.value);
}
TEST(ConstsTests, GoodLiteralsTest) {
TestLibrary library(R"FIDL(
library example;
const C_SIMPLE uint32 = 11259375;
const C_HEX_S uint32 = 0xABCDEF;
const C_HEX_L uint32 = 0XABCDEF;
const C_BINARY_S uint32 = 0b101010111100110111101111;
const C_BINARY_L uint32 = 0B101010111100110111101111;
)FIDL");
ASSERT_COMPILED(library);
auto check_const_eq = [](TestLibrary& library, std::string_view name, uint32_t expected_value) {
CheckConstEq<uint32_t>(library, name, expected_value, Constant::Kind::kLiteral,
ConstantValue::Kind::kUint32);
};
check_const_eq(library, "C_SIMPLE", 11259375);
check_const_eq(library, "C_HEX_S", 11259375);
check_const_eq(library, "C_HEX_L", 11259375);
check_const_eq(library, "C_BINARY_S", 11259375);
check_const_eq(library, "C_BINARY_L", 11259375);
}
TEST(ConstsTests, GoodConstTestBool) {
TestLibrary library(R"FIDL(
library example;
const c bool = false;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadConstTestBoolWithString) {
TestLibrary library;
library.AddFile("bad/fi-0065-a.test.fidl");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "\"foo\"", "string:3", "bool");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestBoolWithNumeric) {
TestLibrary library(R"FIDL(
library example;
const c bool = 6;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "6", "untyped numeric", "bool");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodConstTestInt32) {
TestLibrary library(R"FIDL(
library example;
const c int32 = 42;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodConstTestInt32FromOtherConst) {
TestLibrary library(R"FIDL(
library example;
const b int32 = 42;
const c int32 = b;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadConstTestInt32WithString) {
TestLibrary library(R"FIDL(
library example;
const c int32 = "foo";
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "\"foo\"", "string:3", "int32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestInt32WithBool) {
TestLibrary library(R"FIDL(
library example;
const c int32 = true;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "true", "bool", "int32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodConstTestInt64) {
TestLibrary library;
library.AddFile("good/fi-0066-b.test.fidl");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodConstTestUint64) {
TestLibrary library;
library.AddFile("good/fi-0066-a.test.fidl");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodConstTestUint64FromOtherUint32) {
TestLibrary library(R"FIDL(
library example;
const a uint32 = 42;
const b uint64 = a;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadConstTestUint64Negative) {
TestLibrary library;
library.AddFile("bad/fi-0066.test.fidl");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrConstantOverflowsType, "-42", "uint64");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestUint64Overflow) {
TestLibrary library(R"FIDL(
library example;
const a uint64 = 18446744073709551616;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrConstantOverflowsType, "18446744073709551616", "uint64");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodConstTestFloat32) {
TestLibrary library(R"FIDL(
library example;
const b float32 = 1.61803;
const c float32 = -36.46216;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodConstTestFloat32HighLimit) {
TestLibrary library(R"FIDL(
library example;
const hi float32 = 3.402823e38;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodConstTestFloat32LowLimit) {
TestLibrary library(R"FIDL(
library example;
const lo float32 = -3.40282e38;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadConstTestFloat32HighLimit) {
TestLibrary library(R"FIDL(
library example;
const hi float32 = 3.41e38;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrConstantOverflowsType, "3.41e38", "float32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestFloat32LowLimit) {
TestLibrary library(R"FIDL(
library example;
const b float32 = -3.41e38;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrConstantOverflowsType, "-3.41e38", "float32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodConstTestString) {
TestLibrary library;
library.AddFile("good/fi-0002.test.fidl");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodConstTestStringFromOtherConst) {
TestLibrary library(R"FIDL(
library example;
const c string:4 = "four";
const d string:5 = c;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadConstTestStringWithNumeric) {
TestLibrary library(R"FIDL(
library example;
const c string = 4;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "4", "untyped numeric", "string");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestStringWithBool) {
TestLibrary library(R"FIDL(
library example;
const c string = true;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "true", "bool", "string");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestStringWithStringTooLong) {
TestLibrary library(R"FIDL(
library example;
const c string:4 = "hello";
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "\"hello\"", "string:5", "string:4");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodConstTestUsing) {
TestLibrary library(R"FIDL(
library example;
alias foo = int32;
const c foo = 2;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadConstTestUsingWithInconvertibleValue) {
TestLibrary library(R"FIDL(
library example;
alias foo = int32;
const c foo = "nope";
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "\"nope\"", "string:4", "int32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestNullableString) {
TestLibrary library;
library.AddFile("bad/fi-0059.test.fidl");
library.ExpectFail(ErrInvalidConstantType, "string?");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestArray) {
TestLibrary library(R"FIDL(
library example;
const c array<int32,2> = -1;
)FIDL");
library.ExpectFail(ErrInvalidConstantType, "array<int32, 2>");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestVector) {
TestLibrary library(R"FIDL(
library example;
const c vector<int32>:2 = -1;
)FIDL");
library.ExpectFail(ErrInvalidConstantType, "vector<int32>:2");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestHandleOfThread) {
TestLibrary library(R"FIDL(
library example;
type ObjType = enum : uint32 {
NONE = 0;
THREAD = 2;
};
resource_definition handle : uint32 {
properties {
subtype ObjType;
};
};
const c handle:THREAD = -1;
)FIDL");
library.ExpectFail(ErrInvalidConstantType, "example/handle:thread");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodConstEnumMemberReference) {
TestLibrary library(R"FIDL(
library example;
type MyEnum = strict enum : int32 {
A = 5;
};
const c int32 = MyEnum.A;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodConstBitsMemberReference) {
TestLibrary library(R"FIDL(
library example;
type MyBits = strict bits : uint32 {
A = 0x00000001;
};
const c uint32 = MyBits.A;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodEnumTypedConstEnumMemberReference) {
TestLibrary library(R"FIDL(
library example;
type MyEnum = strict enum : int32 {
A = 5;
};
const c MyEnum = MyEnum.A;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodBitsTypedConstBitsMemberReference) {
TestLibrary library(R"FIDL(
library example;
type MyBits = strict bits : uint32 {
A = 0x00000001;
};
const c MyBits = MyBits.A;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodBitsTypedConstZero) {
TestLibrary library(R"FIDL(
library example;
type MyBits = strict bits : uint32 {
A = 0x00000001;
};
const c MyBits = 0;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadConstDifferentEnumMemberReference) {
TestLibrary library;
library.AddFile("bad/fi-0064.test.fidl");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrMismatchedNameTypeAssignment, "MyEnum", "OtherEnum");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstDifferentBitsMemberReference) {
TestLibrary library(R"FIDL(
library example;
type MyBits = bits : uint32 { VALUE = 0x00000001; };
type OtherBits = bits : uint32 { VALUE = 0x00000004; };
const c MyBits = OtherBits.VALUE;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrMismatchedNameTypeAssignment, "MyBits", "OtherBits");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstAssignPrimitiveToEnum) {
TestLibrary library(R"FIDL(
library example;
type MyEnum = enum : int32 { VALUE = 1; };
const c MyEnum = 5;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "5", "untyped numeric", "example/MyEnum");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstAssignPrimitiveToBits) {
TestLibrary library(R"FIDL(
library example;
type MyBits = bits : uint32 { VALUE = 0x00000001; };
const c MyBits = 5;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "5", "untyped numeric", "example/MyBits");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodMaxBoundTest) {
TestLibrary library(R"FIDL(
library example;
const S string:MAX = "";
type Example = struct {
s string:MAX;
v vector<bool>:MAX;
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodMaxBoundTestConvertToUnbounded) {
TestLibrary library(R"FIDL(
library example;
const A string:MAX = "foo";
const B string = A;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodMaxBoundTestConvertFromUnbounded) {
TestLibrary library(R"FIDL(
library example;
const A string = "foo";
const B string:MAX = A;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadMaxBoundTestAssignToConst) {
TestLibrary library(R"FIDL(
library example;
const FOO uint32 = MAX;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadMaxBoundTestLibraryQualified) {
SharedAmongstLibraries shared;
TestLibrary dependency(&shared, "dependency.fidl", R"FIDL(
library dependency;
type Example = struct {};
)FIDL");
ASSERT_COMPILED(dependency);
TestLibrary library(&shared, "example.fidl", R"FIDL(
library example;
using dependency;
type Example = struct { s string:dependency.MAX; };
)FIDL");
library.ExpectFail(ErrNameNotFound, "MAX", "library 'dependency'");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadParameterizePrimitive) {
TestLibrary library(R"FIDL(
library example;
const u uint8<string> = 0;
)FIDL");
library.ExpectFail(ErrWrongNumberOfLayoutParameters, "uint8", 0, 1);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestAssignTypeSimple) {
TestLibrary library;
library.AddFile("bad/fi-0063.test.fidl");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrExpectedValueButGotType, "MyType");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestAssignTypeName) {
for (auto type_declaration : {
"type Example = struct {};",
"type Example = table {};",
"service Example {};",
"protocol Example {};",
"type Example = bits { A = 1; };",
"type Example = enum { A = 1; };",
"type Example = union { 1: A bool; };",
"alias Example = string;",
}) {
std::ostringstream s;
s << "library example;\n" << type_declaration << "\nconst FOO uint32 = Example;";
auto fidl = s.str();
SCOPED_TRACE(fidl);
TestLibrary library(fidl);
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrExpectedValueButGotType, "Example");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
}
TEST(ConstsTests, BadConstTestAssignBuiltinSimple) {
TestLibrary library;
library.AddFile("bad/fi-0060.test.fidl");
library.ExpectFail(ErrCannotResolveConstantValue);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstTestAssignBuiltinType) {
for (auto builtin : {"bool", "uint32", "box", "vector", "byte"}) {
std::ostringstream ss;
ss << "library example;\n";
ss << "const FOO uint32 = " << builtin << ";\n";
TestLibrary library(ss.str());
// TODO(https://fxbug.dev/42182133): Should have a better error message.
library.ExpectFail(ErrCannotResolveConstantValue);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
}
TEST(ConstsTests, BadConstTestAssignBuiltinNonType) {
for (auto builtin : {"MAX", "HEAD", "optional"}) {
std::ostringstream ss;
ss << "library example;\n";
ss << "const FOO uint32 = " << builtin << ";\n";
TestLibrary library(ss.str());
// TODO(https://fxbug.dev/42182133): Should have a better error message.
library.ExpectFail(ErrCannotResolveConstantValue);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
}
TEST(ConstsTests, BadNameCollision) {
TestLibrary library;
library.AddFile("bad/fi-0034.test.fidl");
library.ExpectFail(ErrNameCollision, Element::Kind::kConst, "COLOR", Element::Kind::kConst,
"bad/fi-0034.test.fidl:6:7");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodFixNameCollisionRename) {
TestLibrary library;
library.AddFile("good/fi-0034-b.test.fidl");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodFixNameCollisionRemove) {
TestLibrary library;
library.AddFile("good/fi-0034-a.test.fidl");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodMultiFileConstReference) {
TestLibrary library;
library.AddSource("first.fidl", R"FIDL(
library example;
type Protein = struct {
amino_acids vector<uint64>:SMALL_SIZE;
};
)FIDL");
library.AddSource("second.fidl", R"FIDL(
library example;
const SMALL_SIZE uint32 = 4;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadUnknownEnumMemberTest) {
TestLibrary library(R"FIDL(
library example;
type EnumType = enum : int32 {
A = 0x00000001;
B = 0x80;
C = 0x2;
};
const dee EnumType = EnumType.D;
)FIDL");
library.ExpectFail(ErrMemberNotFound, "enum 'EnumType'", "D");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadUnknownBitsMemberTest) {
TestLibrary library(R"FIDL(
library example;
type BitsType = bits {
A = 2;
B = 4;
C = 8;
};
const dee BitsType = BitsType.D;
)FIDL");
library.ExpectFail(ErrMemberNotFound, "bits 'BitsType'", "D");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodOrOperatorTest) {
TestLibrary library(R"FIDL(
library example;
type MyBits = strict bits : uint8 {
A = 0x00000001;
B = 0x00000002;
C = 0x00000004;
D = 0x00000008;
};
const bitsValue MyBits = MyBits.A | MyBits.B | MyBits.D;
const Result uint16 = MyBits.A | MyBits.B | MyBits.D;
)FIDL");
ASSERT_COMPILED(library);
CheckConstEq<uint16_t>(library, "Result", 11, Constant::Kind::kBinaryOperator,
ConstantValue::Kind::kUint16);
}
TEST(ConstsTests, BadOrOperatorDifferentTypesTest) {
TestLibrary library;
library.AddFile("bad/fi-0065-b.test.fidl");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "test.bad.fi0065b/TWO_FIFTY_SIX", "uint16",
"uint8");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodOrOperatorDifferentTypesTest) {
TestLibrary library(R"FIDL(
library example;
const one uint8 = 0x0001;
const two_fifty_six uint16 = 0x0100;
const two_fifty_seven uint16 = one | two_fifty_six;
)FIDL");
ASSERT_COMPILED(library);
CheckConstEq<uint16_t>(library, "two_fifty_seven", 257, Constant::Kind::kBinaryOperator,
ConstantValue::Kind::kUint16);
}
TEST(ConstsTests, BadOrOperatorNonPrimitiveTypesTest) {
TestLibrary library;
library.AddFile("bad/fi-0061.test.fidl");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrOrOperatorOnNonPrimitiveValue);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodOrOperatorParenthesesTest) {
TestLibrary library(R"FIDL(
library example;
type MyBits = strict bits : uint8 {
A = 0x00000001;
B = 0x00000002;
C = 0x00000004;
D = 0x00000008;
};
const three MyBits = MyBits.A | MyBits.B;
const seven MyBits = three | MyBits.C;
const fifteen MyBits = (three | seven) | MyBits.D;
const bitsValue MyBits = MyBits.A | ( ( (MyBits.A | MyBits.B) | MyBits.D) | MyBits.C);
)FIDL");
ASSERT_COMPILED(library);
CheckConstEq<uint8_t>(library, "three", 3, Constant::Kind::kBinaryOperator,
ConstantValue::Kind::kUint8);
CheckConstEq<uint8_t>(library, "seven", 7, Constant::Kind::kBinaryOperator,
ConstantValue::Kind::kUint8);
CheckConstEq<uint8_t>(library, "fifteen", 15, Constant::Kind::kBinaryOperator,
ConstantValue::Kind::kUint8);
CheckConstEq<uint8_t>(library, "bitsValue", 15, Constant::Kind::kBinaryOperator,
ConstantValue::Kind::kUint8);
}
TEST(ConstsTests, BadOrOperatorMissingRightParenTest) {
TestLibrary library = TestLibrary(R"FIDL(
library example;
const three uint16 = 3;
const seven uint16 = 7;
const eight uint16 = 8;
const fifteen uint16 = ( three | seven | eight;
)FIDL");
library.ExpectFail(ErrUnexpectedTokenOfKind, Token::KindAndSubkind(Token::Kind::kSemicolon),
Token::KindAndSubkind(Token::Kind::kRightParen));
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadOrOperatorMissingLeftParenTest) {
TestLibrary library = TestLibrary(R"FIDL(
library example;
const three uint16 = 3;
const seven uint16 = 7;
const eight uint16 = 8;
const fifteen uint16 = three | seven | eight );
)FIDL");
library.ExpectFail(ErrExpectedDeclaration, ")");
library.ExpectFail(ErrUnexpectedTokenOfKind, Token::KindAndSubkind(Token::Kind::kRightParen),
Token::KindAndSubkind(Token::Kind::kSemicolon));
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadOrOperatorMisplacedParenTest) {
TestLibrary library = TestLibrary(R"FIDL(
library example;
const three uint16 = 3;
const seven uint16 = 7;
const eight uint16 = 8;
const fifteen uint16 = ( three | seven | ) eight;
)FIDL");
library.ExpectFail(ErrUnexpectedToken);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadIdentifierConstMismatchedTypesTest) {
TestLibrary library(R"FIDL(
library example;
type OneEnum = enum {
A = 1;
};
type AnotherEnum = enum {
B = 1;
};
const a OneEnum = OneEnum.A;
const b AnotherEnum = a;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrMismatchedNameTypeAssignment, "AnotherEnum", "OneEnum");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadEnumBitsConstMismatchedTypesTest) {
TestLibrary library(R"FIDL(
library example;
type OneEnum = enum {
A = 1;
};
type AnotherEnum = enum {
B = 1;
};
const a OneEnum = AnotherEnum.B;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrMismatchedNameTypeAssignment, "OneEnum", "AnotherEnum");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConstReferencesInvalidConst) {
// Test all orderings since this previously crashed only when the invalid
// const (set to 1 instead of a string) was lexicographically smaller.
{
TestLibrary library(R"FIDL(
library example;
const A string = Z;
const Z string = 1;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "1", "untyped numeric", "string");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
{
TestLibrary library(R"FIDL(
library example;
const A string = 1;
const Z string = A;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "1", "untyped numeric", "string");
library.ExpectFail(ErrCannotResolveConstantValue);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
{
TestLibrary library(R"FIDL(
library example;
const Z string = A;
const A string = 1;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "1", "untyped numeric", "string");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
{
TestLibrary library(R"FIDL(
library example;
const Z string = 1;
const A string = Z;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "1", "untyped numeric", "string");
library.ExpectFail(ErrCannotResolveConstantValue);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
}
TEST(ConstsTests, GoodDeclaration) {
TestLibrary library;
library.AddFile("good/fi-0006.test.fidl");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodIntegerConvertWider) {
TestLibrary library(R"FIDL(
library example;
const X uint16 = 23;
const WIDE uint32 = X;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodIntegerConvertNarrower) {
TestLibrary library(R"FIDL(
library example;
const X uint16 = 255;
const NARROW uint8 = X;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodIntegerConvertToSigned) {
TestLibrary library(R"FIDL(
library example;
const X uint16 = 23;
const SIGNED int16 = X;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodIntegerConvertToUnsigned) {
TestLibrary library(R"FIDL(
library example;
const X int16 = 23;
const UNSIGNED uint16 = X;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadIntegerConvertNarrowerOutOfRange) {
TestLibrary library(R"FIDL(
library example;
const X uint16 = 256;
const NARROW uint8 = X;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "example/X", "uint16", "uint8");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadIntegerConvertToSignedOutOfRange) {
TestLibrary library(R"FIDL(
library example;
const X uint16 = 32768; // 2^15
const SIGNED int16 = X;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "example/X", "uint16", "int16");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadIntegerConvertToUnsignedNegative) {
TestLibrary library(R"FIDL(
library example;
const X int16 = -1;
const UNSIGNED uint16 = X;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "example/X", "int16", "uint16");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, GoodConvertFloatWider) {
TestLibrary library(R"FIDL(
library example;
const X float32 = 23;
const WIDE float64 = X;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, GoodConvertFloatNarrower) {
TestLibrary library(R"FIDL(
library example;
const X float64 = 3.4028234663852886e38; // max float32
const NARROW float32 = X;
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ConstsTests, BadConvertFloatNarrowerOutOfRangePositive) {
TestLibrary library(R"FIDL(
library example;
const X float64 = 3.402823466385289e38; // just above max float32
const NARROW float32 = X;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "example/X", "float64", "float32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ConstsTests, BadConvertFloatNarrowerOutOfRangeNegative) {
TestLibrary library(R"FIDL(
library example;
const X float64 = -3.402823466385289e38; // just below min float32
const NARROW float32 = X;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "example/X", "float64", "float32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
// It would be reasonable to allow conversions that don't lose precision (e.g.
// for float64 up to 2^53-1) but for simplicity we don't allow it right now.
TEST(ConstsTests, BadConvertIntegerToFloat) {
TestLibrary library(R"FIDL(
library example;
const X uint16 = 1;
const FLOAT float32 = X;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "example/X", "uint16", "float32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
// It would be reasonable to allow conversions from floats that are exact
// integers, or to truncate, but for simplicity we don't allow it right now.
TEST(ConstsTests, BadConvertFloatToInteger) {
TestLibrary library(R"FIDL(
library example;
const X float32 = 1;
const INTEGER uint16 = X;
)FIDL");
library.ExpectFail(ErrCannotResolveConstantValue);
library.ExpectFail(ErrTypeCannotBeConvertedToType, "example/X", "float32", "uint16");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
} // namespace
} // namespace fidlc