blob: fc4bb8bdd767ba44b69012bccde7ea44f51bbc6e [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 <fidl/flat_ast.h>
#include <fidl/lexer.h>
#include <fidl/parser.h>
#include <fidl/source_file.h>
#include <unittest/unittest.h>
#include "test_library.h"
namespace {
bool valid_empty_protocol() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
protocol Empty {};
)FIDL");
ASSERT_TRUE(library.Compile());
auto protocol = library.LookupProtocol("Empty");
ASSERT_NONNULL(protocol);
EXPECT_EQ(protocol->methods.size(), 0);
EXPECT_EQ(protocol->all_methods.size(), 0);
END_TEST;
}
bool valid_compose_method() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
protocol HasComposeMethod1 {
compose();
};
protocol HasComposeMethod2 {
compose() -> ();
};
)FIDL");
ASSERT_TRUE(library.Compile());
auto protocol1 = library.LookupProtocol("HasComposeMethod1");
ASSERT_NONNULL(protocol1);
EXPECT_EQ(protocol1->methods.size(), 1);
EXPECT_EQ(protocol1->all_methods.size(), 1);
auto protocol2 = library.LookupProtocol("HasComposeMethod2");
ASSERT_NONNULL(protocol2);
EXPECT_EQ(protocol2->methods.size(), 1);
EXPECT_EQ(protocol2->all_methods.size(), 1);
END_TEST;
}
bool valid_protocol_composition() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
[FragileBase]
protocol A {
MethodA();
};
[FragileBase]
protocol B {
compose A;
MethodB();
};
[FragileBase]
protocol C {
compose A;
MethodC();
};
protocol D {
compose B;
compose C;
MethodD();
};
)FIDL");
ASSERT_TRUE(library.Compile());
auto protocol_a = library.LookupProtocol("A");
ASSERT_NONNULL(protocol_a);
EXPECT_EQ(protocol_a->methods.size(), 1);
EXPECT_EQ(protocol_a->all_methods.size(), 1);
auto protocol_b = library.LookupProtocol("B");
ASSERT_NONNULL(protocol_b);
EXPECT_EQ(protocol_b->methods.size(), 1);
EXPECT_EQ(protocol_b->all_methods.size(), 2);
auto protocol_c = library.LookupProtocol("C");
ASSERT_NONNULL(protocol_c);
EXPECT_EQ(protocol_c->methods.size(), 1);
EXPECT_EQ(protocol_c->all_methods.size(), 2);
auto protocol_d = library.LookupProtocol("D");
ASSERT_NONNULL(protocol_d);
EXPECT_EQ(protocol_d->methods.size(), 1);
EXPECT_EQ(protocol_d->all_methods.size(), 4);
END_TEST;
}
bool invalid_colon_syntax_is_not_supported() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
protocol Parent {};
protocol Child : Parent {};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "unexpected token Colon, was expecting LeftCurly");
END_TEST;
}
bool invalid_cannot_attach_attributes_to_compose() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
protocol Child {
[NoCantDo] compose Parent;
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "Cannot attach attributes to compose stanza");
END_TEST;
}
bool invalid_cannot_compose_yourself() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
[FragileBase]
protocol Narcisse {
compose Narcisse;
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "There is an includes-cycle in declaration");
END_TEST;
}
bool invalid_cannot_compose_twice_the_same_protocol() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
[FragileBase]
protocol Parent {
Method();
};
protocol Child {
compose Parent;
compose Parent;
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "protocol composed multiple times");
END_TEST;
}
bool invalid_cannot_compose_missing_protocol() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
protocol Child {
compose MissingParent;
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "unknown type MissingParent");
END_TEST;
}
bool invalid_cannot_use_ordinals_in_protocol_declaration() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
protocol NoMoreOrdinals {
42: NiceTry();
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "unexpected token NumericLiteral, was expecting RightCurly");
END_TEST;
}
bool invalid_no_other_pragma_than_compose() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
protocol Wrong {
not_compose Something;
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "unrecognized protocol member");
END_TEST;
}
bool invalid_composed_protocols_have_clashing_names() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
[FragileBase]
protocol A {
MethodA();
};
[FragileBase]
protocol B {
compose A;
MethodB();
};
[FragileBase]
protocol C {
compose A;
MethodC();
};
protocol D {
compose B;
compose C;
MethodD();
MethodA();
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "Multiple methods with the same name in a protocol");
END_TEST;
}
bool invalid_composed_protocols_have_clashing_ordinals() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library a;
// a.b/lo and a.cv/f have colliding computed ordinals, so this is an illegal
// FIDL definition.
[FragileBase]
protocol b {
lo();
};
[FragileBase]
protocol cv {
compose b;
f();
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(),
"Multiple methods with the same ordinal in a protocol; "
"previous was at example.fidl:9:4. "
"Consider using attribute [Selector=\"f_\"] to change the name used to "
"calculate the ordinal.");
END_TEST;
}
bool invalid_simple_constraint_applies_to_composed_methods_too() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
[FragileBase]
protocol NotSimple {
Complex(vector<uint64> arg);
};
[Layout="Simple"]
protocol YearningForSimplicity {
compose NotSimple;
Simple();
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(), "member 'arg' is not simple");
END_TEST;
}
bool invalid_missing_fragile_base_on_composed_protocol() {
BEGIN_TEST;
TestLibrary library(R"FIDL(
library example;
protocol NoFragileBase {
};
protocol Child {
compose NoFragileBase;
};
)FIDL");
ASSERT_FALSE(library.Compile());
auto errors = library.errors();
ASSERT_EQ(errors.size(), 1);
ASSERT_STR_STR(errors[0].c_str(),
"protocol example/NoFragileBase is not marked by [FragileBase] "
"attribute, disallowing protocol example/Child from "
"composing it");
END_TEST;
}
} // namespace
BEGIN_TEST_CASE(protocol_tests)
RUN_TEST(valid_empty_protocol)
RUN_TEST(valid_compose_method)
RUN_TEST(valid_protocol_composition)
RUN_TEST(invalid_colon_syntax_is_not_supported)
RUN_TEST(invalid_cannot_attach_attributes_to_compose)
RUN_TEST(invalid_cannot_compose_yourself)
RUN_TEST(invalid_cannot_compose_twice_the_same_protocol)
RUN_TEST(invalid_cannot_compose_missing_protocol)
RUN_TEST(invalid_cannot_use_ordinals_in_protocol_declaration)
RUN_TEST(invalid_no_other_pragma_than_compose)
RUN_TEST(invalid_composed_protocols_have_clashing_names)
RUN_TEST(invalid_composed_protocols_have_clashing_ordinals)
RUN_TEST(invalid_simple_constraint_applies_to_composed_methods_too)
RUN_TEST(invalid_missing_fragile_base_on_composed_protocol)
END_TEST_CASE(protocol_tests)