blob: a8b54f14a8e8fcfceb85bed39aec58cacc3ad7dd [file] [log] [blame]
// Copyright 2024 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/tests/test_library.h"
// This file tests how FIDL versioning distinguishes "removal" from
// "replacement", and validation that replacement is done correctly.
// Tests are run for all the versions given in INSTANTIATE_TEST_SUITE_P.
namespace fidlc {
namespace {
class VersioningReplacementTest : public testing::TestWithParam<Version> {};
const Version V1 = Version::From(1).value();
const Version V2 = Version::From(2).value();
const Version V3 = Version::From(3).value();
INSTANTIATE_TEST_SUITE_P(VersioningReplacementTests, VersioningReplacementTest,
testing::Values(V1, V2, V3),
[](auto info) { return info.param.ToString(); });
TEST_P(VersioningReplacementTest, BadRemovedWithReplacement) {
TestLibrary library;
library.SelectVersion("test", GetParam());
library.AddFile("bad/fi-0205.test.fidl");
library.ExpectFail(ErrRemovedWithReplacement, "Bar", Version::From(2).value(),
"bad/fi-0205.test.fidl:11:14");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST_P(VersioningReplacementTest, BadRemovedNamedToAnonymous) {
TestLibrary library(R"FIDL(
@available(added=1)
library example;
@available(removed=2)
type Foo = struct {};
type Bar = struct {
@available(added=2)
foo struct {};
};
)FIDL");
library.SelectVersion("example", GetParam());
library.ExpectFail(ErrRemovedWithReplacement, "Foo", Version::From(2).value(),
"example.fidl:10:9");
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST_P(VersioningReplacementTest, GoodRemovedAnonymousToNamed) {
TestLibrary library(R"FIDL(
@available(added=1)
library example;
type Bar = struct {
// The anonymous type "Foo" inherits removed=2, but removed/replaced
// does not apply to inherited availabilities.
@available(removed=2)
foo struct {};
};
@available(added=2)
type Foo = table {};
)FIDL");
library.SelectVersion("example", GetParam());
ASSERT_COMPILED(library);
EXPECT_EQ(library.HasStruct("Foo"), GetParam() == V1);
EXPECT_EQ(library.HasTable("Foo"), GetParam() >= V2);
}
TEST_P(VersioningReplacementTest, GoodRemovedAnonymousToAnonymous) {
TestLibrary library(R"FIDL(
@available(added=1)
library example;
type Bar1 = struct {
// The anonymous type "Foo" inherits removed=2, but removed/replaced
// does not apply to inherited availabilities.
@available(removed=2)
foo struct {};
};
type Bar2 = struct {
@available(added=2)
foo table {};
};
)FIDL");
library.SelectVersion("example", GetParam());
ASSERT_COMPILED(library);
EXPECT_EQ(library.HasStruct("Foo"), GetParam() == V1);
EXPECT_EQ(library.HasTable("Foo"), GetParam() >= V2);
}
TEST_P(VersioningReplacementTest, BadReplacedWithoutReplacement) {
TestLibrary library;
library.SelectVersion("test", GetParam());
library.AddFile("bad/fi-0206.test.fidl");
library.ExpectFail(ErrReplacedWithoutReplacement, "Bar", Version::From(2).value());
ASSERT_COMPILER_DIAGNOSTICS(library);
}
TEST_P(VersioningReplacementTest, GoodAnonymousReplacedWithoutReplacement) {
TestLibrary library(R"FIDL(
@available(added=1)
library example;
type Bar = struct {
// The anonymous type "Foo" inherits replaced=2, but removed/replaced
// validation does not apply to inherited availabilities.
@available(replaced=2)
foo struct {};
@available(added=2)
foo string;
};
)FIDL");
library.SelectVersion("example", GetParam());
ASSERT_COMPILED(library);
EXPECT_EQ(library.HasStruct("Foo"), GetParam() == V1);
}
TEST_P(VersioningReplacementTest, GoodReplacedNamedToAnonymous) {
TestLibrary library(R"FIDL(
@available(added=1)
library example;
@available(replaced=2)
type Foo = struct {};
type Bar = struct {
@available(added=2)
foo table {};
};
)FIDL");
library.SelectVersion("example", GetParam());
ASSERT_COMPILED(library);
EXPECT_EQ(library.HasStruct("Foo"), GetParam() == V1);
EXPECT_EQ(library.HasTable("Foo"), GetParam() >= V2);
}
TEST_P(VersioningReplacementTest, GoodReplacedAnonymousToNamed) {
TestLibrary library(R"FIDL(
@available(added=1)
library example;
type Bar = struct {
@available(replaced=2)
foo struct {};
@available(added=2)
foo string;
};
@available(added=2)
type Foo = table {};
)FIDL");
library.SelectVersion("example", GetParam());
ASSERT_COMPILED(library);
EXPECT_EQ(library.HasStruct("Foo"), GetParam() == V1);
EXPECT_EQ(library.HasTable("Foo"), GetParam() >= V2);
}
TEST_P(VersioningReplacementTest, GoodReplacedAnonymousToAnonymous) {
TestLibrary library(R"FIDL(
@available(added=1)
library example;
type Bar1 = struct {
@available(replaced=2)
foo struct {};
@available(added=2)
foo string;
};
type Bar2 = struct {
@available(added=2)
foo table {};
};
)FIDL");
library.SelectVersion("example", GetParam());
ASSERT_COMPILED(library);
EXPECT_EQ(library.HasStruct("Foo"), GetParam() == V1);
EXPECT_EQ(library.HasTable("Foo"), GetParam() >= V2);
}
TEST_P(VersioningReplacementTest, GoodReplacedTwice) {
TestLibrary library(R"FIDL(
@available(added=1)
library example;
@available(replaced=2)
type Foo = struct {};
@available(added=2, replaced=3)
type Foo = table {};
@available(added=3)
type Foo = union {};
)FIDL");
library.SelectVersion("example", GetParam());
ASSERT_COMPILED(library);
EXPECT_EQ(library.HasStruct("Foo"), GetParam() == V1);
EXPECT_EQ(library.HasTable("Foo"), GetParam() == V2);
EXPECT_EQ(library.HasUnion("Foo"), GetParam() >= V3);
}
} // namespace
} // namespace fidlc