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/discard_statement.h"
17 #include "src/ast/stage_decoration.h"
18 #include "src/ast/test_helper.h"
19 #include "src/ast/workgroup_decoration.h"
20
21 namespace tint {
22 namespace ast {
23 namespace {
24
25 using FunctionTest = TestHelper;
26
TEST_F(FunctionTest,Creation)27 TEST_F(FunctionTest, Creation) {
28 VariableList params;
29 params.push_back(Param("var", ty.i32()));
30 auto* var = params[0];
31
32 auto* f = Func("func", params, ty.void_(), StatementList{}, DecorationList{});
33 EXPECT_EQ(f->symbol, Symbols().Get("func"));
34 ASSERT_EQ(f->params.size(), 1u);
35 EXPECT_TRUE(f->return_type->Is<ast::Void>());
36 EXPECT_EQ(f->params[0], var);
37 }
38
TEST_F(FunctionTest,Creation_WithSource)39 TEST_F(FunctionTest, Creation_WithSource) {
40 VariableList params;
41 params.push_back(Param("var", ty.i32()));
42
43 auto* f = Func(Source{Source::Location{20, 2}}, "func", params, ty.void_(),
44 StatementList{}, DecorationList{});
45 auto src = f->source;
46 EXPECT_EQ(src.range.begin.line, 20u);
47 EXPECT_EQ(src.range.begin.column, 2u);
48 }
49
TEST_F(FunctionTest,Assert_InvalidName)50 TEST_F(FunctionTest, Assert_InvalidName) {
51 EXPECT_FATAL_FAILURE(
52 {
53 ProgramBuilder b;
54 b.Func("", VariableList{}, b.ty.void_(), StatementList{},
55 DecorationList{});
56 },
57 "internal compiler error");
58 }
59
TEST_F(FunctionTest,Assert_Null_ReturnType)60 TEST_F(FunctionTest, Assert_Null_ReturnType) {
61 EXPECT_FATAL_FAILURE(
62 {
63 ProgramBuilder b;
64 b.Func("f", VariableList{}, nullptr, StatementList{}, DecorationList{});
65 },
66 "internal compiler error");
67 }
68
TEST_F(FunctionTest,Assert_Null_Param)69 TEST_F(FunctionTest, Assert_Null_Param) {
70 EXPECT_FATAL_FAILURE(
71 {
72 ProgramBuilder b;
73 VariableList params;
74 params.push_back(b.Param("var", b.ty.i32()));
75 params.push_back(nullptr);
76
77 b.Func("f", params, b.ty.void_(), StatementList{}, DecorationList{});
78 },
79 "internal compiler error");
80 }
81
TEST_F(FunctionTest,Assert_DifferentProgramID_Symbol)82 TEST_F(FunctionTest, Assert_DifferentProgramID_Symbol) {
83 EXPECT_FATAL_FAILURE(
84 {
85 ProgramBuilder b1;
86 ProgramBuilder b2;
87 b1.Func(b2.Sym("func"), VariableList{}, b1.ty.void_(), StatementList{});
88 },
89 "internal compiler error");
90 }
91
TEST_F(FunctionTest,Assert_DifferentProgramID_Param)92 TEST_F(FunctionTest, Assert_DifferentProgramID_Param) {
93 EXPECT_FATAL_FAILURE(
94 {
95 ProgramBuilder b1;
96 ProgramBuilder b2;
97 b1.Func("func", VariableList{b2.Param("var", b2.ty.i32())},
98 b1.ty.void_(), StatementList{});
99 },
100 "internal compiler error");
101 }
102
TEST_F(FunctionTest,Assert_DifferentProgramID_Deco)103 TEST_F(FunctionTest, Assert_DifferentProgramID_Deco) {
104 EXPECT_FATAL_FAILURE(
105 {
106 ProgramBuilder b1;
107 ProgramBuilder b2;
108 b1.Func("func", VariableList{}, b1.ty.void_(), StatementList{},
109 DecorationList{
110 b2.WorkgroupSize(2, 4, 6),
111 });
112 },
113 "internal compiler error");
114 }
115
TEST_F(FunctionTest,Assert_DifferentProgramID_ReturnDeco)116 TEST_F(FunctionTest, Assert_DifferentProgramID_ReturnDeco) {
117 EXPECT_FATAL_FAILURE(
118 {
119 ProgramBuilder b1;
120 ProgramBuilder b2;
121 b1.Func("func", VariableList{}, b1.ty.void_(), StatementList{},
122 DecorationList{},
123 DecorationList{
124 b2.WorkgroupSize(2, 4, 6),
125 });
126 },
127 "internal compiler error");
128 }
129
TEST_F(FunctionTest,Assert_NonConstParam)130 TEST_F(FunctionTest, Assert_NonConstParam) {
131 EXPECT_FATAL_FAILURE(
132 {
133 ProgramBuilder b;
134 VariableList params;
135 params.push_back(b.Var("var", b.ty.i32(), ast::StorageClass::kNone));
136
137 b.Func("f", params, b.ty.void_(), StatementList{}, DecorationList{});
138 },
139 "internal compiler error");
140 }
141
142 using FunctionListTest = TestHelper;
143
TEST_F(FunctionListTest,FindSymbol)144 TEST_F(FunctionListTest, FindSymbol) {
145 auto* func = Func("main", VariableList{}, ty.f32(), StatementList{},
146 ast::DecorationList{});
147 FunctionList list;
148 list.Add(func);
149 EXPECT_EQ(func, list.Find(Symbols().Register("main")));
150 }
151
TEST_F(FunctionListTest,FindSymbolMissing)152 TEST_F(FunctionListTest, FindSymbolMissing) {
153 FunctionList list;
154 EXPECT_EQ(nullptr, list.Find(Symbols().Register("Missing")));
155 }
156
TEST_F(FunctionListTest,FindSymbolStage)157 TEST_F(FunctionListTest, FindSymbolStage) {
158 auto* fs = Func("main", VariableList{}, ty.f32(), StatementList{},
159 ast::DecorationList{
160 Stage(PipelineStage::kFragment),
161 });
162 auto* vs = Func("main", VariableList{}, ty.f32(), StatementList{},
163 ast::DecorationList{
164 Stage(PipelineStage::kVertex),
165 });
166 FunctionList list;
167 list.Add(fs);
168 list.Add(vs);
169 EXPECT_EQ(fs,
170 list.Find(Symbols().Register("main"), PipelineStage::kFragment));
171 EXPECT_EQ(vs, list.Find(Symbols().Register("main"), PipelineStage::kVertex));
172 }
173
TEST_F(FunctionListTest,FindSymbolStageMissing)174 TEST_F(FunctionListTest, FindSymbolStageMissing) {
175 FunctionList list;
176 list.Add(Func("main", VariableList{}, ty.f32(), StatementList{},
177 ast::DecorationList{
178 Stage(PipelineStage::kFragment),
179 }));
180 EXPECT_EQ(nullptr,
181 list.Find(Symbols().Register("main"), PipelineStage::kVertex));
182 }
183
TEST_F(FunctionListTest,HasStage)184 TEST_F(FunctionListTest, HasStage) {
185 FunctionList list;
186 list.Add(Func("main", VariableList{}, ty.f32(), StatementList{},
187 ast::DecorationList{
188 Stage(PipelineStage::kFragment),
189 }));
190 EXPECT_TRUE(list.HasStage(PipelineStage::kFragment));
191 EXPECT_FALSE(list.HasStage(PipelineStage::kVertex));
192 }
193
194 } // namespace
195 } // namespace ast
196 } // namespace tint
197