blob: 9532f48895419306d01ad93ae96c03098d62924c [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 <zxtest/zxtest.h>
#include "error_test.h"
#include "fidl/diagnostics.h"
#include "test_library.h"
namespace {
TEST(RecoverableParsingTests, BadRecoverAtEndOfFile) {
TestLibrary library(R"FIDL(
library example;
enum Enum {
ONE; // First error
};
bits Bits {
CONSTANT = ; // Second error
};
)FIDL");
ASSERT_ERRORED_TWICE_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind,
fidl::ErrUnexpectedToken);
}
TEST(RecoverableParsingTests, BadRecoverAtEndOfDecl) {
TestLibrary library(R"FIDL(
library example;
enum Enum {
VARIANT = 0;
MISSING_EQUALS 5;
};
union Union {
1: string string_value;
2 uint16 missing_colon;
};
struct Struct {
string value;
};
)FIDL");
ASSERT_ERRORED_TWICE_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind,
fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadRecoverAtEndOfMember) {
TestLibrary library(R"FIDL(
library example;
enum SettingType {
UNKNOWN = 0;
TIME_ZONE = 1;
CONNECTIVITY 2; // Error: missing equals
};
union SettingData {
1: string string_value;
2 ConnectedState time_zone_value; // Error: missing colon
/// Unattached doc comment. // Error: doc comment must be attached
};
LoginOverride { // Error: missing keyword
NONE = 0;
AUTH.PROVIDER = 2, // Error: '.' in identifier
};
table AccountSettings {
1: LoginOverride mo.de; // Error: '.' in identifier
3: OtherSetting setting;
};
struct TimeZoneInfo {
TimeZone? current;
vector<<TimeZone> available; // Error: extra <
};
struct TimeZone {
string id;
string name;
vector<string> region;
};
)FIDL");
EXPECT_FALSE(library.Compile());
const auto& errors = library.errors();
ASSERT_EQ(errors.size(), 7);
ASSERT_ERR(errors[0], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[1], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[2], fidl::ErrMissingOrdinalBeforeType);
ASSERT_ERR(errors[3], fidl::ErrExpectedDeclaration);
ASSERT_ERR(errors[4], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[5], fidl::ErrExpectedOrdinalOrCloseBrace);
ASSERT_ERR(errors[6], fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadDoNotCompileAfterParsingFails) {
TestLibrary library(R"FIDL(
library example;
const uint8 compound.identifier = 0; // Syntax error
struct NameCollision {};
struct NameCollision {}; // This name collision error will not be
// reported, because if parsing fails
// compilation is skipped
)FIDL");
ASSERT_ERRORED_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadRecoverToNextBitsMember) {
TestLibrary library(R"FIDL(
library example;
bits Bits {
ONE 0x1; // First error
TWO = 0x2;
FOUR = 0x4 // Second error
EIGHT = 0x8;
};
)FIDL");
ASSERT_ERRORED_TWICE_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind,
fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadRecoverToNextEnumMember) {
TestLibrary library(R"FIDL(
library example;
enum Enum {
ONE 1; // First error
TWO = 2;
THREE = 3 // Second error
FOUR = 4;
};
)FIDL");
ASSERT_ERRORED_TWICE_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind,
fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadRecoverToNextProtocolMember) {
TestLibrary library(R"FIDL(
library example;
protocol P {
compose A B; // Error
MethodWithoutSemicolon() // Error
ValidMethod();
-> Event(TypeWithoutParamName); // Error
MissingParen request<Protocol> protocol); // Error
-> Event(Type missing_paren; // Error
ValidMethod();
Method() -> (uint16 num) error; // Error
};
)FIDL");
EXPECT_FALSE(library.Compile());
const auto& errors = library.errors();
ASSERT_EQ(errors.size(), 8);
ASSERT_ERR(errors[0], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[1], fidl::ErrUnrecognizedProtocolMember);
ASSERT_ERR(errors[2], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[3], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[4], fidl::ErrUnexpectedToken);
ASSERT_ERR(errors[5], fidl::ErrUnrecognizedProtocolMember);
ASSERT_ERR(errors[6], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[7], fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadRecoverToNextServiceMember) {
TestLibrary library(R"FIDL(
library example;
protocol P {};
protocol Q {};
protocol R {};
service Service {
P p extra_token; // First error
Q q // Second error
R r;
};
)FIDL");
ASSERT_ERRORED_TWICE_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind,
fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadRecoverToNextStructMember) {
TestLibrary library(R"FIDL(
library example;
struct Struct {
string string_value extra_token; // Error
uint8 uint_value;
vector<handle> vector_value // Error
int32 int_value;
};
)FIDL");
EXPECT_FALSE(library.Compile());
const auto& errors = library.errors();
ASSERT_EQ(errors.size(), 3);
ASSERT_ERR(errors[0], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[1], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[2], fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadRecoverToNextTableMember) {
TestLibrary library(R"FIDL(
library example;
table Table {
1: string string_value // Error
2: uint8 uint_value;
3: vector<handle> value_with space; // Error
4: int32 int_value;
};
)FIDL");
EXPECT_FALSE(library.Compile());
const auto& errors = library.errors();
ASSERT_EQ(errors.size(), 3);
ASSERT_ERR(errors[0], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[1], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[2], fidl::ErrExpectedOrdinalOrCloseBrace);
}
TEST(RecoverableParsingTests, BadRecoverToNextUnionMember) {
TestLibrary library(R"FIDL(
library example;
union Union {
1 string missing_colon; // First error
3: uint8 uint_value;
4: string missing_semicolon // Second error
5: int16 int_value;
};
)FIDL");
ASSERT_ERRORED_TWICE_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind,
fidl::ErrUnexpectedTokenOfKind);
}
TEST(RecoverableParsingTests, BadRecoverToNextParameterInList) {
TestLibrary library(R"FIDL(
library example;
protocol Protocol {
Method(uint8, uint16 n);
Method(, string s);
-> Event(Type, uint8 num, string compound.identifier);
Method(uint8 num, uint16 num) -> (uint16 value, string value_with space);
Method(Type param, request<<LocationLookup> frame) - (uint16 port);
};
)FIDL");
EXPECT_FALSE(library.Compile());
const auto& errors = library.errors();
ASSERT_EQ(errors.size(), 8);
ASSERT_ERR(errors[0], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[1], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[2], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[3], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[4], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[5], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[6], fidl::ErrUnexpectedTokenOfKind);
ASSERT_ERR(errors[7], fidl::ErrExpectedProtocolMember);
}
TEST(RecoverableParsingTests, BadRecoverFinalMemberMissingSemicolon) {
TestLibrary library(R"FIDL(
library example;
struct Struct {
uint8 uint_value;
string foo // First error
};
// Recovered back to top-level parsing.
struct Good {};
extra_token // Second error
)FIDL");
ASSERT_ERRORED_TWICE_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind,
fidl::ErrExpectedDeclaration);
}
TEST(RecoverableParsingTests, BadRecoverFinalMemberMissingNameAndSemicolon) {
TestLibrary library(R"FIDL(
library example;
struct Struct {
uint8 uint_value;
string }; // First error
// Does not recover back to top-level parsing. End the struct.
};
// Back to top-level parsing.
struct Good {};
extra_token // Second error
)FIDL");
ASSERT_ERRORED_TWICE_DURING_COMPILE(library, fidl::ErrUnexpectedTokenOfKind,
fidl::ErrExpectedDeclaration);
}
} // namespace