1 //
2 // Copyright 2012 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "PreprocessorTest.h"
8 #include "compiler/preprocessor/Token.h"
9
10 namespace angle
11 {
12
13 class VersionTest : public SimplePreprocessorTest
14 {};
15
TEST_F(VersionTest,NoDirectives)16 TEST_F(VersionTest, NoDirectives)
17 {
18 const char *str = "foo\n";
19 const char *expected = "foo\n";
20
21 using testing::_;
22 EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 100, SH_GLES2_SPEC, _));
23 // No error or warning.
24 EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
25
26 preprocess(str, expected);
27 }
28
TEST_F(VersionTest,NoVersion)29 TEST_F(VersionTest, NoVersion)
30 {
31 const char *str = "#define foo\n";
32 const char *expected = "\n";
33
34 using testing::_;
35 EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 100, SH_GLES2_SPEC, _));
36 // No error or warning.
37 EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
38
39 preprocess(str, expected);
40 }
41
TEST_F(VersionTest,Valid)42 TEST_F(VersionTest, Valid)
43 {
44 const char *str = "#version 200\n";
45 const char *expected = "\n";
46
47 using testing::_;
48 EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200, SH_GLES2_SPEC, _));
49 // No error or warning.
50 EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
51
52 preprocess(str, expected);
53 }
54
55 // Test for Desktop GL Shaders
TEST_F(VersionTest,GLSpec)56 TEST_F(VersionTest, GLSpec)
57 {
58 const char *str = "#version 330 core\n";
59 const char *expected = "\n";
60
61 using testing::_;
62 EXPECT_CALL(mDirectiveHandler,
63 handleVersion(pp::SourceLocation(0, 1), 330, SH_GL_COMPATIBILITY_SPEC, _));
64 // No error or warning.
65 EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
66
67 preprocess(str, expected, SH_GL_COMPATIBILITY_SPEC);
68 }
69
TEST_F(VersionTest,CommentsIgnored)70 TEST_F(VersionTest, CommentsIgnored)
71 {
72 const char *str =
73 "/*foo*/"
74 "#"
75 "/*foo*/"
76 "version"
77 "/*foo*/"
78 "200"
79 "/*foo*/"
80 "//foo"
81 "\n";
82 const char *expected = "\n";
83
84 using testing::_;
85 EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200, SH_GLES2_SPEC, _));
86 // No error or warning.
87 EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
88
89 preprocess(str, expected);
90 }
91
TEST_F(VersionTest,MissingNewline)92 TEST_F(VersionTest, MissingNewline)
93 {
94 const char *str = "#version 200";
95 const char *expected = "";
96
97 using testing::_;
98 // Directive successfully parsed.
99 EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 1), 200, SH_GLES2_SPEC, _));
100 // Error reported about EOF.
101 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_EOF_IN_DIRECTIVE, _, _));
102
103 preprocess(str, expected);
104 }
105
TEST_F(VersionTest,AfterComments)106 TEST_F(VersionTest, AfterComments)
107 {
108 const char *str =
109 "/* block comment acceptable */\n"
110 "// line comment acceptable\n"
111 "#version 200\n";
112 const char *expected = "\n\n\n";
113
114 using testing::_;
115 // Directive successfully parsed.
116 EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 3), 200, SH_GLES2_SPEC, _));
117 // No error or warning.
118 EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
119
120 preprocess(str, expected);
121 }
122
TEST_F(VersionTest,AfterWhitespace)123 TEST_F(VersionTest, AfterWhitespace)
124 {
125 const char *str =
126 "\n"
127 "\n"
128 "#version 200\n";
129 const char *expected = "\n\n\n";
130
131 using testing::_;
132 // Directive successfully parsed.
133 EXPECT_CALL(mDirectiveHandler, handleVersion(pp::SourceLocation(0, 3), 200, SH_GLES2_SPEC, _));
134 // No error or warning.
135 EXPECT_CALL(mDiagnostics, print(_, _, _)).Times(0);
136
137 preprocess(str, expected);
138 }
139
TEST_F(VersionTest,AfterValidToken)140 TEST_F(VersionTest, AfterValidToken)
141 {
142 const char *str =
143 "foo\n"
144 "#version 200\n";
145
146 using testing::_;
147 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
148 pp::SourceLocation(0, 2), _));
149
150 preprocess(str);
151 }
152
TEST_F(VersionTest,AfterInvalidToken)153 TEST_F(VersionTest, AfterInvalidToken)
154 {
155 const char *str =
156 "$\n"
157 "#version 200\n";
158
159 using testing::_;
160 EXPECT_CALL(mDiagnostics,
161 print(pp::Diagnostics::PP_INVALID_CHARACTER, pp::SourceLocation(0, 1), "$"));
162 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
163 pp::SourceLocation(0, 2), _));
164
165 preprocess(str);
166 }
167
TEST_F(VersionTest,AfterValidDirective)168 TEST_F(VersionTest, AfterValidDirective)
169 {
170 const char *str =
171 "#\n"
172 "#version 200\n";
173
174 using testing::_;
175 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
176 pp::SourceLocation(0, 2), _));
177
178 preprocess(str);
179 }
180
TEST_F(VersionTest,AfterInvalidDirective)181 TEST_F(VersionTest, AfterInvalidDirective)
182 {
183 const char *str =
184 "#foo\n"
185 "#version 200\n";
186
187 using testing::_;
188 EXPECT_CALL(mDiagnostics,
189 print(pp::Diagnostics::PP_DIRECTIVE_INVALID_NAME, pp::SourceLocation(0, 1), "foo"));
190 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
191 pp::SourceLocation(0, 2), _));
192
193 preprocess(str);
194 }
195
TEST_F(VersionTest,AfterExcludedBlock)196 TEST_F(VersionTest, AfterExcludedBlock)
197 {
198 const char *str =
199 "#if 0\n"
200 "foo\n"
201 "#endif\n"
202 "#version 200\n";
203
204 using testing::_;
205 EXPECT_CALL(mDiagnostics, print(pp::Diagnostics::PP_VERSION_NOT_FIRST_STATEMENT,
206 pp::SourceLocation(0, 4), _));
207
208 preprocess(str);
209 }
210
211 struct VersionTestParam
212 {
213 const char *str;
214 pp::Diagnostics::ID id;
215 };
216
217 class InvalidVersionTest : public VersionTest, public testing::WithParamInterface<VersionTestParam>
218 {};
219
TEST_P(InvalidVersionTest,Identified)220 TEST_P(InvalidVersionTest, Identified)
221 {
222 VersionTestParam param = GetParam();
223 const char *expected = "\n";
224
225 using testing::_;
226 // No handleVersion call.
227 EXPECT_CALL(mDirectiveHandler, handleVersion(_, _, _, _)).Times(0);
228 // Invalid version directive call.
229 EXPECT_CALL(mDiagnostics, print(param.id, pp::SourceLocation(0, 1), _));
230
231 preprocess(param.str, expected);
232 }
233
234 static const VersionTestParam kParams[] = {
235 {"#version\n", pp::Diagnostics::PP_INVALID_VERSION_DIRECTIVE},
236 {"#version foo\n", pp::Diagnostics::PP_INVALID_VERSION_NUMBER},
237 {"#version 100 foo\n", pp::Diagnostics::PP_UNEXPECTED_TOKEN},
238 {"#version 0xffffffff\n", pp::Diagnostics::PP_INTEGER_OVERFLOW}};
239
240 INSTANTIATE_TEST_SUITE_P(All, InvalidVersionTest, testing::ValuesIn(kParams));
241
242 } // namespace angle
243