blob: d81f57fa3531199367bb3352ce841585af3fc006 [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 <gtest/gtest.h>
#include "tools/fidl/fidlc/src/diagnostics.h"
#include "tools/fidl/fidlc/src/flat_ast.h"
#include "tools/fidl/fidlc/src/types.h"
#include "tools/fidl/fidlc/tests/test_library.h"
namespace fidlc {
namespace {
TEST(ProtocolTests, GoodValidEmptyProtocol) {
TestLibrary library(R"FIDL(
library example;
protocol Empty {};
)FIDL");
ASSERT_COMPILED(library);
auto protocol = library.LookupProtocol("Empty");
ASSERT_NE(protocol, nullptr);
EXPECT_EQ(protocol->methods.size(), 0u);
EXPECT_EQ(protocol->openness, Openness::kOpen);
EXPECT_EQ(protocol->all_methods.size(), 0u);
}
TEST(ProtocolTests, GoodValidEmptyOpenProtocol) {
TestLibrary library(R"FIDL(
library example;
open protocol Empty {};
)FIDL");
ASSERT_COMPILED(library);
auto protocol = library.LookupProtocol("Empty");
ASSERT_NE(protocol, nullptr);
EXPECT_EQ(protocol->methods.size(), 0u);
EXPECT_EQ(protocol->openness, Openness::kOpen);
EXPECT_EQ(protocol->all_methods.size(), 0u);
}
TEST(ProtocolTests, GoodValidEmptyAjarProtocol) {
TestLibrary library(R"FIDL(
library example;
ajar protocol Empty {};
)FIDL");
ASSERT_COMPILED(library);
auto protocol = library.LookupProtocol("Empty");
ASSERT_NE(protocol, nullptr);
EXPECT_EQ(protocol->methods.size(), 0u);
EXPECT_EQ(protocol->openness, Openness::kAjar);
EXPECT_EQ(protocol->all_methods.size(), 0u);
}
TEST(ProtocolTests, GoodValidEmptyClosedProtocol) {
TestLibrary library(R"FIDL(
library example;
closed protocol Empty {};
)FIDL");
ASSERT_COMPILED(library);
auto protocol = library.LookupProtocol("Empty");
ASSERT_NE(protocol, nullptr);
EXPECT_EQ(protocol->methods.size(), 0u);
EXPECT_EQ(protocol->openness, Openness::kClosed);
EXPECT_EQ(protocol->all_methods.size(), 0u);
}
TEST(ProtocolTests, BadEmptyStrictProtocol) {
TestLibrary library(R"FIDL(
library example;
strict protocol Empty {};
)FIDL");
library.ExpectFail(ErrExpectedDeclaration, "strict");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadEmptyFlexibleProtocol) {
TestLibrary library(R"FIDL(
library example;
flexible protocol Empty {};
)FIDL");
library.ExpectFail(ErrExpectedDeclaration, "flexible");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadOpenMissingProtocolToken) {
TestLibrary library(R"FIDL(
library example;
open Empty {};
)FIDL");
library.ExpectFail(ErrUnexpectedIdentifier, Token::KindAndSubkind(Token::Kind::kIdentifier),
Token::KindAndSubkind(Token::Subkind::kProtocol));
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadAjarMissingProtocolToken) {
TestLibrary library(R"FIDL(
library example;
ajar Empty {};
)FIDL");
library.ExpectFail(ErrUnexpectedIdentifier, Token::KindAndSubkind(Token::Kind::kIdentifier),
Token::KindAndSubkind(Token::Subkind::kProtocol));
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadClosedMissingProtocolToken) {
TestLibrary library(R"FIDL(
library example;
closed Empty {};
)FIDL");
library.ExpectFail(ErrUnexpectedIdentifier, Token::KindAndSubkind(Token::Kind::kIdentifier),
Token::KindAndSubkind(Token::Subkind::kProtocol));
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadEmptyProtocolMember) {
TestLibrary library(R"FIDL(
library example;
protocol Example {
;
};
)FIDL");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, GoodValidProtocolComposition) {
TestLibrary library(R"FIDL(
library example;
protocol A {
MethodA();
};
protocol B {
compose A;
MethodB();
};
protocol C {
compose A;
MethodC();
};
protocol D {
compose B;
compose C;
MethodD();
};
)FIDL");
ASSERT_COMPILED(library);
auto protocol_a = library.LookupProtocol("A");
ASSERT_NE(protocol_a, nullptr);
EXPECT_EQ(protocol_a->methods.size(), 1u);
EXPECT_EQ(protocol_a->all_methods.size(), 1u);
auto protocol_b = library.LookupProtocol("B");
ASSERT_NE(protocol_b, nullptr);
EXPECT_EQ(protocol_b->methods.size(), 1u);
EXPECT_EQ(protocol_b->all_methods.size(), 2u);
auto protocol_c = library.LookupProtocol("C");
ASSERT_NE(protocol_c, nullptr);
EXPECT_EQ(protocol_c->methods.size(), 1u);
EXPECT_EQ(protocol_c->all_methods.size(), 2u);
auto protocol_d = library.LookupProtocol("D");
ASSERT_NE(protocol_d, nullptr);
EXPECT_EQ(protocol_d->methods.size(), 1u);
EXPECT_EQ(protocol_d->all_methods.size(), 4u);
}
TEST(ProtocolTests, GoodValidOpenClosedProtocolComposition) {
TestLibrary library(R"FIDL(
library example;
closed protocol Closed {};
ajar protocol Ajar {};
open protocol Open {};
closed protocol ComposeInClosed {
compose Closed;
};
ajar protocol ComposeInAjar {
compose Closed;
compose Ajar;
};
open protocol ComposeInOpen {
compose Closed;
compose Ajar;
compose Open;
};
)FIDL");
ASSERT_COMPILED(library);
auto compose_in_closed = library.LookupProtocol("ComposeInClosed");
ASSERT_NE(compose_in_closed, nullptr);
EXPECT_EQ(compose_in_closed->composed_protocols.size(), 1u);
auto compose_in_ajar = library.LookupProtocol("ComposeInAjar");
ASSERT_NE(compose_in_ajar, nullptr);
EXPECT_EQ(compose_in_ajar->composed_protocols.size(), 2u);
auto compose_in_open = library.LookupProtocol("ComposeInOpen");
ASSERT_NE(compose_in_open, nullptr);
EXPECT_EQ(compose_in_open->composed_protocols.size(), 3u);
}
TEST(ProtocolTests, BadInvalidComposeOpenInClosed) {
TestLibrary library(R"FIDL(
library example;
open protocol Composed {};
closed protocol Composing {
compose Composed;
};
)FIDL");
library.ExpectFail(ErrComposedProtocolTooOpen, Openness::kClosed, "Composing", Openness::kOpen,
"Composed");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadInvalidComposeAjarInClosed) {
TestLibrary library(R"FIDL(
library example;
ajar protocol Composed {};
closed protocol Composing {
compose Composed;
};
)FIDL");
library.ExpectFail(ErrComposedProtocolTooOpen, Openness::kClosed, "Composing", Openness::kAjar,
"Composed");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadInvalidComposeOpenInAjar) {
TestLibrary library;
library.AddFile("bad/fi-0114.test.fidl");
library.ExpectFail(ErrComposedProtocolTooOpen, Openness::kAjar, "Composing", Openness::kOpen,
"Composed");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadModifierStrictOnCompose) {
TestLibrary library(R"FIDL(
library example;
protocol A {};
protocol B {
strict compose A;
};
)FIDL");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadModifierFlexibleOnCompose) {
TestLibrary library(R"FIDL(
library example;
protocol A {};
protocol B {
flexible compose A;
};
)FIDL");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadModifierStrictOnInvalidMember) {
TestLibrary library(R"FIDL(
library example;
protocol Example {
strict;
};
)FIDL");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadModifierFlexibleOnInvalidMember) {
TestLibrary library(R"FIDL(
library example;
protocol Example {
flexible;
};
)FIDL");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadColonNotSupported) {
TestLibrary library(R"FIDL(
library example;
protocol Parent {};
protocol Child : Parent {};
)FIDL");
library.ExpectFail(ErrUnexpectedTokenOfKind, Token::KindAndSubkind(Token::Kind::kColon),
Token::KindAndSubkind(Token::Kind::kLeftCurly));
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDocCommentOutsideAttributelist) {
TestLibrary library(R"FIDL(
library example;
protocol WellDocumented {
Method();
/// Misplaced doc comment
};
)FIDL");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, GoodAttachAttributesToCompose) {
TestLibrary library(R"FIDL(
library example;
protocol ParentA {
ParentMethodA();
};
protocol ParentB {
ParentMethodB();
};
protocol Child {
@this_is_allowed
compose ParentA;
/// This is also allowed.
compose ParentB;
ChildMethod();
};
)FIDL");
ASSERT_COMPILED(library);
auto child_protocol = library.LookupProtocol("Child");
ASSERT_NE(child_protocol, nullptr);
EXPECT_EQ(child_protocol->methods.size(), 1u);
EXPECT_EQ(child_protocol->all_methods.size(), 3u);
ASSERT_EQ(child_protocol->composed_protocols.size(), 2u);
EXPECT_EQ(child_protocol->composed_protocols.front().attributes->attributes.size(), 1u);
EXPECT_EQ(child_protocol->composed_protocols.front().attributes->attributes.front()->name.data(),
"this_is_allowed");
EXPECT_EQ(child_protocol->composed_protocols.back().attributes->attributes.size(), 1u);
EXPECT_EQ(child_protocol->composed_protocols.back().attributes->attributes.front()->name.data(),
"doc");
EXPECT_EQ(child_protocol->composed_protocols.back().attributes->attributes.front()->span.data(),
"/// This is also allowed.");
ASSERT_EQ(child_protocol->composed_protocols.back().attributes->attributes.front()->args.size(),
1u);
EXPECT_TRUE(child_protocol->composed_protocols.back()
.attributes->attributes.front()
->args.front()
->value->IsResolved());
}
TEST(ProtocolTests, BadCannotComposeYourself) {
TestLibrary library(R"FIDL(
library example;
protocol Narcisse {
compose Narcisse;
};
)FIDL");
library.ExpectFail(ErrIncludeCycle, "protocol 'Narcisse' -> protocol 'Narcisse'");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadCannotMutuallyCompose) {
TestLibrary library;
library.AddFile("bad/fi-0057-b.test.fidl");
library.ExpectFail(ErrIncludeCycle, "protocol 'Yang' -> protocol 'Yin' -> protocol 'Yang'");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadCannotComposeSameProtocolTwice) {
TestLibrary library(R"FIDL(
library example;
protocol Parent {
Method();
};
protocol Child {
compose Parent;
compose Parent;
};
)FIDL");
library.ExpectFail(ErrNameCollision, Element::Kind::kProtocolCompose, "Parent",
Element::Kind::kProtocolCompose, "example.fidl:9:13");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadCannotComposeMissingProtocol) {
TestLibrary library(R"FIDL(
library example;
protocol Child {
compose MissingParent;
};
)FIDL");
library.ExpectFail(ErrNameNotFound, "MissingParent", "library 'example'");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadCannotComposeNonProtocol) {
TestLibrary library;
library.AddFile("bad/fi-0073.test.fidl");
library.ExpectFail(ErrComposingNonProtocol);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadCannotUseOrdinalsInProtocolDeclaration) {
TestLibrary library(R"FIDL(
library example;
protocol NoMoreOrdinals {
42: NiceTry();
};
)FIDL");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadEmptyNamedItem) {
TestLibrary library;
library.AddFile("bad/fi-0020.noformat.test.fidl");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadNoOtherPragmaThanCompose) {
TestLibrary library(R"FIDL(
library example;
protocol Wrong {
not_compose Something;
};
)FIDL");
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDuplicateMethodNames) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod();
MyMethod();
};
)FIDL");
library.ExpectFail(ErrNameCollision, Element::Kind::kProtocolMethod, "MyMethod",
Element::Kind::kProtocolMethod, "example.fidl:5:5");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDuplicateMethodNamesFromImmediateComposition) {
TestLibrary library(R"FIDL(
library example;
protocol MyChildProtocol {
MyMethod();
};
protocol MyProtocol {
compose MyChildProtocol;
MyMethod();
};
)FIDL");
library.ExpectFail(ErrNameCollision, Element::Kind::kProtocolMethod, "MyMethod",
Element::Kind::kProtocolMethod, "example.fidl:5:5");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDuplicateMethodNamesFromMultipleComposition) {
TestLibrary library(R"FIDL(
library example;
protocol A {
Method();
};
protocol B {
Method();
};
protocol C {
compose A;
compose B;
};
)FIDL");
library.ExpectFail(ErrNameCollision, Element::Kind::kProtocolMethod, "Method",
Element::Kind::kProtocolMethod, "example.fidl:5:5");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDuplicateMethodNamesFromNestedComposition) {
TestLibrary library(R"FIDL(
library example;
protocol A {
MethodA();
};
protocol B {
compose A;
MethodB();
};
protocol C {
compose A;
MethodC();
};
protocol D {
compose B;
compose C;
MethodD();
MethodA();
};
)FIDL");
library.ExpectFail(ErrNameCollision, Element::Kind::kProtocolMethod, "MethodA",
Element::Kind::kProtocolMethod, "example.fidl:5:5");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadComposedProtocolsHaveClashingOrdinals) {
TestLibrary library(R"FIDL(
library methodhasher;
protocol SpecialComposed {
ClashOne();
};
protocol Special {
compose SpecialComposed;
ClashTwo();
};
)FIDL");
library.method_hasher() = [](std::string_view selector) -> uint64_t { return 42; };
library.ExpectFail(ErrDuplicateMethodOrdinal, "example.fidl:5:4");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadRequestMustBeProtocol) {
TestLibrary library;
library.AddFile("bad/fi-0157.test.fidl");
library.ExpectFail(ErrMustBeAProtocol, "server_end");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadRequestMustBeProtocolWithOptional) {
TestLibrary library(R"FIDL(
library example;
type MyStruct = struct {};
alias ServerEnd = server_end:<MyStruct, optional>;
)FIDL");
library.ExpectFail(ErrMustBeAProtocol, "server_end");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadRequestMustBeParameterized) {
TestLibrary library;
library.AddFile("bad/fi-0168.test.fidl");
library.ExpectFail(ErrProtocolConstraintRequired, "server_end");
ASSERT_COMPILER_DIAGNOSTICS(library);
EXPECT_EQ(library.errors()[0]->span.data(), "server_end");
}
TEST(ProtocolTests, BadRequestMustContainProtocol) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod(resource struct { server server_end; });
};
)FIDL");
library.ExpectFail(ErrProtocolConstraintRequired, "server_end");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadRequestCannotHaveSize) {
TestLibrary library(R"FIDL(
library example;
protocol P {};
type S = struct {
p server_end:<P,0>;
};
)FIDL");
library.ExpectFail(ErrUnexpectedConstraint, "server_end");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDuplicateParameterName) {
TestLibrary library(R"FIDL(
library example;
protocol P {
MethodWithDuplicateParams(struct {foo uint8; foo uint8; });
};
)FIDL");
library.ExpectFail(ErrNameCollision, Element::Kind::kStructMember, "foo",
Element::Kind::kStructMember, "example.fidl:5:37");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadParameterizedTypedChannel) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {};
type Foo = resource struct {
foo client_end<MyProtocol>;
};
)FIDL");
library.ExpectFail(ErrWrongNumberOfLayoutParameters, "client_end", 0, 1);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadTooManyConstraintsTypedChannel) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {};
type Foo = resource struct {
foo client_end:<MyProtocol, optional, 1, 2>;
};
)FIDL");
library.ExpectFail(ErrTooManyConstraints, "client_end", 2, 4);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, GoodTypedChannels) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {};
type Foo = resource struct {
a client_end:MyProtocol;
b client_end:<MyProtocol, optional>;
c server_end:MyProtocol;
d server_end:<MyProtocol, optional>;
};
)FIDL");
ASSERT_COMPILED(library);
auto container = library.LookupStruct("Foo");
ASSERT_NE(container, nullptr);
ASSERT_EQ(container->members.size(), 4u);
size_t i = 0;
auto a_type_base = container->members[i++].type_ctor->type;
ASSERT_EQ(a_type_base->kind, Type::Kind::kTransportSide);
const auto* a_type = static_cast<const TransportSideType*>(a_type_base);
EXPECT_EQ(a_type->end, TransportSide::kClient);
EXPECT_EQ(a_type->nullability, Nullability::kNonnullable);
auto b_type_base = container->members[i++].type_ctor->type;
ASSERT_EQ(b_type_base->kind, Type::Kind::kTransportSide);
const auto* b_type = static_cast<const TransportSideType*>(b_type_base);
EXPECT_EQ(b_type->end, TransportSide::kClient);
EXPECT_EQ(b_type->nullability, Nullability::kNullable);
auto c_type_base = container->members[i++].type_ctor->type;
ASSERT_EQ(c_type_base->kind, Type::Kind::kTransportSide);
const auto* c_type = static_cast<const TransportSideType*>(c_type_base);
EXPECT_EQ(c_type->end, TransportSide::kServer);
EXPECT_EQ(c_type->nullability, Nullability::kNonnullable);
auto d_type_base = container->members[i++].type_ctor->type;
ASSERT_EQ(d_type_base->kind, Type::Kind::kTransportSide);
const auto* d_type = static_cast<const TransportSideType*>(d_type_base);
EXPECT_EQ(d_type->end, TransportSide::kServer);
EXPECT_EQ(d_type->nullability, Nullability::kNullable);
}
TEST(ProtocolTests, GoodPartialTypedChannelConstraints) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {};
alias ClientEnd = client_end:MyProtocol;
alias ServerEnd = server_end:MyProtocol;
type Foo = resource struct {
a ClientEnd;
b ClientEnd:optional;
c ServerEnd;
d ServerEnd:optional;
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, BadMethodStructLayoutDefaultMember) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod(struct {
@allow_deprecated_struct_defaults
foo uint8 = 1;
});
};
)FIDL");
library.ExpectFail(ErrPayloadStructHasDefaultMembers);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadMethodEmptyPayloadStruct) {
TestLibrary library;
library.AddFile("bad/fi-0077-a.test.fidl");
library.ExpectFail(ErrEmptyPayloadStructs);
library.ExpectFail(ErrEmptyPayloadStructs);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, GoodMethodAbsentPayloadStruct) {
TestLibrary library;
library.AddFile("good/fi-0077-a.test.fidl");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, BadEventEmptyPayloadStruct) {
TestLibrary library;
library.AddFile("bad/fi-0077-b.test.fidl");
library.ExpectFail(ErrEmptyPayloadStructs);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, GoodEventAbsentPayloadStruct) {
TestLibrary library;
library.AddFile("good/fi-0077-b.test.fidl");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, BadMethodEnumLayout) {
TestLibrary library;
library.AddFile("bad/fi-0074.test.fidl");
library.ExpectFail(ErrInvalidMethodPayloadLayoutClass, Decl::Kind::kEnum);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, GoodMethodAbsentResponseWithError) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod() -> () error uint32;
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, BadMethodEmptyStructResponseWithError) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod() -> (struct {}) error uint32;
};
)FIDL");
library.ExpectFail(ErrEmptyPayloadStructs);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, GoodMethodNamedTypeRequest) {
TestLibrary library(R"FIDL(
library example;
type MyStruct = struct{
a bool;
};
protocol MyProtocol {
MyMethodOneWay(MyStruct);
MyMethodTwoWay(MyStruct) -> ();
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, GoodMethodNamedTypeResponse) {
TestLibrary library(R"FIDL(
library example;
type MyStruct = struct{
a bool;
};
protocol MyProtocol {
MyMethod() -> (MyStruct);
-> OnMyEvent(MyStruct);
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, GoodMethodNamedTypeResultPayload) {
TestLibrary library(R"FIDL(
library example;
type MyStruct = struct{
a bool;
};
protocol MyProtocol {
MyMethod() -> (MyStruct) error uint32;
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, GoodMethodNamedAlias) {
TestLibrary library(R"FIDL(
library example;
type MyStruct = struct {
a bool;
};
alias MyStructAlias = MyStruct;
alias MyAliasAlias = MyStructAlias;
protocol MyProtocol {
MyMethod(MyStructAlias) -> (MyAliasAlias);
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, BadMethodNamedEmptyPayloadStruct) {
TestLibrary library(R"FIDL(
library example;
type MyStruct = struct{};
protocol MyProtocol {
MyMethod(MyStruct) -> (MyStruct);
};
)FIDL");
library.ExpectFail(ErrEmptyPayloadStructs);
library.ExpectFail(ErrEmptyPayloadStructs);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadMethodNamedDefaultValueStruct) {
TestLibrary library;
library.AddFile("bad/fi-0084.test.fidl");
library.ExpectFail(ErrPayloadStructHasDefaultMembers);
library.ExpectFail(ErrPayloadStructHasDefaultMembers);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadMethodNamedInvalidHandle) {
TestLibrary library(R"FIDL(
library example;
type ObjType = strict enum : uint32 {
NONE = 0;
VMO = 3;
};
type Rights = strict bits : uint32 {
TRANSFER = 1;
};
resource_definition Handle : uint32 {
properties {
subtype ObjType;
rights Rights;
};
};
protocol MyProtocol {
MyMethod(Handle);
};
)FIDL");
library.ExpectFail(ErrInvalidMethodPayloadType, "example/Handle");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadMethodNamedInvalidAlias) {
TestLibrary library(R"FIDL(
library example;
type ObjType = strict enum : uint32 {
NONE = 0;
VMO = 3;
};
type Rights = strict bits : uint32 {
TRANSFER = 1;
};
resource_definition Handle : uint32 {
properties {
subtype ObjType;
rights Rights;
};
};
alias MyPrimAlias = bool;
alias MyHandleAlias = Handle;
alias MyVectorAlias = vector<MyPrimAlias>;
alias MyAliasAlias = MyVectorAlias:optional;
protocol MyProtocol {
strict MyMethod(MyPrimAlias) -> (MyHandleAlias);
strict MyOtherMethod(MyVectorAlias) -> (MyAliasAlias);
};
)FIDL");
library.ExpectFail(ErrInvalidMethodPayloadType, "bool");
library.ExpectFail(ErrInvalidMethodPayloadType, "example/Handle");
library.ExpectFail(ErrInvalidMethodPayloadType, "vector<bool>");
// TODO(https://fxbug.dev/42175844): Should be "vector<bool>:optional".
library.ExpectFail(ErrInvalidMethodPayloadType, "vector<bool>?");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadMethodNamedInvalidKind) {
TestLibrary library(R"FIDL(
library example;
protocol MyOtherProtocol {
MyOtherMethod();
};
service MyService {
my_other_protocol client_end:MyOtherProtocol;
};
protocol MyProtocol {
MyMethod(MyOtherProtocol) -> (MyService);
};
)FIDL");
library.ExpectFail(ErrExpectedType);
library.ExpectFail(ErrExpectedType);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, GoodMethodTableRequest) {
TestLibrary library(R"FIDL(
library example;
protocol MyOtherProtocol {};
type MyTable = resource table {
1: a client_end:<MyProtocol>;
};
protocol MyProtocol {
MyMethodOneWay(table {
1: b bool;
});
MyMethodTwoWay(MyTable) -> ();
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, GoodMethodTableResponse) {
TestLibrary library(R"FIDL(
library example;
protocol MyOtherProtocol {};
type MyTable = resource table {
1: a client_end:<MyProtocol>;
};
protocol MyProtocol {
MyMethod() -> (table {
1: b bool;
});
-> OnMyEvent(MyTable);
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, GoodMethodTableResultPayload) {
TestLibrary library(R"FIDL(
library example;
protocol MyOtherProtocol {};
type MyTable = resource table {
1: a client_end:<MyProtocol>;
};
protocol MyProtocol {
MyMethod() -> (MyTable) error uint32;
MyAnonResponseMethod() -> (table {
1: b bool;
}) error uint32;
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, GoodMethodUnionRequest) {
TestLibrary library(R"FIDL(
library example;
protocol MyOtherProtocol {};
type MyUnion = strict resource union {
1: a client_end:<MyProtocol>;
};
protocol MyProtocol {
MyMethodOneWay(flexible union {
1: b bool;
});
MyMethodTwoWay(MyUnion) -> ();
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, GoodMethodUnionResponse) {
TestLibrary library(R"FIDL(
library example;
protocol MyOtherProtocol {};
type MyUnion = strict resource union {
1: a client_end:<MyProtocol>;
};
protocol MyProtocol {
MyMethod() -> (flexible union {
1: b bool;
});
-> OnMyEvent(MyUnion);
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, GoodMethodUnionResultPayload) {
TestLibrary library(R"FIDL(
library example;
protocol MyOtherProtocol {};
type MyUnion = strict resource union {
1: a client_end:<MyProtocol>;
};
protocol MyProtocol {
MyMethod() -> (MyUnion) error uint32;
MyAnonResponseMethod() -> (flexible union {
1: b bool;
}) error uint32;
};
)FIDL");
ASSERT_COMPILED(library);
}
TEST(ProtocolTests, BadOneWayErrorSyntax) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyOneWay() error int32;
};
)FIDL");
library.ExpectFail(ErrUnexpectedTokenOfKind, Token::KindAndSubkind(Token::Subkind::kError),
Token::KindAndSubkind(Token::Kind::kSemicolon));
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadEventErrorSyntax) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
-> OnMyEvent() error int32;
};
)FIDL");
library.ExpectFail(ErrUnexpectedTokenOfKind, Token::KindAndSubkind(Token::Subkind::kError),
Token::KindAndSubkind(Token::Kind::kSemicolon));
library.ExpectFail(ErrInvalidProtocolMember);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDisallowedRequestType) {
TestLibrary library;
library.AddFile("bad/fi-0075.test.fidl");
library.ExpectFail(ErrInvalidMethodPayloadType, "uint32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadInvalidRequestType) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod(box);
};
)FIDL");
library.ExpectFail(ErrWrongNumberOfLayoutParameters, "box", 1, 0);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDisallowedResponseType) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod() -> (uint32);
};
)FIDL");
library.ExpectFail(ErrInvalidMethodPayloadType, "uint32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadInvalidResponseType) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod() -> (box);
};
)FIDL");
library.ExpectFail(ErrWrongNumberOfLayoutParameters, "box", 1, 0);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadDisallowedSuccessType) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod() -> (uint32) error uint32;
};
)FIDL");
library.ExpectFail(ErrInvalidMethodPayloadType, "uint32");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST(ProtocolTests, BadInvalidSuccessType) {
TestLibrary library(R"FIDL(
library example;
protocol MyProtocol {
MyMethod() -> (box) error uint32;
};
)FIDL");
library.ExpectFail(ErrWrongNumberOfLayoutParameters, "box", 1, 0);
ASSERT_COMPILER_DIAGNOSTICS(library);
}
// TODO(https://fxbug.dev/42175339): add bad `:optional` message body tests here.
} // namespace
} // namespace fidlc