1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <unittest/unittest.h>
6
7 #include <locale.h>
8
9 #include <fidl/flat_ast.h>
10 #include <fidl/lexer.h>
11 #include <fidl/parser.h>
12 #include <fidl/source_file.h>
13
14 #include "test_library.h"
15
16 namespace {
17
18 // Test that an invalid compound identifier fails parsing. Regression
19 // test for FIDL-263.
bad_compound_identifier_test()20 bool bad_compound_identifier_test() {
21 BEGIN_TEST;
22
23 // The leading 0 in the library name causes parsing an Identifier
24 // to fail, and then parsing a CompoundIdentifier to fail.
25 TestLibrary library(R"FIDL(
26 library 0fidl.test.badcompoundidentifier;
27 )FIDL");
28 EXPECT_FALSE(library.Compile());
29 auto errors = library.errors();
30 ASSERT_EQ(errors.size(), 1);
31 ASSERT_STR_STR(errors[0].c_str(), "unexpected token");
32
33 END_TEST;
34 }
35
36 // Test that otherwise reserved words can be appropriarely parsed when context
37 // is clear.
parsing_reserved_words_in_struct_test()38 bool parsing_reserved_words_in_struct_test() {
39 BEGIN_TEST;
40
41 TestLibrary library(R"FIDL(
42 library example;
43
44 struct InStruct {
45 bool as;
46 bool library;
47 bool using;
48
49 bool array;
50 bool handle;
51 bool request;
52 bool string;
53 bool vector;
54
55 bool bool;
56 bool int8;
57 bool int16;
58 bool int32;
59 bool int64;
60 bool uint8;
61 bool uint16;
62 bool uint32;
63 bool uint64;
64 bool float32;
65 bool float64;
66
67 bool true;
68 bool false;
69
70 bool reserved;
71 };
72 )FIDL");
73 EXPECT_TRUE(library.Compile());
74
75 END_TEST;
76 }
77
78 // Test that otherwise reserved words can be appropriarely parsed when context
79 // is clear.
parsing_reserved_words_in_interface_test()80 bool parsing_reserved_words_in_interface_test() {
81 BEGIN_TEST;
82
83 TestLibrary library(R"FIDL(
84 library example;
85
86 interface InInterface {
87 01: as(bool as);
88 02: library(bool library);
89 03: using(bool using);
90
91 11: array(bool array);
92 12: handle(bool handle);
93 13: request(bool request);
94 14: string(bool string);
95 15: vector(bool vector);
96
97 31: bool(bool bool);
98 32: int8(bool int8);
99 33: int16(bool int16);
100 34: int32(bool int32);
101 35: int64(bool int64);
102 36: uint8(bool uint8);
103 37: uint16(bool uint16);
104 38: uint32(bool uint32);
105 39: uint64(bool uint64);
106 40: float32(bool float32);
107 41: float64(bool float64);
108
109 51: true(bool true);
110 52: false(bool false);
111
112 61: reserved(bool reserved);
113 };
114 )FIDL");
115 EXPECT_TRUE(library.Compile());
116
117 END_TEST;
118 }
119
bad_char_at_sign_test()120 bool bad_char_at_sign_test() {
121 BEGIN_TEST;
122
123 TestLibrary library(R"FIDL(
124 library test;
125
126 struct Test {
127 uint8 @uint8;
128 };
129 )FIDL");
130 EXPECT_FALSE(library.Compile());
131 auto errors = library.errors();
132 ASSERT_EQ(errors.size(), 1);
133 ASSERT_STR_STR(errors[0].c_str(), "invalid character '@'");
134
135 END_TEST;
136 }
137
bad_char_slash_test()138 bool bad_char_slash_test() {
139 BEGIN_TEST;
140
141 TestLibrary library(R"FIDL(
142 library test;
143
144 struct Test / {
145 uint8 uint8;
146 };
147 )FIDL");
148 EXPECT_FALSE(library.Compile());
149 auto errors = library.errors();
150 ASSERT_EQ(errors.size(), 1);
151 ASSERT_STR_STR(errors[0].c_str(), "invalid character '/'");
152
153 END_TEST;
154 }
155
bad_identifier_test()156 bool bad_identifier_test() {
157 BEGIN_TEST;
158
159 TestLibrary library(R"FIDL(
160 library test;
161
162 struct test_ {
163 uint8 uint8;
164 };
165 )FIDL");
166 EXPECT_FALSE(library.Compile());
167 auto errors = library.errors();
168 ASSERT_EQ(errors.size(), 1);
169 ASSERT_STR_STR(errors[0].c_str(), "invalid identifier 'test_'");
170
171 END_TEST;
172 }
173
174 class LocaleSwapper {
175 public:
LocaleSwapper(const char * new_locale)176 explicit LocaleSwapper(const char* new_locale) {
177 old_locale_ = setlocale(LC_ALL, new_locale);
178 }
~LocaleSwapper()179 ~LocaleSwapper() {
180 setlocale(LC_ALL, old_locale_);
181 }
182
183 private:
184 const char* old_locale_;
185 };
186
invalid_character_test(void)187 static bool invalid_character_test(void) {
188 BEGIN_TEST;
189
190 class InvalidCharacterLibrary : public TestLibrary {
191 public:
192 InvalidCharacterLibrary()
193 : TestLibrary("invalid.character.fidl", R"FIDL(
194 library fidl.test.maxbytes;
195
196 // This is all alphanumeric in the appropriate locale, but not a valid
197 // identifier.
198 struct ß {
199 int32 x;
200 };
201
202 )FIDL") {}
203 } test_library;
204
205 {
206 LocaleSwapper("de_DE.iso88591");
207 EXPECT_FALSE(test_library.Compile());
208 }
209
210 const auto& errors = test_library.errors();
211 EXPECT_NE(errors.size(), 0);
212 ASSERT_STR_STR(errors[0].data(), "invalid character");
213
214 END_TEST;
215 }
216
empty_struct_test()217 bool empty_struct_test() {
218 BEGIN_TEST;
219
220 TestLibrary library("empty_struct.fidl", R"FIDL(
221 library fidl.test.emptystruct;
222
223 struct Empty {
224 };
225
226 )FIDL");
227 EXPECT_TRUE(library.Compile());
228
229 END_TEST;
230 }
231
232 } // namespace
233
234 BEGIN_TEST_CASE(parser_tests);
235 RUN_TEST(bad_compound_identifier_test);
236 RUN_TEST(parsing_reserved_words_in_struct_test);
237 RUN_TEST(parsing_reserved_words_in_interface_test);
238 RUN_TEST(bad_char_at_sign_test);
239 RUN_TEST(bad_char_slash_test);
240 RUN_TEST(bad_identifier_test);
241 RUN_TEST(invalid_character_test);
242 RUN_TEST(empty_struct_test);
243 END_TEST_CASE(parser_tests);
244