blob: 0ec9a79b338d7a774119f407bd95eea0cac1d655 [file] [log] [blame]
// Copyright 2019 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 <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tools/fidl/fidlc/src/diagnostics.h"
#include "tools/fidl/fidlc/tests/test_library.h"
namespace fidlc {
namespace {
using ::testing::HasSubstr;
#define ASSERT_WARNINGS(quantity, lib, content) \
do { \
const auto& warnings = (lib).lints(); \
if (strlen(content) != 0) { \
bool contains_content = false; \
for (size_t i = 0; i < warnings.size(); i++) { \
if (warnings[i].find(content) != std::string::npos) { \
contains_content = true; \
break; \
} \
} \
ASSERT_TRUE(contains_content) << (content) << " not found"; \
} \
if (warnings.size() != (quantity)) { \
std::string error = "Found warning: "; \
for (size_t i = 0; i < warnings.size(); i++) { \
error.append(warnings[i]); \
} \
ASSERT_EQ(static_cast<size_t>(quantity), warnings.size()) << error; \
} \
} while (0)
TEST(LintTests, BadConstNames) {
TestLibrary library(R"FIDL(
library fuchsia.a;
const bad_CONST uint64 = 1234;
)FIDL");
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint());
ASSERT_WARNINGS(1, library, "bad_CONST");
}
TEST(LintTests, BadConstNamesKconst) {
TestLibrary library(R"FIDL(
library fuchsia.a;
const kAllIsCalm uint64 = 1234;
)FIDL");
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint());
ASSERT_WARNINGS(1, library, "kAllIsCalm");
const auto& warnings = library.lints();
ASSERT_THAT(warnings[0], HasSubstr("ALL_IS_CALM"));
}
TEST(LintTests, GoodConstNames) {
TestLibrary library(R"FIDL(
library fuchsia.a;
const GOOD_CONST uint64 = 1234;
)FIDL");
ASSERT_COMPILED(library);
ASSERT_TRUE(library.Lint());
ASSERT_WARNINGS(0, library, "");
}
TEST(LintTests, BadProtocolNames) {
TestLibrary library(R"FIDL(
library fuchsia.a;
protocol URLLoader {};
)FIDL");
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint());
ASSERT_WARNINGS(1, library, "URLLoader");
const auto& warnings = library.lints();
ASSERT_THAT(warnings[0], HasSubstr("UrlLoader"));
}
TEST(LintTests, GoodProtocolNames) {
TestLibrary library(R"FIDL(
library fuchsia.a;
protocol UrlLoader {};
)FIDL");
ASSERT_COMPILED(library);
ASSERT_TRUE(library.Lint());
ASSERT_WARNINGS(0, library, "");
}
TEST(LintTests, BadLibraryNamesBannedName) {
TestLibrary library(R"FIDL(
library fuchsia.zxsocket;
)FIDL");
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint());
ASSERT_WARNINGS(1, library, "zxsocket");
}
TEST(LintTests, BadUsingNames) {
TestLibrary library(R"FIDL(
library fuchsia.a;
using zx as bad_USING;
alias Unused = bad_USING.Handle;
)FIDL");
library.UseLibraryZx();
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint());
ASSERT_WARNINGS(1, library, "bad_USING");
}
TEST(LintTests, GoodUsingNames) {
TestLibrary library(R"FIDL(
library fuchsia.a;
using zx as good_using;
alias Unused = good_using.Handle;
)FIDL");
library.UseLibraryZx();
ASSERT_COMPILED(library);
ASSERT_TRUE(library.Lint());
ASSERT_WARNINGS(0, library, "");
}
TEST(LintTests, BadAliasNames) {
TestLibrary library(R"FIDL(
library fuchsia.a;
alias snake_case = uint32;
)FIDL");
library.UseLibraryZx();
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint());
ASSERT_WARNINGS(1, library, "snake_case");
}
TEST(LintTests, GoodAliasNames) {
TestLibrary library(R"FIDL(
library fuchsia.a;
alias SnakeCase = uint32;
)FIDL");
library.UseLibraryZx();
ASSERT_COMPILED(library);
ASSERT_TRUE(library.Lint());
ASSERT_WARNINGS(0, library, "");
}
// TODO(https://fxbug.dev/42158155): Delete this test once new-types are supported.
// This is a case where compilation would fail, but since the linter only operates on the parsed
// raw AST, we would not yet know it. Thus, we expect compilation to fail, but linting to pass.
TEST(LintTests, GoodIgnoreNewTypes) {
TestLibrary library(R"FIDL(
library fuchsia.a;
type TransactionId = uint64;
)FIDL");
ASSERT_FALSE(library.Compile());
ASSERT_TRUE(library.Lint());
}
TEST(LintTests, GoodProtocolOpenness) {
TestLibrary library(R"FIDL(
library fuchsia.a;
open protocol OpenExample {};
ajar protocol AjarExample {};
closed protocol ClosedExample {};
)FIDL");
ASSERT_COMPILED(library);
ASSERT_TRUE(library.Lint({.included_check_ids = {"explicit-openness-modifier"}}));
ASSERT_WARNINGS(0, library, "");
}
TEST(LintTests, BadMissingProtocolOpenness) {
TestLibrary library(R"FIDL(
library fuchsia.a;
protocol Example {};
)FIDL");
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint({.included_check_ids = {"explicit-openness-modifier"}}));
ASSERT_WARNINGS(1, library, "Example must have an explicit openness modifier");
}
TEST(LintTests, GoodMethodStrictness) {
TestLibrary library(R"FIDL(
library fuchsia.a;
protocol DefaultOpenExample {
strict Foo1();
flexible Foo2();
strict Bar1() -> ();
flexible Bar2() -> ();
strict -> OnBaz1();
flexible -> OnBaz2();
};
open protocol OpenExample {
strict Foo1();
flexible Foo2();
strict Bar1() -> ();
flexible Bar2() -> ();
strict -> OnBaz1();
flexible -> OnBaz2();
};
ajar protocol AjarExample {
strict Foo1();
flexible Foo2();
strict Bar() -> ();
strict -> OnBaz1();
flexible -> OnBaz2();
};
closed protocol ClosedExample {
strict Foo();
strict Bar() -> ();
strict -> OnBaz();
};
)FIDL");
ASSERT_COMPILED(library);
ASSERT_TRUE(library.Lint({.included_check_ids = {"explicit-flexible-method-modifier"}}));
ASSERT_WARNINGS(0, library, "");
}
TEST(LintTests, BadMissingOneWayMethodStrictness) {
TestLibrary library(R"FIDL(
library fuchsia.a;
open protocol Example {
Foo();
};
)FIDL");
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint({.included_check_ids = {"explicit-flexible-method-modifier"}}));
ASSERT_WARNINGS(1, library, "Foo must have an explicit 'flexible' modifier");
}
TEST(LintTests, BadMissingTwoWayMethodStrictness) {
TestLibrary library(R"FIDL(
library fuchsia.a;
open protocol Example {
Foo() -> ();
};
)FIDL");
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint({.included_check_ids = {"explicit-flexible-method-modifier"}}));
ASSERT_WARNINGS(1, library, "Foo must have an explicit 'flexible' modifier");
}
TEST(LintTests, BadMissingEventStrictness) {
TestLibrary library(R"FIDL(
library fuchsia.a;
open protocol Example {
-> OnFoo();
};
)FIDL");
ASSERT_COMPILED(library);
ASSERT_FALSE(library.Lint({.included_check_ids = {"explicit-flexible-method-modifier"}}));
ASSERT_WARNINGS(1, library, "OnFoo must have an explicit 'flexible' modifier");
}
TEST(LintTests, BadMissingMethodStrictnessClosedProtocol) {
// A closed protocol with missing method strictness won't compile, but the
// linter will still emit a warning as well.
TestLibrary library(R"FIDL(
library fuchsia.a;
closed protocol Example {
Foo();
};
)FIDL");
library.ExpectFail(ErrFlexibleOneWayMethodInClosedProtocol, "one-way method");
ASSERT_COMPILER_DIAGNOSTICS(library);
ASSERT_FALSE(library.Lint({.included_check_ids = {"explicit-flexible-method-modifier"}}));
ASSERT_WARNINGS(1, library, "Foo must have an explicit 'flexible' modifier");
}
TEST(LintTests, BadMissingEventStrictnessClosedProtocol) {
// A closed protocol with missing event strictness won't compile, but the
// linter will still emit a warning as well.
TestLibrary library(R"FIDL(
library fuchsia.a;
closed protocol Example {
-> OnFoo();
};
)FIDL");
library.ExpectFail(ErrFlexibleOneWayMethodInClosedProtocol, "event");
ASSERT_COMPILER_DIAGNOSTICS(library);
ASSERT_FALSE(library.Lint({.included_check_ids = {"explicit-flexible-method-modifier"}}));
ASSERT_WARNINGS(1, library, "OnFoo must have an explicit 'flexible' modifier");
}
} // namespace
} // namespace fidlc