1 // Copyright (c) 2015-2016 The Khronos Group Inc.
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 <string>
16 #include <utility>
17 #include <vector>
18 
19 #include "gmock/gmock.h"
20 #include "test/test_fixture.h"
21 #include "test/unit_spirv.h"
22 
23 namespace spvtools {
24 namespace {
25 
26 using ::testing::Eq;
27 
TEST(TextLiteral,GoodI32)28 TEST(TextLiteral, GoodI32) {
29   spv_literal_t l;
30 
31   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("-0", &l));
32   EXPECT_EQ(SPV_LITERAL_TYPE_INT_32, l.type);
33   EXPECT_EQ(0, l.value.i32);
34 
35   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("-2147483648", &l));
36   EXPECT_EQ(SPV_LITERAL_TYPE_INT_32, l.type);
37   EXPECT_EQ((-2147483647L - 1), l.value.i32);
38 }
39 
TEST(TextLiteral,GoodU32)40 TEST(TextLiteral, GoodU32) {
41   spv_literal_t l;
42 
43   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("0", &l));
44   EXPECT_EQ(SPV_LITERAL_TYPE_UINT_32, l.type);
45   EXPECT_EQ(0, l.value.i32);
46 
47   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("4294967295", &l));
48   EXPECT_EQ(SPV_LITERAL_TYPE_UINT_32, l.type);
49   EXPECT_EQ(4294967295, l.value.u32);
50 }
51 
TEST(TextLiteral,GoodI64)52 TEST(TextLiteral, GoodI64) {
53   spv_literal_t l;
54 
55   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("-2147483649", &l));
56   EXPECT_EQ(SPV_LITERAL_TYPE_INT_64, l.type);
57   EXPECT_EQ(-2147483649LL, l.value.i64);
58 }
59 
TEST(TextLiteral,GoodU64)60 TEST(TextLiteral, GoodU64) {
61   spv_literal_t l;
62 
63   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("4294967296", &l));
64   EXPECT_EQ(SPV_LITERAL_TYPE_UINT_64, l.type);
65   EXPECT_EQ(4294967296u, l.value.u64);
66 }
67 
TEST(TextLiteral,GoodFloat)68 TEST(TextLiteral, GoodFloat) {
69   spv_literal_t l;
70 
71   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("1.0", &l));
72   EXPECT_EQ(SPV_LITERAL_TYPE_FLOAT_32, l.type);
73   EXPECT_EQ(1.0, l.value.f);
74 
75   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("1.5", &l));
76   EXPECT_EQ(SPV_LITERAL_TYPE_FLOAT_32, l.type);
77   EXPECT_EQ(1.5, l.value.f);
78 
79   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral("-.25", &l));
80   EXPECT_EQ(SPV_LITERAL_TYPE_FLOAT_32, l.type);
81   EXPECT_EQ(-.25, l.value.f);
82 }
83 
TEST(TextLiteral,BadString)84 TEST(TextLiteral, BadString) {
85   spv_literal_t l;
86 
87   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("", &l));
88   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("-", &l));
89   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("--", &l));
90   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("1-2", &l));
91   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("123a", &l));
92   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("12.2.3", &l));
93   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("\"", &l));
94   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("\"z", &l));
95   EXPECT_EQ(SPV_FAILED_MATCH, spvTextToLiteral("a\"", &l));
96 }
97 
98 class GoodStringTest
99     : public ::testing::TestWithParam<std::pair<const char*, const char*>> {};
100 
TEST_P(GoodStringTest,GoodStrings)101 TEST_P(GoodStringTest, GoodStrings) {
102   spv_literal_t l;
103 
104   ASSERT_EQ(SPV_SUCCESS, spvTextToLiteral(std::get<0>(GetParam()), &l));
105   EXPECT_EQ(SPV_LITERAL_TYPE_STRING, l.type);
106   EXPECT_EQ(std::get<1>(GetParam()), l.str);
107 }
108 
109 INSTANTIATE_TEST_SUITE_P(
110     TextLiteral, GoodStringTest,
111     ::testing::ValuesIn(std::vector<std::pair<const char*, const char*>>{
112         {R"("-")", "-"},
113         {R"("--")", "--"},
114         {R"("1-2")", "1-2"},
115         {R"("123a")", "123a"},
116         {R"("12.2.3")", "12.2.3"},
117         {R"("\"")", "\""},
118         {R"("\\")", "\\"},
119         {"\"\\foo\nbar\"", "foo\nbar"},
120         {"\"\\foo\\\nbar\"", "foo\nbar"},
121         {"\"\xE4\xBA\xB2\"", "\xE4\xBA\xB2"},
122         {"\"\\\xE4\xBA\xB2\"", "\xE4\xBA\xB2"},
123         {"\"this \\\" and this \\\\ and \\\xE4\xBA\xB2\"",
124          "this \" and this \\ and \xE4\xBA\xB2"}}));
125 
TEST(TextLiteral,StringTooLong)126 TEST(TextLiteral, StringTooLong) {
127   spv_literal_t l;
128   std::string too_long =
129       std::string("\"") +
130       std::string(SPV_LIMIT_LITERAL_STRING_BYTES_MAX + 1, 'a') + "\"";
131   EXPECT_EQ(SPV_ERROR_OUT_OF_MEMORY, spvTextToLiteral(too_long.data(), &l));
132 }
133 
TEST(TextLiteral,GoodLongString)134 TEST(TextLiteral, GoodLongString) {
135   spv_literal_t l;
136   // The universal limit of 65535 Unicode characters might make this
137   // fail validation, since SPV_LIMIT_LITERAL_STRING_BYTES_MAX is 4*65535.
138   // However, as an implementation detail, we'll allow the assembler
139   // to parse it.  Otherwise we'd have to scan the string for valid UTF-8
140   // characters.
141   std::string unquoted(SPV_LIMIT_LITERAL_STRING_BYTES_MAX, 'a');
142   std::string good_long = std::string("\"") + unquoted + "\"";
143   EXPECT_EQ(SPV_SUCCESS, spvTextToLiteral(good_long.data(), &l));
144   EXPECT_EQ(SPV_LITERAL_TYPE_STRING, l.type);
145   EXPECT_EQ(unquoted.data(), l.str);
146 }
147 
TEST(TextLiteral,GoodUTF8String)148 TEST(TextLiteral, GoodUTF8String) {
149   const std::string unquoted =
150       spvtest::MakeLongUTF8String(SPV_LIMIT_LITERAL_STRING_UTF8_CHARS_MAX);
151   const std::string good_long = std::string("\"") + unquoted + "\"";
152   spv_literal_t l;
153   EXPECT_EQ(SPV_SUCCESS, spvTextToLiteral(good_long.data(), &l));
154   EXPECT_EQ(SPV_LITERAL_TYPE_STRING, l.type);
155   EXPECT_EQ(unquoted.data(), l.str);
156 }
157 
158 // A test case for parsing literal numbers.
159 struct TextLiteralCase {
160   uint32_t bitwidth;
161   const char* text;
162   bool is_signed;
163   bool success;
164   std::vector<uint32_t> expected_values;
165 };
166 
167 using IntegerTest =
168     spvtest::TextToBinaryTestBase<::testing::TestWithParam<TextLiteralCase>>;
169 
successfulEncode(const TextLiteralCase & test,IdTypeClass type)170 std::vector<uint32_t> successfulEncode(const TextLiteralCase& test,
171                                        IdTypeClass type) {
172   spv_instruction_t inst;
173   std::string message;
174   auto capture_message = [&message](spv_message_level_t, const char*,
175                                     const spv_position_t&,
176                                     const char* m) { message = m; };
177   IdType expected_type{test.bitwidth, test.is_signed, type};
178   EXPECT_EQ(SPV_SUCCESS,
179             AssemblyContext(nullptr, capture_message)
180                 .binaryEncodeNumericLiteral(test.text, SPV_ERROR_INVALID_TEXT,
181                                             expected_type, &inst))
182       << message;
183   return inst.words;
184 }
185 
failedEncode(const TextLiteralCase & test,IdTypeClass type)186 std::string failedEncode(const TextLiteralCase& test, IdTypeClass type) {
187   spv_instruction_t inst;
188   std::string message;
189   auto capture_message = [&message](spv_message_level_t, const char*,
190                                     const spv_position_t&,
191                                     const char* m) { message = m; };
192   IdType expected_type{test.bitwidth, test.is_signed, type};
193   EXPECT_EQ(SPV_ERROR_INVALID_TEXT,
194             AssemblyContext(nullptr, capture_message)
195                 .binaryEncodeNumericLiteral(test.text, SPV_ERROR_INVALID_TEXT,
196                                             expected_type, &inst));
197   return message;
198 }
199 
TEST_P(IntegerTest,IntegerBounds)200 TEST_P(IntegerTest, IntegerBounds) {
201   if (GetParam().success) {
202     EXPECT_THAT(successfulEncode(GetParam(), IdTypeClass::kScalarIntegerType),
203                 Eq(GetParam().expected_values));
204   } else {
205     std::stringstream ss;
206     ss << "Integer " << GetParam().text << " does not fit in a "
207        << GetParam().bitwidth << "-bit "
208        << (GetParam().is_signed ? "signed" : "unsigned") << " integer";
209     EXPECT_THAT(failedEncode(GetParam(), IdTypeClass::kScalarIntegerType),
210                 Eq(ss.str()));
211   }
212 }
213 
214 // Four nicely named methods for making TextLiteralCase values.
215 // Their names have underscores in some places to make it easier
216 // to read the table that follows.
Make_Ok__Signed(uint32_t bitwidth,const char * text,std::vector<uint32_t> encoding)217 TextLiteralCase Make_Ok__Signed(uint32_t bitwidth, const char* text,
218                                 std::vector<uint32_t> encoding) {
219   return TextLiteralCase{bitwidth, text, true, true, encoding};
220 }
Make_Ok__Unsigned(uint32_t bitwidth,const char * text,std::vector<uint32_t> encoding)221 TextLiteralCase Make_Ok__Unsigned(uint32_t bitwidth, const char* text,
222                                   std::vector<uint32_t> encoding) {
223   return TextLiteralCase{bitwidth, text, false, true, encoding};
224 }
Make_Bad_Signed(uint32_t bitwidth,const char * text)225 TextLiteralCase Make_Bad_Signed(uint32_t bitwidth, const char* text) {
226   return TextLiteralCase{bitwidth, text, true, false, {}};
227 }
Make_Bad_Unsigned(uint32_t bitwidth,const char * text)228 TextLiteralCase Make_Bad_Unsigned(uint32_t bitwidth, const char* text) {
229   return TextLiteralCase{bitwidth, text, false, false, {}};
230 }
231 
232 // clang-format off
233 INSTANTIATE_TEST_SUITE_P(
234     DecimalIntegers, IntegerTest,
235     ::testing::ValuesIn(std::vector<TextLiteralCase>{
236         // Check max value and overflow value for 1-bit numbers.
237         Make_Ok__Signed(1, "0", {0}),
238         Make_Ok__Unsigned(1, "1", {1}),
239         Make_Bad_Signed(1, "1"),
240         Make_Bad_Unsigned(1, "2"),
241 
242         // Check max value and overflow value for 2-bit numbers.
243         Make_Ok__Signed(2, "1", {1}),
244         Make_Ok__Unsigned(2, "3", {3}),
245         Make_Bad_Signed(2, "2"),
246         Make_Bad_Unsigned(2, "4"),
247 
248         // Check max negative value and overflow value for signed
249         // 1- and 2-bit numbers.  Signed negative numbers are sign-extended.
250         Make_Ok__Signed(1, "-0", {uint32_t(0)}),
251         Make_Ok__Signed(1, "-1", {uint32_t(-1)}),
252         Make_Ok__Signed(2, "-0", {0}),
253         Make_Ok__Signed(2, "-1", {uint32_t(-1)}),
254         Make_Ok__Signed(2, "-2", {uint32_t(-2)}),
255         Make_Bad_Signed(2, "-3"),
256 
257         Make_Bad_Unsigned(2, "2224323424242424"),
258         Make_Ok__Unsigned(16, "65535", {0xFFFF}),
259         Make_Bad_Unsigned(16, "65536"),
260         Make_Bad_Signed(16, "65535"),
261         Make_Ok__Signed(16, "32767", {0x7FFF}),
262         Make_Ok__Signed(16, "-32768", {0xFFFF8000}),
263 
264         // Check values around 32-bits in magnitude.
265         Make_Ok__Unsigned(33, "4294967296", {0, 1}),
266         Make_Ok__Unsigned(33, "4294967297", {1, 1}),
267         Make_Bad_Unsigned(33, "8589934592"),
268         Make_Bad_Signed(33, "4294967296"),
269         Make_Ok__Signed(33, "-4294967296", {0x0, 0xFFFFFFFF}),
270         Make_Ok__Unsigned(64, "4294967296", {0, 1}),
271         Make_Ok__Unsigned(64, "4294967297", {1, 1}),
272 
273         // Check max value and overflow value for 64-bit numbers.
274         Make_Ok__Signed(64, "9223372036854775807", {0xffffffff, 0x7fffffff}),
275         Make_Bad_Signed(64, "9223372036854775808"),
276         Make_Ok__Unsigned(64, "9223372036854775808", {0x00000000, 0x80000000}),
277         Make_Ok__Unsigned(64, "18446744073709551615", {0xffffffff, 0xffffffff}),
278         Make_Ok__Signed(64, "-9223372036854775808", {0x00000000, 0x80000000}),
279 
280     }));
281 // clang-format on
282 
283 using IntegerLeadingMinusTest =
284     spvtest::TextToBinaryTestBase<::testing::TestWithParam<TextLiteralCase>>;
285 
TEST_P(IntegerLeadingMinusTest,CantHaveLeadingMinusOnUnsigned)286 TEST_P(IntegerLeadingMinusTest, CantHaveLeadingMinusOnUnsigned) {
287   EXPECT_FALSE(GetParam().success);
288   EXPECT_THAT(failedEncode(GetParam(), IdTypeClass::kScalarIntegerType),
289               Eq("Cannot put a negative number in an unsigned literal"));
290 }
291 
292 // clang-format off
293 INSTANTIATE_TEST_SUITE_P(
294     DecimalAndHexIntegers, IntegerLeadingMinusTest,
295     ::testing::ValuesIn(std::vector<TextLiteralCase>{
296         // Unsigned numbers never allow a leading minus sign.
297         Make_Bad_Unsigned(16, "-0"),
298         Make_Bad_Unsigned(16, "-0x0"),
299         Make_Bad_Unsigned(16, "-0x1"),
300         Make_Bad_Unsigned(32, "-0"),
301         Make_Bad_Unsigned(32, "-0x0"),
302         Make_Bad_Unsigned(32, "-0x1"),
303         Make_Bad_Unsigned(64, "-0"),
304         Make_Bad_Unsigned(64, "-0x0"),
305         Make_Bad_Unsigned(64, "-0x1"),
306     }));
307 
308 // clang-format off
309 INSTANTIATE_TEST_SUITE_P(
310     HexIntegers, IntegerTest,
311     ::testing::ValuesIn(std::vector<TextLiteralCase>{
312         // Check 0x and 0X prefices.
313         Make_Ok__Signed(16, "0x1234", {0x1234}),
314         Make_Ok__Signed(16, "0X1234", {0x1234}),
315 
316         // Check 1-bit numbers
317         Make_Ok__Signed(1, "0x0", {0}),
318         Make_Ok__Signed(1, "0x1", {uint32_t(-1)}),
319         Make_Ok__Unsigned(1, "0x0", {0}),
320         Make_Ok__Unsigned(1, "0x1", {1}),
321         Make_Bad_Signed(1, "0x2"),
322         Make_Bad_Unsigned(1, "0x2"),
323 
324         // Check 2-bit numbers
325         Make_Ok__Signed(2, "0x0", {0}),
326         Make_Ok__Signed(2, "0x1", {1}),
327         Make_Ok__Signed(2, "0x2", {uint32_t(-2)}),
328         Make_Ok__Signed(2, "0x3", {uint32_t(-1)}),
329         Make_Ok__Unsigned(2, "0x0", {0}),
330         Make_Ok__Unsigned(2, "0x1", {1}),
331         Make_Ok__Unsigned(2, "0x2", {2}),
332         Make_Ok__Unsigned(2, "0x3", {3}),
333         Make_Bad_Signed(2, "0x4"),
334         Make_Bad_Unsigned(2, "0x4"),
335 
336         // Check 8-bit numbers
337         Make_Ok__Signed(8, "0x7f", {0x7f}),
338         Make_Ok__Signed(8, "0x80", {0xffffff80}),
339         Make_Ok__Unsigned(8, "0x80", {0x80}),
340         Make_Ok__Unsigned(8, "0xff", {0xff}),
341         Make_Bad_Signed(8, "0x100"),
342         Make_Bad_Unsigned(8, "0x100"),
343 
344         // Check 16-bit numbers
345         Make_Ok__Signed(16, "0x7fff", {0x7fff}),
346         Make_Ok__Signed(16, "0x8000", {0xffff8000}),
347         Make_Ok__Unsigned(16, "0x8000", {0x8000}),
348         Make_Ok__Unsigned(16, "0xffff", {0xffff}),
349         Make_Bad_Signed(16, "0x10000"),
350         Make_Bad_Unsigned(16, "0x10000"),
351 
352         // Check 32-bit numbers
353         Make_Ok__Signed(32, "0x7fffffff", {0x7fffffff}),
354         Make_Ok__Signed(32, "0x80000000", {0x80000000}),
355         Make_Ok__Unsigned(32, "0x80000000", {0x80000000}),
356         Make_Ok__Unsigned(32, "0xffffffff", {0xffffffff}),
357         Make_Bad_Signed(32, "0x100000000"),
358         Make_Bad_Unsigned(32, "0x100000000"),
359 
360         // Check 48-bit numbers
361         Make_Ok__Unsigned(48, "0x7ffffffff", {0xffffffff, 7}),
362         Make_Ok__Unsigned(48, "0x800000000", {0, 8}),
363         Make_Ok__Signed(48, "0x7fffffffffff", {0xffffffff, 0x7fff}),
364         Make_Ok__Signed(48, "0x800000000000", {0, 0xffff8000}),
365         Make_Bad_Signed(48, "0x1000000000000"),
366         Make_Bad_Unsigned(48, "0x1000000000000"),
367 
368         // Check 64-bit numbers
369         Make_Ok__Signed(64, "0x7fffffffffffffff", {0xffffffff, 0x7fffffff}),
370         Make_Ok__Signed(64, "0x8000000000000000", {0x00000000, 0x80000000}),
371         Make_Ok__Unsigned(64, "0x7fffffffffffffff", {0xffffffff, 0x7fffffff}),
372         Make_Ok__Unsigned(64, "0x8000000000000000", {0x00000000, 0x80000000}),
373     }));
374 // clang-format on
375 
TEST(OverflowIntegerParse,Decimal)376 TEST(OverflowIntegerParse, Decimal) {
377   std::string signed_input = "-18446744073709551616";
378   std::string expected_message0 =
379       "Invalid signed integer literal: " + signed_input;
380   EXPECT_THAT(failedEncode(Make_Bad_Signed(64, signed_input.c_str()),
381                            IdTypeClass::kScalarIntegerType),
382               Eq(expected_message0));
383 
384   std::string unsigned_input = "18446744073709551616";
385   std::string expected_message1 =
386       "Invalid unsigned integer literal: " + unsigned_input;
387   EXPECT_THAT(failedEncode(Make_Bad_Unsigned(64, unsigned_input.c_str()),
388                            IdTypeClass::kScalarIntegerType),
389               Eq(expected_message1));
390 
391   // TODO(dneto): When the given number doesn't have a leading sign,
392   // we say we're trying to parse an unsigned number, even when the caller
393   // asked for a signed number.  This is kind of weird, but it's an
394   // artefact of how we do the parsing.
395   EXPECT_THAT(failedEncode(Make_Bad_Signed(64, unsigned_input.c_str()),
396                            IdTypeClass::kScalarIntegerType),
397               Eq(expected_message1));
398 }
399 
TEST(OverflowIntegerParse,Hex)400 TEST(OverflowIntegerParse, Hex) {
401   std::string input = "0x10000000000000000";
402   std::string expected_message = "Invalid unsigned integer literal: " + input;
403   EXPECT_THAT(failedEncode(Make_Bad_Signed(64, input.c_str()),
404                            IdTypeClass::kScalarIntegerType),
405               Eq(expected_message));
406   EXPECT_THAT(failedEncode(Make_Bad_Unsigned(64, input.c_str()),
407                            IdTypeClass::kScalarIntegerType),
408               Eq(expected_message));
409 }
410 
411 }  // namespace
412 }  // namespace spvtools
413