1 // Copyright 2020 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "gtest/gtest-spi.h"
16 #include "src/ast/test_helper.h"
17 #include "src/clone_context.h"
18
19 namespace tint {
20 namespace ast {
21 namespace {
22
23 using ModuleTest = TestHelper;
24
TEST_F(ModuleTest,Creation)25 TEST_F(ModuleTest, Creation) {
26 EXPECT_EQ(Program(std::move(*this)).AST().Functions().size(), 0u);
27 }
28
TEST_F(ModuleTest,LookupFunction)29 TEST_F(ModuleTest, LookupFunction) {
30 auto* func = Func("main", VariableList{}, ty.f32(), StatementList{},
31 ast::DecorationList{});
32
33 Program program(std::move(*this));
34 EXPECT_EQ(func,
35 program.AST().Functions().Find(program.Symbols().Get("main")));
36 }
37
TEST_F(ModuleTest,LookupFunctionMissing)38 TEST_F(ModuleTest, LookupFunctionMissing) {
39 Program program(std::move(*this));
40 EXPECT_EQ(nullptr,
41 program.AST().Functions().Find(program.Symbols().Get("Missing")));
42 }
43
TEST_F(ModuleTest,Assert_Null_GlobalVariable)44 TEST_F(ModuleTest, Assert_Null_GlobalVariable) {
45 EXPECT_FATAL_FAILURE(
46 {
47 ProgramBuilder builder;
48 builder.AST().AddGlobalVariable(nullptr);
49 },
50 "internal compiler error");
51 }
52
TEST_F(ModuleTest,Assert_Null_TypeDecl)53 TEST_F(ModuleTest, Assert_Null_TypeDecl) {
54 EXPECT_FATAL_FAILURE(
55 {
56 ProgramBuilder builder;
57 builder.AST().AddTypeDecl(nullptr);
58 },
59 "internal compiler error");
60 }
61
TEST_F(ModuleTest,Assert_DifferentProgramID_Function)62 TEST_F(ModuleTest, Assert_DifferentProgramID_Function) {
63 EXPECT_FATAL_FAILURE(
64 {
65 ProgramBuilder b1;
66 ProgramBuilder b2;
67 b1.AST().AddFunction(b2.create<ast::Function>(
68 b2.Symbols().Register("func"), VariableList{}, b2.ty.f32(),
69 b2.Block(), DecorationList{}, DecorationList{}));
70 },
71 "internal compiler error");
72 }
73
TEST_F(ModuleTest,Assert_DifferentProgramID_GlobalVariable)74 TEST_F(ModuleTest, Assert_DifferentProgramID_GlobalVariable) {
75 EXPECT_FATAL_FAILURE(
76 {
77 ProgramBuilder b1;
78 ProgramBuilder b2;
79 b1.AST().AddGlobalVariable(
80 b2.Var("var", b2.ty.i32(), ast::StorageClass::kPrivate));
81 },
82 "internal compiler error");
83 }
84
TEST_F(ModuleTest,Assert_Null_Function)85 TEST_F(ModuleTest, Assert_Null_Function) {
86 EXPECT_FATAL_FAILURE(
87 {
88 ProgramBuilder builder;
89 builder.AST().AddFunction(nullptr);
90 },
91 "internal compiler error");
92 }
93
TEST_F(ModuleTest,CloneOrder)94 TEST_F(ModuleTest, CloneOrder) {
95 // Create a program with a function, alias decl and var decl.
96 Program p = [] {
97 ProgramBuilder b;
98 b.Func("F", {}, b.ty.void_(), {});
99 b.Alias("A", b.ty.u32());
100 b.Global("V", b.ty.i32(), ast::StorageClass::kPrivate);
101 return Program(std::move(b));
102 }();
103
104 // Clone the program, using ReplaceAll() to create new module-scope
105 // declarations. We want to test that these are added just before the
106 // declaration that triggered the ReplaceAll().
107 ProgramBuilder cloned;
108 CloneContext ctx(&cloned, &p);
109 ctx.ReplaceAll([&](const ast::Function*) -> const ast::Function* {
110 ctx.dst->Alias("inserted_before_F", cloned.ty.u32());
111 return nullptr;
112 });
113 ctx.ReplaceAll([&](const ast::Alias*) -> const ast::Alias* {
114 ctx.dst->Alias("inserted_before_A", cloned.ty.u32());
115 return nullptr;
116 });
117 ctx.ReplaceAll([&](const ast::Variable*) -> const ast::Variable* {
118 ctx.dst->Alias("inserted_before_V", cloned.ty.u32());
119 return nullptr;
120 });
121 ctx.Clone();
122
123 auto& decls = cloned.AST().GlobalDeclarations();
124 ASSERT_EQ(decls.size(), 6u);
125 EXPECT_TRUE(decls[1]->Is<ast::Function>());
126 EXPECT_TRUE(decls[3]->Is<ast::Alias>());
127 EXPECT_TRUE(decls[5]->Is<ast::Variable>());
128
129 ASSERT_TRUE(decls[0]->Is<ast::Alias>());
130 ASSERT_TRUE(decls[2]->Is<ast::Alias>());
131 ASSERT_TRUE(decls[4]->Is<ast::Alias>());
132
133 ASSERT_EQ(cloned.Symbols().NameFor(decls[0]->As<ast::Alias>()->name),
134 "inserted_before_F");
135 ASSERT_EQ(cloned.Symbols().NameFor(decls[2]->As<ast::Alias>()->name),
136 "inserted_before_A");
137 ASSERT_EQ(cloned.Symbols().NameFor(decls[4]->As<ast::Alias>()->name),
138 "inserted_before_V");
139 }
140
141 } // namespace
142 } // namespace ast
143 } // namespace tint
144