dawn-cmake/src/program_test.cc

107 lines
2.9 KiB
C++
Raw Normal View History

2020-03-02 20:47:43 +00:00
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
#include "gtest/gtest-spi.h"
#include "src/ast/return_statement.h"
#include "src/ast/test_helper.h"
2020-03-02 20:47:43 +00:00
namespace tint {
namespace {
2020-03-02 20:47:43 +00:00
using ProgramTest = ast::TestHelper;
2020-03-02 20:47:43 +00:00
TEST_F(ProgramTest, Unbuilt) {
Program program;
EXPECT_FALSE(program.IsValid());
}
TEST_F(ProgramTest, Creation) {
Program program(std::move(*this));
EXPECT_EQ(program.AST().Functions().size(), 0u);
2020-03-02 20:47:43 +00:00
}
TEST_F(ProgramTest, ToStrEmitsPreambleAndPostamble) {
Program program(std::move(*this));
const auto str = program.to_str();
auto* const expected = "Module{\n}\n";
EXPECT_EQ(str, expected);
}
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
TEST_F(ProgramTest, EmptyIsValid) {
Program program(std::move(*this));
EXPECT_TRUE(program.IsValid());
2020-03-02 20:47:43 +00:00
}
TEST_F(ProgramTest, IDsAreUnique) {
Program program_a(ProgramBuilder{});
Program program_b(ProgramBuilder{});
Program program_c(ProgramBuilder{});
EXPECT_NE(program_a.ID(), program_b.ID());
EXPECT_NE(program_b.ID(), program_c.ID());
EXPECT_NE(program_c.ID(), program_a.ID());
}
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
TEST_F(ProgramTest, Assert_GlobalVariable) {
Global("var", ty.f32(), ast::StorageClass::kInput);
Program program(std::move(*this));
EXPECT_TRUE(program.IsValid());
}
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
TEST_F(ProgramTest, Assert_NullGlobalVariable) {
EXPECT_FATAL_FAILURE(
{
ProgramBuilder b;
b.AST().AddGlobalVariable(nullptr);
},
"internal compiler error");
}
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
TEST_F(ProgramTest, Assert_NullConstructedType) {
EXPECT_FATAL_FAILURE(
{
ProgramBuilder b;
b.AST().AddConstructedType(nullptr);
},
"internal compiler error");
}
ast: Replace IsValid() with TINT_ASSERT() The readers must not produce invalid ASTs. If readers cannot produce a valid AST, then they should error instead. If a reader does produce an invalid AST, this change catches this bad behavior early, significantly helping identify the root of the broken logic. IsValid() made a bit more sense in the days where the AST was mutable, and was constructed by calling setters on the nodes to build up the tree. In order to detect bad ASTs, IsValid() would have to perform an entire AST traversal and give a yes / no answer for the entire tree. Not only was this slow, an answer of 'no' didn't tell you *where* the AST was invalid, resulting in a lot of manual debugging. Now that the AST is fully immutable, all child nodes need to be built before their parents. The AST node constructors now become a perfect place to perform pointer sanity checking. The argument for attempting to catch and handle invalid ASTs is not a compelling one. Invalid ASTs are invalid compiler behavior, not something that should ever happen with a correctly functioning compiler. If this were to happen in production, the user would be utterly clueless to _why_ the program is invalid, or _how_ to fix it. Attempting to handle invalid ASTs is just masking a much larger problem. Let's just let the fuzzers do their job to catch any of these cases early. Fixed: chromium:1185569 Change-Id: I6496426a3a9da9d42627d2c1ca23917bfd04cc5c Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/44048 Commit-Queue: Ben Clayton <bclayton@chromium.org> Reviewed-by: David Neto <dneto@google.com>
2021-03-10 11:41:49 +00:00
TEST_F(ProgramTest, Assert_Null_Function) {
EXPECT_FATAL_FAILURE(
{
ProgramBuilder b;
b.AST().AddFunction(nullptr);
},
"internal compiler error");
}
TEST_F(ProgramTest, DiagnosticsMove) {
Diagnostics().add_error("an error message");
Program program_a(std::move(*this));
EXPECT_FALSE(program_a.IsValid());
EXPECT_EQ(program_a.Diagnostics().count(), 1u);
EXPECT_EQ(program_a.Diagnostics().error_count(), 1u);
EXPECT_EQ(program_a.Diagnostics().begin()->message, "an error message");
Program program_b(std::move(program_a));
EXPECT_FALSE(program_b.IsValid());
EXPECT_EQ(program_b.Diagnostics().count(), 1u);
EXPECT_EQ(program_b.Diagnostics().error_count(), 1u);
EXPECT_EQ(program_b.Diagnostics().begin()->message, "an error message");
}
} // namespace
2020-03-02 20:47:43 +00:00
} // namespace tint