1 /*
2 * Copyright (C) 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "aidl.h"
18
19 #include <android-base/stringprintf.h>
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 #include <format>
24 #include <map>
25 #include <memory>
26 #include <set>
27 #include <string>
28 #include <unordered_map>
29 #include <unordered_set>
30 #include <variant>
31 #include <vector>
32
33 #include "aidl_checkapi.h"
34 #include "aidl_dumpapi.h"
35 #include "aidl_language.h"
36 #include "aidl_to_cpp.h"
37 #include "aidl_to_cpp_common.h"
38 #include "aidl_to_java.h"
39 #include "aidl_to_ndk.h"
40 #include "aidl_to_rust.h"
41 #include "comments.h"
42 #include "logging.h"
43 #include "options.h"
44 #include "parser.h"
45 #include "preprocess.h"
46 #include "tests/fake_io_delegate.h"
47
48 using android::aidl::test::FakeIoDelegate;
49 using android::base::StringPrintf;
50 using std::map;
51 using std::set;
52 using std::string;
53 using std::unique_ptr;
54 using std::variant;
55 using std::vector;
56 using testing::HasSubstr;
57 using testing::TestParamInfo;
58 using testing::internal::CaptureStderr;
59 using testing::internal::GetCapturedStderr;
60
61 namespace android {
62 namespace aidl {
63 namespace {
64
65 const char kExpectedDepFileContents[] =
66 R"(place/for/output/p/IFoo.java : \
67 p/IFoo.aidl
68
69 p/IFoo.aidl :
70 )";
71
72 const char kExpectedNinjaDepFileContents[] =
73 R"(place/for/output/p/IFoo.java : \
74 p/IFoo.aidl
75 )";
76
77 const char kExpectedParcelableDeclarationDepFileContents[] =
78 R"( : \
79 p/Foo.aidl
80
81 p/Foo.aidl :
82 )";
83
84 const char kExpectedStructuredParcelableDepFileContents[] =
85 R"(place/for/output/p/Foo.java : \
86 p/Foo.aidl
87
88 p/Foo.aidl :
89 )";
90
91 } // namespace
92
93 const string INVALID_INT8_VALUE = "Invalid type specifier for an int8 literal";
94 const string INVALID_FLOAT_VALUE = "Invalid type specifier for a literal float";
95 const string INVALID_OPERATION = "Cannot perform operation";
96
97 class AidlTest : public ::testing::TestWithParam<Options::Language> {
98 protected:
Parse(const string & path,const string & contents,AidlTypenames & typenames_,Options::Language lang,AidlError * error=nullptr,const vector<string> additional_arguments={})99 AidlDefinedType* Parse(const string& path, const string& contents, AidlTypenames& typenames_,
100 Options::Language lang, AidlError* error = nullptr,
101 const vector<string> additional_arguments = {}) {
102 io_delegate_.SetFileContents(path, contents);
103 vector<string> args;
104 args.emplace_back("aidl");
105 args.emplace_back("--min_sdk_version=current");
106 args.emplace_back("--lang=" + to_string(lang));
107 for (const string& s : additional_arguments) {
108 args.emplace_back(s);
109 }
110 for (const string& f : preprocessed_files_) {
111 args.emplace_back("--preprocessed=" + f);
112 }
113 args.emplace_back("--include=.");
114 for (const string& i : import_paths_) {
115 args.emplace_back("--include=" + i);
116 }
117 args.emplace_back(path);
118 Options options = Options::From(args);
119 vector<string> imported_files;
120 ImportResolver import_resolver{io_delegate_, path, import_paths_};
121 AidlError actual_error = ::android::aidl::internals::load_and_validate_aidl(
122 path, options, io_delegate_, &typenames_, &imported_files);
123
124 if (error != nullptr) {
125 *error = actual_error;
126 }
127
128 if (actual_error != AidlError::OK) {
129 return nullptr;
130 }
131
132 const auto& defined_types = typenames_.MainDocument().DefinedTypes();
133 EXPECT_EQ(1ul, defined_types.size());
134
135 return defined_types.front().get();
136 }
137
EvaluateInvalidAssignment(string content,string expected_stderr,AidlTypenames & typenames_,Options::Language lang)138 void EvaluateInvalidAssignment(string content, string expected_stderr, AidlTypenames& typenames_,
139 Options::Language lang) {
140 AidlError error;
141 CaptureStderr();
142 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", content, typenames_, lang, &error));
143 EXPECT_THAT(GetCapturedStderr(), HasSubstr(expected_stderr));
144 };
145
EvaluateValidAssignment(string content,string expected_stderr,AidlTypenames & typenames_,Options::Language lang)146 void EvaluateValidAssignment(string content, string expected_stderr, AidlTypenames& typenames_,
147 Options::Language lang) {
148 AidlError error;
149 CaptureStderr();
150 EXPECT_NE(nullptr, Parse("a/IFoo.aidl", content, typenames_, lang, &error));
151 EXPECT_THAT(GetCapturedStderr(), HasSubstr(expected_stderr));
152 };
153
GetLanguage()154 Options::Language GetLanguage() { return GetParam(); }
155
156 FakeIoDelegate io_delegate_;
157 vector<string> preprocessed_files_;
158 set<string> import_paths_;
159 AidlTypenames typenames_;
160 };
161
162 // Instantiate the AidlTest parameterized suite, calling all of the TEST_P
163 // tests with each of the supported languages as a parameter.
164 INSTANTIATE_TEST_SUITE_P(AidlTestSuite, AidlTest,
165 testing::Values(Options::Language::CPP, Options::Language::JAVA,
166 Options::Language::NDK, Options::Language::RUST),
__anon078f757c0202(const testing::TestParamInfo<Options::Language>& info) 167 [](const testing::TestParamInfo<Options::Language>& info) {
168 return to_string(info.param);
169 });
170
TEST_P(AidlTest,AcceptMissingPackage)171 TEST_P(AidlTest, AcceptMissingPackage) {
172 EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { }", typenames_, GetLanguage()));
173 }
174
TEST_P(AidlTest,EndsInSingleLineComment)175 TEST_P(AidlTest, EndsInSingleLineComment) {
176 EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { } // foo", typenames_, GetLanguage()));
177 }
178
TEST_P(AidlTest,InterfaceRequiresCorrectPath)179 TEST_P(AidlTest, InterfaceRequiresCorrectPath) {
180 const string expected_stderr =
181 "ERROR: a/Foo.aidl:1.11-21: IBar should be declared in a file called a/IBar.aidl\n";
182 const std::string file_contents = "package a; interface IBar {}";
183 CaptureStderr();
184 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", file_contents, typenames_, GetLanguage()));
185 EXPECT_EQ(expected_stderr, GetCapturedStderr()) << file_contents;
186 }
187
TEST_P(AidlTest,ParcelableRequiresCorrectPath)188 TEST_P(AidlTest, ParcelableRequiresCorrectPath) {
189 const string expected_stderr =
190 "ERROR: a/Foo.aidl:1.11-21: Bar should be declared in a file called a/Bar.aidl\n";
191 const std::string file_contents = "package a; interface Bar {}";
192 CaptureStderr();
193 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", file_contents, typenames_, GetLanguage()));
194 EXPECT_EQ(expected_stderr, GetCapturedStderr()) << file_contents;
195 }
196
TEST_P(AidlTest,UnstructuredParcelableRequiresCorrectPath)197 TEST_P(AidlTest, UnstructuredParcelableRequiresCorrectPath) {
198 const string expected_stderr =
199 "ERROR: a/Foo.aidl:1.22-26: Bar should be declared in a file called a/Bar.aidl\n";
200 const std::string file_contents = "package a; parcelable Bar cpp_header \"anything.h\";";
201 CaptureStderr();
202 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", file_contents, typenames_, GetLanguage()));
203 EXPECT_EQ(expected_stderr, GetCapturedStderr()) << file_contents;
204 }
205
TEST_P(AidlTest,EnumRequiresCorrectPath)206 TEST_P(AidlTest, EnumRequiresCorrectPath) {
207 const string expected_stderr =
208 "ERROR: a/Foo.aidl:1.16-20: Bar should be declared in a file called a/Bar.aidl\n";
209 const std::string file_contents = "package a; enum Bar { A, }";
210 CaptureStderr();
211 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", file_contents, typenames_, GetLanguage()));
212 EXPECT_EQ(expected_stderr, GetCapturedStderr()) << file_contents;
213 }
214
TEST_P(AidlTest,SupportOnlyOutParameters)215 TEST_P(AidlTest, SupportOnlyOutParameters) {
216 const string interface_list = "package a; interface IBar { void f(out List<String> bar); }";
217 EXPECT_NE(nullptr, Parse("a/IBar.aidl", interface_list, typenames_, GetLanguage()));
218 }
219
TEST_P(AidlTest,RejectOutParametersForIBinder)220 TEST_P(AidlTest, RejectOutParametersForIBinder) {
221 const string interface_ibinder = "package a; interface IBaz { void f(out IBinder bar); }";
222 const string expected_ibinder_stderr =
223 "ERROR: a/IBaz.aidl:1.47-51: 'bar' can't be an out parameter because IBinder can only be an "
224 "in parameter.\n";
225 CaptureStderr();
226 EXPECT_EQ(nullptr, Parse("a/IBaz.aidl", interface_ibinder, typenames_, GetLanguage()));
227 EXPECT_EQ(expected_ibinder_stderr, GetCapturedStderr());
228 }
229
TEST_P(AidlTest,RejectsOutParametersInOnewayInterface)230 TEST_P(AidlTest, RejectsOutParametersInOnewayInterface) {
231 const string oneway_interface = "package a; oneway interface IBar { void f(out int[] bar); }";
232 const string expected_stderr =
233 "ERROR: a/IBar.aidl:1.40-42: oneway method 'f' cannot have out parameters\n";
234 CaptureStderr();
235 EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_interface, typenames_, GetLanguage()));
236 EXPECT_EQ(expected_stderr, GetCapturedStderr());
237 }
238
TEST_P(AidlTest,RejectsOutParametersInOnewayMethod)239 TEST_P(AidlTest, RejectsOutParametersInOnewayMethod) {
240 const string oneway_method = "package a; interface IBar { oneway void f(out int[] bar); }";
241 const string expected_stderr =
242 "ERROR: a/IBar.aidl:1.40-42: oneway method 'f' cannot have out parameters\n";
243 CaptureStderr();
244 EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, typenames_, GetLanguage()));
245 EXPECT_EQ(expected_stderr, GetCapturedStderr());
246 }
247
TEST_P(AidlTest,RejectsOnewayNonVoidReturn)248 TEST_P(AidlTest, RejectsOnewayNonVoidReturn) {
249 const string oneway_method = "package a; interface IFoo { oneway int f(); }";
250 const string expected_stderr =
251 "ERROR: a/IFoo.aidl:1.39-41: oneway method 'f' cannot return a value\n";
252 CaptureStderr();
253 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
254 EXPECT_EQ(expected_stderr, GetCapturedStderr());
255 }
256
TEST_P(AidlTest,RejectsNullablePrimitive)257 TEST_P(AidlTest, RejectsNullablePrimitive) {
258 const string oneway_method = "package a; interface IFoo { @nullable int f(); }";
259 const string expected_stderr =
260 "ERROR: a/IFoo.aidl:1.38-42: Primitive type cannot get nullable annotation\n";
261 CaptureStderr();
262 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
263 EXPECT_EQ(expected_stderr, GetCapturedStderr());
264 }
265
TEST_P(AidlTest,AcceptNullableList)266 TEST_P(AidlTest, AcceptNullableList) {
267 const string oneway_method = "package a; interface IFoo { @nullable List<String> f(); }";
268 const string expected_stderr = "";
269 CaptureStderr();
270 EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
271 EXPECT_EQ(expected_stderr, GetCapturedStderr());
272 }
273
TEST_P(AidlTest,RejectRecursiveParcelable)274 TEST_P(AidlTest, RejectRecursiveParcelable) {
275 CaptureStderr();
276 EXPECT_EQ(nullptr, Parse("Foo.aidl", "parcelable Foo { Foo foo; }", typenames_, GetLanguage()));
277 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Foo is a recursive parcelable"));
278 }
279
TEST_P(AidlTest,RejectIndirectRecursiveParcelable)280 TEST_P(AidlTest, RejectIndirectRecursiveParcelable) {
281 io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { Foo foo; }");
282 import_paths_.emplace("");
283 CaptureStderr();
284 EXPECT_EQ(nullptr, Parse("Foo.aidl", "parcelable Foo { Bar bar; }", typenames_, GetLanguage()));
285 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Foo is a recursive parcelable"));
286 }
287
TEST_P(AidlTest,RejectRecursiveTypeEvenIfNullable)288 TEST_P(AidlTest, RejectRecursiveTypeEvenIfNullable) {
289 // Note: in native backends @nullable is mapped to non-heap wrapper like std::optional/Option<T>
290 io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { @nullable Foo foo; }");
291 import_paths_.emplace("");
292 CaptureStderr();
293 EXPECT_EQ(nullptr, Parse("Foo.aidl", "parcelable Foo { Bar bar; }", typenames_, GetLanguage()));
294 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Foo is a recursive parcelable"));
295 }
296
TEST_P(AidlTest,OkayIfRecursionInvolvesHeapType)297 TEST_P(AidlTest, OkayIfRecursionInvolvesHeapType) {
298 CaptureStderr();
299 std::string java_only_map_field;
300 if (GetLanguage() == Options::Language::JAVA) {
301 java_only_map_field = " Map<String, Foo> map;\n";
302 }
303 EXPECT_NE(nullptr, Parse("Foo.aidl",
304 "parcelable Foo {\n"
305 " List<Foo> list;\n" +
306 java_only_map_field +
307 " Foo[] arr;\n"
308 " @nullable(heap=true) Foo heap_nullable;\n"
309 "}\n",
310 typenames_, GetLanguage()));
311 EXPECT_THAT(GetCapturedStderr(), "");
312 }
313
TEST_P(AidlTest,InterfaceCanReferenceItself)314 TEST_P(AidlTest, InterfaceCanReferenceItself) {
315 CaptureStderr();
316 EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { void foo(in IFoo self); }", typenames_,
317 GetLanguage()));
318 EXPECT_THAT(GetCapturedStderr(), "");
319 }
320
TEST_P(AidlTest,HeapNullableCantApplyToOtherThanParcelables)321 TEST_P(AidlTest, HeapNullableCantApplyToOtherThanParcelables) {
322 CaptureStderr();
323 EXPECT_EQ(nullptr, Parse("Foo.aidl",
324 "parcelable Foo {\n"
325 " @nullable(heap=true) String s;\n"
326 "}",
327 typenames_, GetLanguage()));
328 EXPECT_THAT(GetCapturedStderr(), HasSubstr("@nullable(heap=true) is available to parcelables"));
329 }
330
TEST_P(AidlTest,RejectsDuplicatedArgumentNames)331 TEST_P(AidlTest, RejectsDuplicatedArgumentNames) {
332 const string method = "package a; interface IFoo { void f(int a, int a); }";
333 const string expected_stderr =
334 "ERROR: a/IFoo.aidl:1.33-35: method 'f' has duplicate argument name 'a'\n";
335 CaptureStderr();
336 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage()));
337 EXPECT_EQ(expected_stderr, GetCapturedStderr());
338 }
339
TEST_P(AidlTest,RejectsDuplicatedFieldNames)340 TEST_P(AidlTest, RejectsDuplicatedFieldNames) {
341 const string method = "package a; parcelable Foo { int a; String a; }";
342 const string expected_stderr = "ERROR: a/Foo.aidl:1.42-44: 'Foo' has duplicate field name 'a'\n";
343 CaptureStderr();
344 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, GetLanguage()));
345 EXPECT_EQ(expected_stderr, GetCapturedStderr());
346 }
347
TEST_P(AidlTest,AcceptsEmptyParcelable)348 TEST_P(AidlTest, AcceptsEmptyParcelable) {
349 CaptureStderr();
350 EXPECT_NE(nullptr, Parse("Foo.aidl", "parcelable Foo {}", typenames_, GetLanguage()));
351 EXPECT_EQ("", GetCapturedStderr());
352 }
353
TEST_P(AidlTest,RejectsDuplicatedAnnotationParams)354 TEST_P(AidlTest, RejectsDuplicatedAnnotationParams) {
355 const string method = "package a; interface IFoo { @UnsupportedAppUsage(foo=1, foo=2)void f(); }";
356 const string expected_stderr = "ERROR: a/IFoo.aidl:1.56-62: Trying to redefine parameter foo.\n";
357 CaptureStderr();
358 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage()));
359 EXPECT_EQ(expected_stderr, GetCapturedStderr());
360 }
361
TEST_P(AidlTest,RejectUnsupportedInterfaceAnnotations)362 TEST_P(AidlTest, RejectUnsupportedInterfaceAnnotations) {
363 AidlError error;
364 const string method = "package a; @nullable interface IFoo { int f(); }";
365 CaptureStderr();
366 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage(), &error));
367 EXPECT_THAT(GetCapturedStderr(), HasSubstr("@nullable is not available."));
368 EXPECT_EQ(AidlError::BAD_TYPE, error);
369 }
370
TEST_P(AidlTest,RejectUnsupportedTypeAnnotations)371 TEST_P(AidlTest, RejectUnsupportedTypeAnnotations) {
372 AidlError error;
373 const string method = "package a; interface IFoo { @JavaOnlyStableParcelable int f(); }";
374 CaptureStderr();
375 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage(), &error));
376 EXPECT_THAT(GetCapturedStderr(), HasSubstr("@JavaOnlyStableParcelable is not available."));
377 EXPECT_EQ(AidlError::BAD_TYPE, error);
378 }
379
TEST_P(AidlTest,RejectUnsupportedParcelableDefineAnnotations)380 TEST_P(AidlTest, RejectUnsupportedParcelableDefineAnnotations) {
381 AidlError error;
382 const string method = "package a; @nullable parcelable Foo { String a; String b; }";
383 CaptureStderr();
384 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, GetLanguage(), &error));
385 EXPECT_THAT(GetCapturedStderr(), HasSubstr("@nullable is not available."));
386 EXPECT_EQ(AidlError::BAD_TYPE, error);
387 }
388
TEST_P(AidlTest,ParsesNonNullableAnnotation)389 TEST_P(AidlTest, ParsesNonNullableAnnotation) {
390 auto parse_result =
391 Parse("a/IFoo.aidl", "package a; interface IFoo { String f(); }", typenames_, GetLanguage());
392 ASSERT_NE(nullptr, parse_result);
393 const AidlInterface* interface = parse_result->AsInterface();
394 ASSERT_NE(nullptr, interface);
395 ASSERT_FALSE(interface->GetMethods().empty());
396 EXPECT_FALSE(interface->GetMethods()[0]->GetType().IsNullable());
397 }
398
TEST_P(AidlTest,ParsesNullableAnnotation)399 TEST_P(AidlTest, ParsesNullableAnnotation) {
400 auto parse_result = Parse("a/IFoo.aidl", "package a; interface IFoo { @nullable String f(); }",
401 typenames_, GetLanguage());
402 ASSERT_NE(nullptr, parse_result);
403 const AidlInterface* interface = parse_result->AsInterface();
404 ASSERT_NE(nullptr, interface);
405 ASSERT_FALSE(interface->GetMethods().empty());
406 EXPECT_TRUE(interface->GetMethods()[0]->GetType().IsNullable());
407 }
408
TEST_P(AidlTest,ParsesNonUtf8Annotations)409 TEST_P(AidlTest, ParsesNonUtf8Annotations) {
410 auto parse_result =
411 Parse("a/IFoo.aidl", "package a; interface IFoo { String f(); }", typenames_, GetLanguage());
412 ASSERT_NE(nullptr, parse_result);
413 const AidlInterface* interface = parse_result->AsInterface();
414 ASSERT_NE(nullptr, interface);
415 ASSERT_FALSE(interface->GetMethods().empty());
416 EXPECT_FALSE(interface->GetMethods()[0]->GetType().IsUtf8InCpp());
417 }
418
TEST_P(AidlTest,ParsesUtf8Annotations)419 TEST_P(AidlTest, ParsesUtf8Annotations) {
420 auto parse_result = Parse("a/IFoo.aidl", "package a; interface IFoo { @utf8InCpp String f(); }",
421 typenames_, GetLanguage());
422 ASSERT_NE(nullptr, parse_result);
423 const AidlInterface* interface = parse_result->AsInterface();
424 ASSERT_NE(nullptr, interface);
425 ASSERT_FALSE(interface->GetMethods().empty());
426 EXPECT_TRUE(interface->GetMethods()[0]->GetType().IsUtf8InCpp());
427 }
428
TEST_P(AidlTest,VintfRequiresStructuredAndStability)429 TEST_P(AidlTest, VintfRequiresStructuredAndStability) {
430 AidlError error;
431 const string expected_stderr =
432 "ERROR: IFoo.aidl:1.16-26: Must compile @VintfStability type w/ aidl_interface 'stability: "
433 "\"vintf\"'\n"
434 "ERROR: IFoo.aidl:1.16-26: Must compile @VintfStability type w/ aidl_interface "
435 "--structured\n";
436 CaptureStderr();
437 ASSERT_EQ(nullptr, Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_,
438 GetLanguage(), &error));
439 EXPECT_EQ(expected_stderr, GetCapturedStderr());
440 ASSERT_EQ(AidlError::NOT_STRUCTURED, error);
441 }
442
TEST_P(AidlTest,VintfRequiresStructured)443 TEST_P(AidlTest, VintfRequiresStructured) {
444 AidlError error;
445 const string expected_stderr =
446 "ERROR: IFoo.aidl:1.16-26: Must compile @VintfStability type w/ aidl_interface "
447 "--structured\n";
448 CaptureStderr();
449 ASSERT_EQ(nullptr, Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_,
450 GetLanguage(), &error, {"--stability", "vintf"}));
451 EXPECT_EQ(expected_stderr, GetCapturedStderr());
452 ASSERT_EQ(AidlError::NOT_STRUCTURED, error);
453 }
454
TEST_P(AidlTest,VintfRequiresSpecifiedStability)455 TEST_P(AidlTest, VintfRequiresSpecifiedStability) {
456 AidlError error;
457 const string expected_stderr =
458 "ERROR: IFoo.aidl:1.16-26: Must compile @VintfStability type w/ aidl_interface 'stability: "
459 "\"vintf\"'\n";
460 CaptureStderr();
461 ASSERT_EQ(nullptr, Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_,
462 GetLanguage(), &error, {"--structured"}));
463 EXPECT_EQ(expected_stderr, GetCapturedStderr());
464 ASSERT_EQ(AidlError::NOT_STRUCTURED, error);
465 }
466
TEST_P(AidlTest,ParsesStabilityAnnotations)467 TEST_P(AidlTest, ParsesStabilityAnnotations) {
468 AidlError error;
469 auto parse_result = Parse("IFoo.aidl", "@VintfStability interface IFoo {}", typenames_,
470 GetLanguage(), &error, {"--structured", "--stability", "vintf"});
471 ASSERT_EQ(AidlError::OK, error);
472 ASSERT_NE(nullptr, parse_result);
473 const AidlInterface* interface = parse_result->AsInterface();
474 ASSERT_NE(nullptr, interface);
475 ASSERT_TRUE(interface->IsVintfStability());
476 }
477
TEST_P(AidlTest,TypesShouldHaveVintfStabilityWhenCompilingWithTheVintfFlag)478 TEST_P(AidlTest, TypesShouldHaveVintfStabilityWhenCompilingWithTheVintfFlag) {
479 CaptureStderr();
480 string code =
481 "@VintfStability\n"
482 "parcelable Foo {\n"
483 " interface INested { interface INastyNester {} }"
484 "}";
485 EXPECT_NE(nullptr, Parse("Foo.aidl", code, typenames_, GetLanguage(), nullptr,
486 {"--structured", "--stability", "vintf"}));
487 EXPECT_EQ(GetCapturedStderr(), "");
488 auto nested = typenames_.TryGetDefinedType("Foo.INested");
489 ASSERT_NE(nullptr, nested);
490 ASSERT_TRUE(nested->IsVintfStability());
491
492 auto nastyNester = typenames_.TryGetDefinedType("Foo.INested.INastyNester");
493 ASSERT_NE(nullptr, nastyNester);
494 ASSERT_TRUE(nastyNester->IsVintfStability());
495 }
496
TEST_P(AidlTest,VintfStabilityAppliesToNestedTypesAsWell)497 TEST_P(AidlTest, VintfStabilityAppliesToNestedTypesAsWell) {
498 CaptureStderr();
499 EXPECT_EQ(nullptr, Parse("Foo.aidl", "parcelable Foo {}", typenames_, GetLanguage(), nullptr,
500 {"--structured", "--stability", "vintf"}));
501 EXPECT_THAT(GetCapturedStderr(),
502 HasSubstr("Foo does not have VINTF level stability (marked @VintfStability)"));
503 }
504
TEST_F(AidlTest,ParsesJavaOnlyStableParcelable)505 TEST_F(AidlTest, ParsesJavaOnlyStableParcelable) {
506 Options java_options = Options::From("aidl -I . -o out --structured a/Foo.aidl");
507 Options cpp_options = Options::From("aidl -I . --lang=cpp -o out -h out/include a/Foo.aidl");
508 Options cpp_structured_options =
509 Options::From("aidl --lang=cpp -I . --structured -o out -h out/include a/Foo.aidl");
510 Options rust_options = Options::From("aidl -I . --lang=rust -o out --structured a/Foo.aidl");
511 io_delegate_.SetFileContents(
512 "a/Foo.aidl",
513 StringPrintf("package a; @JavaOnlyStableParcelable parcelable Foo cpp_header \"Foo.h\" ;"));
514
515 EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
516 EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
517
518 CaptureStderr();
519 EXPECT_FALSE(compile_aidl(cpp_structured_options, io_delegate_));
520 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Cannot declare unstructured"));
521
522 CaptureStderr();
523 EXPECT_FALSE(compile_aidl(rust_options, io_delegate_));
524 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Cannot declare unstructured"));
525 }
526
TEST_F(AidlTest,ParsesNdkOnlyStableParcelable)527 TEST_F(AidlTest, ParsesNdkOnlyStableParcelable) {
528 Options java_options = Options::From("aidl -I . -o out --structured a/Foo.aidl");
529 Options ndk_structured_options =
530 Options::From("aidl --lang=ndk --structured -I . -o out -h out/include a/Foo.aidl");
531 Options rust_options = Options::From("aidl --lang=rust -I . -o out --structured a/Foo.aidl");
532 Options cpp_options = Options::From("aidl --lang=cpp -I . -o out -h out/include a/Foo.aidl");
533 io_delegate_.SetFileContents(
534 "a/Foo.aidl",
535 StringPrintf("package a; @NdkOnlyStableParcelable parcelable Foo cpp_header \"Foo.h\" ;"));
536
537 EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
538
539 // not considered unstructured, but it still can't be compiled directly with
540 // --structured AIDL - it can only be used as an import
541 CaptureStderr();
542 EXPECT_FALSE(compile_aidl(ndk_structured_options, io_delegate_));
543 EXPECT_THAT(GetCapturedStderr(),
544 HasSubstr("Refusing to generate code with unstructured parcelables"));
545
546 CaptureStderr();
547 EXPECT_FALSE(compile_aidl(java_options, io_delegate_));
548 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Cannot declare unstructured"));
549
550 CaptureStderr();
551 EXPECT_FALSE(compile_aidl(rust_options, io_delegate_));
552 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Cannot declare unstructured"));
553 }
554
TEST_P(AidlTest,NdkAndJavaAndRustStabilityIsVintfStable)555 TEST_P(AidlTest, NdkAndJavaAndRustStabilityIsVintfStable) {
556 CaptureStderr();
557
558 io_delegate_.SetFileContents(
559 "NonPortableThing.aidl",
560 "@NdkOnlyStableParcelable @JavaOnlyStableParcelable @RustOnlyStableParcelable parcelable "
561 "NonPortableThing ndk_header \"lol.h\" cpp_header \"lolol.h\" rust_type \"lol::Lol\";");
562 import_paths_.emplace("");
563
564 auto result =
565 Parse("IFoo.aidl",
566 "import NonPortableThing; @VintfStability interface IFoo { NonPortableThing get(); }",
567 typenames_, GetLanguage(), nullptr, {"--structured", "--stability", "vintf"});
568
569 if (GetLanguage() == Options::Language::NDK || GetLanguage() == Options::Language::JAVA ||
570 GetLanguage() == Options::Language::RUST) {
571 EXPECT_NE(result, nullptr);
572 EXPECT_EQ(GetCapturedStderr(), "");
573 } else {
574 EXPECT_EQ(result, nullptr);
575 EXPECT_THAT(
576 GetCapturedStderr(),
577 HasSubstr("NonPortableThing does not have VINTF level stability (marked @VintfStability)"));
578 }
579 }
580
TEST_F(AidlTest,ParcelableSupportJavaDeriveToString)581 TEST_F(AidlTest, ParcelableSupportJavaDeriveToString) {
582 io_delegate_.SetFileContents("a/Foo.aidl", R"(package a;
583 @JavaDerive(toString=true) parcelable Foo { int a; float b; })");
584 Options java_options = Options::From("aidl --lang=java -I . -o out a/Foo.aidl");
585 EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
586
587 string java_out;
588 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &java_out));
589 EXPECT_THAT(java_out, testing::HasSubstr("public String toString() {"));
590
591 // Other backends shouldn't be bothered
592 Options cpp_options = Options::From("aidl --lang=cpp -I . -o out -h out a/Foo.aidl");
593 EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
594
595 Options ndk_options = Options::From("aidl --lang=ndk -I . -o out -h out a/Foo.aidl");
596 EXPECT_TRUE(compile_aidl(ndk_options, io_delegate_));
597 }
598
TEST_F(AidlTest,UnionSupportJavaDeriveToString)599 TEST_F(AidlTest, UnionSupportJavaDeriveToString) {
600 io_delegate_.SetFileContents("a/Foo.aidl", R"(package a;
601 @JavaDerive(toString=true) union Foo { int a; int[] b; })");
602 CaptureStderr();
603 Options java_options = Options::From("aidl --lang=java -I . -o out a/Foo.aidl");
604 EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
605 EXPECT_EQ("", GetCapturedStderr());
606 }
607
TEST_F(AidlTest,ParcelableSupportJavaDeriveEquals)608 TEST_F(AidlTest, ParcelableSupportJavaDeriveEquals) {
609 io_delegate_.SetFileContents("a/Foo.aidl", R"(package a;
610 @JavaDerive(equals=true) parcelable Foo { int a; float b; })");
611 CaptureStderr();
612 Options java_options = Options::From("aidl --lang=java -I . -o out a/Foo.aidl");
613 EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
614 EXPECT_EQ("", GetCapturedStderr());
615
616 const std::string expected = R"--(
617 @Override
618 public boolean equals(Object other) {
619 if (this == other) return true;
620 if (other == null) return false;
621 if (!(other instanceof Foo)) return false;
622 Foo that = (Foo)other;
623 if (!java.util.Objects.deepEquals(a, that.a)) return false;
624 if (!java.util.Objects.deepEquals(b, that.b)) return false;
625 return true;
626 }
627
628 @Override
629 public int hashCode() {
630 return java.util.Arrays.deepHashCode(java.util.Arrays.asList(a, b).toArray());
631 }
632 )--";
633
634 string java_out;
635 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &java_out));
636 EXPECT_THAT(java_out, testing::HasSubstr(expected));
637 }
638
TEST_F(AidlTest,UnionSupportJavaDeriveEquals)639 TEST_F(AidlTest, UnionSupportJavaDeriveEquals) {
640 io_delegate_.SetFileContents("a/Foo.aidl", R"(package a;
641 @JavaDerive(equals=true) union Foo { int a; int[] b; })");
642 CaptureStderr();
643 Options java_options = Options::From("aidl --lang=java -I . -o out a/Foo.aidl");
644 EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
645 EXPECT_EQ("", GetCapturedStderr());
646
647 const std::string expected = R"--(
648 @Override
649 public boolean equals(Object other) {
650 if (this == other) return true;
651 if (other == null) return false;
652 if (!(other instanceof Foo)) return false;
653 Foo that = (Foo)other;
654 if (_tag != that._tag) return false;
655 if (!java.util.Objects.deepEquals(_value, that._value)) return false;
656 return true;
657 }
658
659 @Override
660 public int hashCode() {
661 return java.util.Arrays.deepHashCode(java.util.Arrays.asList(_tag, _value).toArray());
662 }
663 )--";
664
665 string java_out;
666 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &java_out));
667 EXPECT_THAT(java_out, testing::HasSubstr(expected));
668 }
669
TEST_F(AidlTest,RejectsJavaDeriveAnnotation)670 TEST_F(AidlTest, RejectsJavaDeriveAnnotation) {
671 {
672 io_delegate_.SetFileContents("a/Foo.aidl",
673 "package a; @JavaDerive(blah=true) parcelable Foo{}");
674 Options java_options = Options::From("aidl --lang=java -I . -o out a/Foo.aidl");
675 CaptureStderr();
676 EXPECT_FALSE(compile_aidl(java_options, io_delegate_));
677 const std::string expected_stderr =
678 "ERROR: a/Foo.aidl:1.11-34: Parameter blah not supported for annotation JavaDerive.";
679 EXPECT_THAT(GetCapturedStderr(),
680 HasSubstr("Parameter blah not supported for annotation JavaDerive."));
681 }
682
683 {
684 io_delegate_.SetFileContents("a/IFoo.aidl", "package a; @JavaDerive interface IFoo{}");
685 Options java_options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
686 CaptureStderr();
687 EXPECT_FALSE(compile_aidl(java_options, io_delegate_));
688 EXPECT_THAT(GetCapturedStderr(), HasSubstr("@JavaDerive is not available."));
689 }
690 }
691
TEST_P(AidlTest,ParseDescriptorAnnotation)692 TEST_P(AidlTest, ParseDescriptorAnnotation) {
693 AidlError error;
694 auto parse_result = Parse("IFoo.aidl", R"(@Descriptor(value="IBar") interface IFoo{})",
695 typenames_, GetLanguage(), &error, {"--structured"});
696 ASSERT_EQ(AidlError::OK, error);
697 ASSERT_NE(nullptr, parse_result);
698 const AidlInterface* interface = parse_result->AsInterface();
699 ASSERT_NE(nullptr, interface);
700 ASSERT_EQ("IBar", interface->GetDescriptor());
701 }
702
TEST_P(AidlTest,UnknownAnnotation)703 TEST_P(AidlTest, UnknownAnnotation) {
704 CaptureStderr();
705 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", "package a; @Unknown interface IFoo { }", typenames_,
706 GetLanguage()));
707 EXPECT_THAT(GetCapturedStderr(), HasSubstr("not a recognized annotation"));
708
709 CaptureStderr();
710 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", "package a; @Unknown(param=true) interface IFoo { }",
711 typenames_, GetLanguage()));
712 EXPECT_THAT(GetCapturedStderr(), HasSubstr("not a recognized annotation"));
713 }
714
TEST_P(AidlTest,AcceptsOnewayMethod)715 TEST_P(AidlTest, AcceptsOnewayMethod) {
716 const string oneway_method = "package a; interface IFoo { oneway void f(int a); }";
717 EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
718 }
719
TEST_P(AidlTest,AcceptsOnewayInterface)720 TEST_P(AidlTest, AcceptsOnewayInterface) {
721 const string oneway_interface = "package a; oneway interface IBar { void f(int a); }";
722 EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, typenames_, GetLanguage()));
723 }
724
TEST_P(AidlTest,AcceptsAnnotatedOnewayMethod)725 TEST_P(AidlTest, AcceptsAnnotatedOnewayMethod) {
726 const string oneway_method =
727 "package a; interface IFoo { @UnsupportedAppUsage oneway void f(int a); }";
728 EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
729 }
730
TEST_P(AidlTest,AnnotationsInMultiplePlaces)731 TEST_P(AidlTest, AnnotationsInMultiplePlaces) {
732 const string oneway_method =
733 "package a; interface IFoo { @UnsupportedAppUsage oneway @PropagateAllowBlocking void f(int "
734 "a); }";
735 const AidlDefinedType* defined = Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage());
736 ASSERT_NE(nullptr, defined);
737 const AidlInterface* iface = defined->AsInterface();
738 ASSERT_NE(nullptr, iface);
739
740 const auto& methods = iface->GetMethods();
741 ASSERT_EQ(1u, methods.size());
742 const auto& method = methods[0];
743 const AidlTypeSpecifier& ret_type = method->GetType();
744
745 // TODO(b/151102494): these annotations should be on the method
746 ASSERT_NE(nullptr, ret_type.UnsupportedAppUsage());
747 ASSERT_TRUE(ret_type.IsPropagateAllowBlocking());
748 }
749
TEST_P(AidlTest,AnnotationValueAttribute)750 TEST_P(AidlTest, AnnotationValueAttribute) {
751 const string content =
752 "package a; @Descriptor(\"descriptor_value\") interface IFoo { void f(int a); }";
753 const AidlDefinedType* defined = Parse("a/IFoo.aidl", content, typenames_, GetLanguage());
754 ASSERT_NE(nullptr, defined);
755 const AidlInterface* iface = defined->AsInterface();
756 ASSERT_NE(nullptr, iface);
757
758 ASSERT_EQ("descriptor_value", iface->GetDescriptor());
759 }
760
TEST_F(AidlTest,CheckApiForAnnotationValueAttribute)761 TEST_F(AidlTest, CheckApiForAnnotationValueAttribute) {
762 Options options = Options::From("aidl --checkapi=equal old new");
763
764 io_delegate_.SetFileContents("old/p/IFoo.aidl",
765 "package p; @Descriptor(value=\"v1\") interface IFoo{ void foo();}");
766 io_delegate_.SetFileContents("new/p/IFoo.aidl",
767 "package p; @Descriptor(\"v1\") interface IFoo{ void foo();}");
768
769 EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
770 }
771
TEST_P(AidlTest,WritesComments)772 TEST_P(AidlTest, WritesComments) {
773 string foo_interface =
774 R"(package a;
775 /* foo */
776 interface IFoo {
777 /* i */
778 int i();
779 // j
780 @nullable String j();
781 // k1
782 /* k2 */
783 @UnsupportedAppUsage oneway void k(int a);
784 })";
785
786 CaptureStderr();
787 auto parse_result = Parse("a/IFoo.aidl", foo_interface, typenames_, GetLanguage());
788 EXPECT_NE(nullptr, parse_result);
789 EXPECT_EQ("", GetCapturedStderr());
790
791 EXPECT_EQ((Comments{{"/* foo */"}}), parse_result->GetComments());
792
793 const AidlInterface* interface = parse_result->AsInterface();
794 EXPECT_EQ((Comments{{"/* i */"}}), interface->GetMethods()[0]->GetComments());
795 EXPECT_EQ((Comments{{"// j\n"}}), interface->GetMethods()[1]->GetComments());
796 EXPECT_EQ((Comments{{"// k1\n"}, {"/* k2 */"}}), interface->GetMethods()[2]->GetComments());
797 }
798
TEST_P(AidlTest,CppHeaderCanBeIdentifierAsWell)799 TEST_P(AidlTest, CppHeaderCanBeIdentifierAsWell) {
800 io_delegate_.SetFileContents("p/cpp_header.aidl",
801 R"(package p;
802 parcelable cpp_header cpp_header "bar/header" ndk_header "ndk/bar/header" )"
803 R"(rust_type "package::SomeType";)");
804 import_paths_.emplace("");
805 const string input_path = "p/IFoo.aidl";
806 const string input = R"(package p;
807 import p.cpp_header;
808 interface IFoo {
809 // get bar
810 cpp_header get();
811 })";
812
813 auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
814 EXPECT_NE(nullptr, parse_result);
815 const AidlInterface* interface = parse_result->AsInterface();
816 EXPECT_EQ((Comments{{"// get bar\n"}}), interface->GetMethods()[0]->GetComments());
817 }
818
TEST_F(AidlTest,RejectsIfCppHeaderIsMissing)819 TEST_F(AidlTest, RejectsIfCppHeaderIsMissing) {
820 io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo;");
821 Options options = Options::From("aidl -I . --lang cpp -h h -o o Foo.aidl");
822 CaptureStderr();
823 EXPECT_FALSE(compile_aidl(options, io_delegate_));
824 EXPECT_THAT(GetCapturedStderr(), HasSubstr("must have cpp_header defined"));
825 }
826
TEST_F(AidlTest,RejectsIfTypeRefsCppHeaderIsMissing)827 TEST_F(AidlTest, RejectsIfTypeRefsCppHeaderIsMissing) {
828 io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo;");
829 io_delegate_.SetFileContents("IBar.aidl", "interface IBar { void bar(in Foo foo); }");
830 Options options = Options::From("aidl -I . --lang cpp -h h -o o IBar.aidl");
831 CaptureStderr();
832 EXPECT_FALSE(compile_aidl(options, io_delegate_));
833 EXPECT_THAT(GetCapturedStderr(), HasSubstr("must have cpp_header defined"));
834 }
835
TEST_F(AidlTest,ParsesPreprocessedFile)836 TEST_F(AidlTest, ParsesPreprocessedFile) {
837 string simple_content = "parcelable a.Foo;\ninterface b.IBar;";
838 io_delegate_.SetFileContents("path", simple_content);
839 EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").is_resolved);
840 EXPECT_TRUE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/true));
841 EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").is_resolved);
842 EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").is_resolved);
843 }
844
TEST_F(AidlTest,ParsesPreprocessedFileWithWhitespace)845 TEST_F(AidlTest, ParsesPreprocessedFileWithWhitespace) {
846 string simple_content = "parcelable a.Foo;\n interface b.IBar ;\t";
847 io_delegate_.SetFileContents("path", simple_content);
848
849 EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").is_resolved);
850 EXPECT_TRUE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/true));
851 EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").is_resolved);
852 EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").is_resolved);
853 }
854
TEST_P(AidlTest,PreferImportToPreprocessed)855 TEST_P(AidlTest, PreferImportToPreprocessed) {
856 io_delegate_.SetFileContents("preprocessed", "interface another.IBar;");
857 io_delegate_.SetFileContents("one/IBar.aidl",
858 "package one; "
859 "interface IBar {}");
860 preprocessed_files_.push_back("preprocessed");
861 import_paths_.emplace("");
862 auto parse_result = Parse("p/IFoo.aidl", "package p; import one.IBar; interface IFoo {}",
863 typenames_, GetLanguage());
864 EXPECT_NE(nullptr, parse_result);
865
866 // We expect to know about both kinds of IBar
867 EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
868 EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
869 // But if we request just "IBar" we should get our imported one.
870 AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", /*array=*/std::nullopt, nullptr, {});
871 ambiguous_type.Resolve(typenames_, parse_result);
872 EXPECT_EQ("one.IBar", ambiguous_type.GetName());
873 }
874
875 // Special case of PreferImportToPreprocessed. Imported type should be preferred
876 // even when the preprocessed file already has the same type.
TEST_P(AidlTest,B147918827)877 TEST_P(AidlTest, B147918827) {
878 io_delegate_.SetFileContents("preprocessed", "interface another.IBar;\ninterface one.IBar;");
879 io_delegate_.SetFileContents("one/IBar.aidl",
880 "package one; "
881 "interface IBar {}");
882 preprocessed_files_.push_back("preprocessed");
883 import_paths_.emplace("");
884 auto parse_result = Parse("p/IFoo.aidl", "package p; import one.IBar; interface IFoo {}",
885 typenames_, GetLanguage());
886 EXPECT_NE(nullptr, parse_result);
887
888 // We expect to know about both kinds of IBar
889 EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
890 EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
891 // But if we request just "IBar" we should get our imported one.
892 AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", /*array=*/std::nullopt, nullptr, {});
893 ambiguous_type.Resolve(typenames_, parse_result);
894 EXPECT_EQ("one.IBar", ambiguous_type.GetName());
895 }
896
TEST_F(AidlTest,WritePreprocessedFile)897 TEST_F(AidlTest, WritePreprocessedFile) {
898 io_delegate_.SetFileContents("p/Outer.aidl", "package p; parcelable Outer.Inner;");
899 io_delegate_.SetFileContents("one/IBar.aidl",
900 "package one; import p.Outer;"
901 "interface IBar {}");
902
903 vector<string> args{"aidl", "--preprocess", "preprocessed",
904 "-I.", "p/Outer.aidl", "one/IBar.aidl"};
905 Options options = Options::From(args);
906 EXPECT_TRUE(::android::aidl::Preprocess(options, io_delegate_));
907
908 std::map<std::string, std::string> expected = {{"preprocessed",
909 "parcelable p.Outer.Inner;\n"
910 "interface one.IBar {\n"
911 "}\n"}};
912 EXPECT_THAT(io_delegate_.OutputFiles(), testing::Eq(expected));
913 }
914
TEST_F(AidlTest,PreprocessVariousThings)915 TEST_F(AidlTest, PreprocessVariousThings) {
916 io_delegate_.SetFileContents("foo/bar/IFoo.aidl",
917 "package foo.bar;\n"
918 "interface IFoo {\n"
919 " int foo();\n"
920 " const int FOO = foo.bar.Bar.BAR + 1; // should be 44\n"
921 "}\n");
922 io_delegate_.SetFileContents("foo/bar/Bar.aidl",
923 "package foo.bar;\n"
924 "parcelable Bar {\n"
925 " const int BAR = imported.Foo.FOO + 1; // should be 43\n"
926 " imported.Foo foo;\n"
927 "}\n");
928 io_delegate_.SetFileContents("foo/bar/Gen.aidl",
929 "package foo.bar;\n"
930 "parcelable Gen<T> {\n"
931 "}\n");
932 io_delegate_.SetFileContents("foo/bar/Enum.aidl",
933 "package foo.bar;\n"
934 "enum Enum {\n"
935 " FOO = 3, BAR = FOO + 3, // should be 3, 6\n"
936 "}\n");
937 io_delegate_.SetFileContents("sub/imported/Foo.aidl",
938 "package imported;\n"
939 "parcelable Foo {\n"
940 " const int FOO = 42;\n"
941 "}\n");
942
943 vector<string> args = {
944 "aidl",
945 "--preprocess",
946 "preprocessed",
947 "-Isub",
948 "-I.",
949 "foo/bar/IFoo.aidl",
950 "foo/bar/Bar.aidl",
951 "foo/bar/Gen.aidl",
952 "foo/bar/Enum.aidl",
953 };
954 ASSERT_TRUE(Preprocess(Options::From(args), io_delegate_));
955 std::string preprocessed =
956 "interface foo.bar.IFoo {\n"
957 " const int FOO = 44;\n"
958 "}\n"
959 "parcelable foo.bar.Bar {\n"
960 " const int BAR = 43;\n"
961 "}\n"
962 "parcelable foo.bar.Gen<T> {\n"
963 "}\n"
964 "enum foo.bar.Enum {\n"
965 " FOO = 3,\n"
966 " BAR = 6,\n"
967 "}\n";
968 std::map<std::string, std::string> expected = {{"preprocessed", preprocessed}};
969 EXPECT_THAT(io_delegate_.OutputFiles(), testing::Eq(expected));
970
971 // use preprocessed
972 io_delegate_.SetFileContents("a/Foo.aidl",
973 "package a; parcelable Foo { const int y = foo.bar.Bar.BAR; }");
974 io_delegate_.SetFileContents("preprocessed", preprocessed);
975 CaptureStderr();
976 auto options = Options::From("aidl --lang java -I . -o out a/Foo.aidl -ppreprocessed");
977 EXPECT_TRUE(compile_aidl(options, io_delegate_));
978 EXPECT_EQ("", GetCapturedStderr());
979 string code;
980 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &code));
981 EXPECT_THAT(code, testing::HasSubstr("public static final int y = 43;"));
982 }
983
TEST_F(AidlTest,AllowMultipleUnstructuredNestedParcelablesInASingleDocument)984 TEST_F(AidlTest, AllowMultipleUnstructuredNestedParcelablesInASingleDocument) {
985 io_delegate_.SetFileContents("p/IFoo.aidl",
986 "package p;\n"
987 "import x.Outer;\n"
988 "interface IFoo {\n"
989 " void foo(in Outer.Inner1 in1, in Outer.Inner2 in2);\n"
990 "}");
991 io_delegate_.SetFileContents("imported/x/Outer.aidl",
992 "package x;\n"
993 "parcelable Outer.Inner1;\n"
994 "parcelable Outer.Inner2;\n");
995 auto opt = Options::From("aidl -I . -Iimported --lang=java p/IFoo.aidl");
996 CaptureStderr();
997 EXPECT_TRUE(compile_aidl(opt, io_delegate_));
998 EXPECT_EQ("", GetCapturedStderr());
999 }
1000
TEST_F(AidlTest,StubsSourceIsGeneratedFromDuplicateDefinitionWithFrameworkAidl_FrameworkAidlLater)1001 TEST_F(AidlTest,
1002 StubsSourceIsGeneratedFromDuplicateDefinitionWithFrameworkAidl_FrameworkAidlLater) {
1003 // Main doc(Foo.aidl) is loaded
1004 // And then framework.aidl is loaded as preprocessed. (conflict)
1005 io_delegate_.SetFileContents("sdk/framework.aidl", "parcelable x.Foo.Inner;\n");
1006 io_delegate_.SetFileContents("x/Foo.aidl",
1007 "package x;\n"
1008 "parcelable Foo.Inner;\n");
1009 auto opt = Options::From("aidl -psdk/framework.aidl -I. x/Foo.aidl");
1010 CaptureStderr();
1011 EXPECT_TRUE(compile_aidl(opt, io_delegate_));
1012 EXPECT_EQ("", GetCapturedStderr());
1013 }
1014
TEST_F(AidlTest,StubsSourceIsGeneratedFromDuplicateDefinitionWithFrameworkAidl_FrameworkAidlFirst)1015 TEST_F(AidlTest,
1016 StubsSourceIsGeneratedFromDuplicateDefinitionWithFrameworkAidl_FrameworkAidlFirst) {
1017 // Main doc(IBar.aidl) is loaded first.
1018 // Framework.aidl is loaded as preprocessed.
1019 // And then import(Foo.aidl) is loaded. (conflict)
1020 io_delegate_.SetFileContents("sdk/framework.aidl", "parcelable x.Foo.Inner;\n");
1021 io_delegate_.SetFileContents("x/IBar.aidl",
1022 "package x;\n"
1023 "import x.Foo;\n"
1024 "interface IBar {\n"
1025 " void bar(in Foo.Inner inner);\n"
1026 "}");
1027 io_delegate_.SetFileContents("x/Foo.aidl",
1028 "package x;\n"
1029 "parcelable Foo.Inner;\n");
1030 auto opt = Options::From("aidl -psdk/framework.aidl -I. x/IBar.aidl");
1031 CaptureStderr();
1032 EXPECT_TRUE(compile_aidl(opt, io_delegate_));
1033 EXPECT_EQ("", GetCapturedStderr());
1034 }
1035
TEST_F(AidlTest,PreprocessedFileCantDeclarePackage)1036 TEST_F(AidlTest, PreprocessedFileCantDeclarePackage) {
1037 string simple_content = "package xxx; parcelable a.Foo;";
1038 io_delegate_.SetFileContents("path", simple_content);
1039 CaptureStderr();
1040 EXPECT_FALSE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/true));
1041 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Preprocessed file can't declare package."));
1042 }
1043
TEST_F(AidlTest,RejectQualifiedTypeNameUnlessPreprocessed)1044 TEST_F(AidlTest, RejectQualifiedTypeNameUnlessPreprocessed) {
1045 string simple_content = "parcelable a.Foo {}";
1046 io_delegate_.SetFileContents("path", simple_content);
1047 CaptureStderr();
1048 EXPECT_FALSE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/false));
1049 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Type name can't be qualified"));
1050 }
1051
TEST_P(AidlTest,PreprocessedCanDeclareJavaStyleBuiltinTypes)1052 TEST_P(AidlTest, PreprocessedCanDeclareJavaStyleBuiltinTypes) {
1053 string contents = R"(
1054 interface android.os.IBinder;
1055 interface android.os.IInterface;
1056 parcelable android.os.ParcelFileDescriptor;
1057 )";
1058 io_delegate_.SetFileContents("path", contents);
1059 CaptureStderr();
1060 EXPECT_TRUE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/true));
1061 EXPECT_THAT(GetCapturedStderr(), "");
1062 }
1063
TEST_P(AidlTest,SupportDeprecated)1064 TEST_P(AidlTest, SupportDeprecated) {
1065 struct TestCase {
1066 std::string output_file;
1067 std::string annotation;
1068 };
1069
1070 auto CheckDeprecated = [&](const std::string& filename, const std::string& contents,
1071 std::vector<std::pair<Options::Language, TestCase>> expectations) {
1072 io_delegate_.SetFileContents(filename, contents);
1073
1074 auto options = Options::From("aidl -I . --lang=" + to_string(GetLanguage()) + " " + filename +
1075 " --out=out --header_out=out");
1076 EXPECT_TRUE(compile_aidl(options, io_delegate_));
1077 for (const auto& [lang, test_case] : expectations) {
1078 if (lang != GetLanguage()) continue;
1079 string output;
1080 EXPECT_TRUE(io_delegate_.GetWrittenContents(test_case.output_file, &output));
1081 EXPECT_THAT(output, HasSubstr(test_case.annotation));
1082 }
1083 };
1084
1085 // Emit escaped string for notes
1086 CheckDeprecated(
1087 "IFoo.aidl",
1088 R"(interface IFoo {
1089 /**
1090 * @note asdf
1091 * @deprecated a really long deprecation message
1092 *
1093 * which is really long
1094 * @param foo bar
1095 */
1096 List<String> foo();
1097 })",
1098 {
1099 {Options::Language::JAVA, {"out/IFoo.java", "@Deprecated"}},
1100 {Options::Language::CPP,
1101 {"out/IFoo.h",
1102 R"(__attribute__((deprecated("a really long deprecation message which is really long"))))"}},
1103 {Options::Language::NDK,
1104 {"out/aidl/IFoo.h",
1105 R"(__attribute__((deprecated("a really long deprecation message which is really long"))))"}},
1106 {Options::Language::RUST,
1107 {"out/IFoo.rs",
1108 R"(#[deprecated = "a really long deprecation message which is really long"])"}},
1109 });
1110
1111 // In AIDL @deprecated can be in block comments as well as javadoc style
1112 CheckDeprecated(
1113 "IFoo.aidl",
1114 "interface IFoo {\n"
1115 " /* @deprecated use bar() */\n"
1116 " List<String> foo();\n"
1117 "}",
1118 {
1119 {Options::Language::JAVA, {"out/IFoo.java", "@Deprecated"}},
1120 {Options::Language::JAVA, {"out/IFoo.java", "/** @deprecated use bar() */"}},
1121 {Options::Language::CPP, {"out/IFoo.h", "__attribute__((deprecated(\"use bar()\")))"}},
1122 {Options::Language::NDK,
1123 {"out/aidl/IFoo.h", "__attribute__((deprecated(\"use bar()\")))"}},
1124 {Options::Language::RUST, {"out/IFoo.rs", "#[deprecated = \"use bar()\"]"}},
1125 });
1126
1127 // but not in line comments
1128 auto parsed = Parse("IFoo.aidl", "// @deprecated\ninterface IFoo {}", typenames_, GetLanguage());
1129 EXPECT_FALSE(parsed->IsDeprecated());
1130
1131 // parcelable
1132 CheckDeprecated("Foo.aidl",
1133 "parcelable Foo {\n"
1134 " /** @deprecated use bar*/\n"
1135 " int foo = 0;\n"
1136 "}",
1137 {
1138 {Options::Language::JAVA, {"out/Foo.java", "@Deprecated"}},
1139 {Options::Language::CPP, {"out/Foo.h", "__attribute__((deprecated"}},
1140 {Options::Language::NDK, {"out/aidl/Foo.h", "__attribute__((deprecated"}},
1141 {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
1142 });
1143
1144 // interface constants
1145 CheckDeprecated("IFoo.aidl",
1146 "interface IFoo {\n"
1147 " /** @deprecated use bar*/\n"
1148 " const int FOO = 0;\n"
1149 "}",
1150 {
1151 {Options::Language::JAVA, {"out/IFoo.java", "@Deprecated"}},
1152 {Options::Language::CPP, {"out/IFoo.h", "__attribute__((deprecated"}},
1153 {Options::Language::NDK, {"out/aidl/IFoo.h", "__attribute__((deprecated"}},
1154 {Options::Language::RUST, {"out/IFoo.rs", "#[deprecated"}},
1155 });
1156
1157 // union fields
1158 CheckDeprecated("Foo.aidl",
1159 "union Foo {\n"
1160 " int bar = 0;\n"
1161 " /** @deprecated use bar*/\n"
1162 " int foo;\n"
1163 "}",
1164 {
1165 {Options::Language::JAVA, {"out/Foo.java", "@Deprecated"}},
1166 {Options::Language::CPP, {"out/Foo.h", "__attribute__((deprecated"}},
1167 {Options::Language::NDK, {"out/aidl/Foo.h", "__attribute__((deprecated"}},
1168 {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
1169 });
1170
1171 CheckDeprecated("Foo.aidl",
1172 "/** @deprecated use Bar */\n"
1173 "parcelable Foo {}",
1174 {
1175 {Options::Language::JAVA, {"out/Foo.java", "@Deprecated"}},
1176 {Options::Language::CPP, {"out/Foo.h", "__attribute__((deprecated"}},
1177 {Options::Language::NDK, {"out/aidl/Foo.h", "__attribute__((deprecated"}},
1178 {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
1179 });
1180
1181 CheckDeprecated("Foo.aidl",
1182 "/** @deprecated use Bar */\n"
1183 "union Foo { int foo = 0; }",
1184 {
1185 {Options::Language::JAVA, {"out/Foo.java", "@Deprecated"}},
1186 {Options::Language::CPP, {"out/Foo.h", "__attribute__((deprecated"}},
1187 {Options::Language::NDK, {"out/aidl/Foo.h", "__attribute__((deprecated"}},
1188 {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
1189 });
1190
1191 CheckDeprecated("IFoo.aidl",
1192 "/** @deprecated use IBar */\n"
1193 "interface IFoo {}",
1194 {
1195 {Options::Language::JAVA, {"out/IFoo.java", "@Deprecated"}},
1196 {Options::Language::CPP, {"out/IFoo.h", "__attribute__((deprecated"}},
1197 {Options::Language::NDK, {"out/aidl/IFoo.h", "__attribute__((deprecated"}},
1198 {Options::Language::RUST, {"out/IFoo.rs", "#[deprecated"}},
1199 });
1200
1201 CheckDeprecated("Foo.aidl",
1202 "/** @deprecated use IBar */\n"
1203 "enum Foo { FOO }",
1204 {
1205 {Options::Language::JAVA, {"out/Foo.java", "@Deprecated"}},
1206 {Options::Language::CPP, {"out/Foo.h", "__attribute__((deprecated"}},
1207 {Options::Language::NDK, {"out/aidl/Foo.h", "__attribute__((deprecated"}},
1208 {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
1209 });
1210
1211 CheckDeprecated("Foo.aidl",
1212 "enum Foo {\n"
1213 " /** @deprecated */\n"
1214 " FOO,\n"
1215 " BAR,\n"
1216 "}",
1217 {
1218 {Options::Language::JAVA, {"out/Foo.java", "@Deprecated"}},
1219 {Options::Language::CPP, {"out/Foo.h", "__attribute__((deprecated"}},
1220 {Options::Language::NDK, {"out/aidl/Foo.h", "__attribute__((deprecated"}},
1221 {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
1222 });
1223 }
1224
TEST_P(AidlTest,RequireOuterClass)1225 TEST_P(AidlTest, RequireOuterClass) {
1226 const string expected_stderr =
1227 "ERROR: p/IFoo.aidl: Couldn't find import for class Inner. Searched here:\n - ./\nERROR: "
1228 "p/IFoo.aidl:1.54-60: Failed to resolve 'Inner'\n";
1229 io_delegate_.SetFileContents("p/Outer.aidl", "package p; parcelable Outer.Inner;");
1230 import_paths_.emplace("");
1231 CaptureStderr();
1232 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1233 "package p; import p.Outer; interface IFoo { void f(in Inner c); }",
1234 typenames_, GetLanguage()));
1235 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1236 }
1237
TEST_P(AidlTest,ParseCompoundParcelableFromPreprocess)1238 TEST_P(AidlTest, ParseCompoundParcelableFromPreprocess) {
1239 io_delegate_.SetFileContents("preprocessed",
1240 "parcelable p.Outer.Inner cpp_header \"inner.h\" ndk_header "
1241 "\"ndk/inner.h\" rust_type \"package::Inner\";");
1242 preprocessed_files_.push_back("preprocessed");
1243 auto parse_result = Parse("p/IFoo.aidl", "package p; interface IFoo { void f(in Inner c); }",
1244 typenames_, GetLanguage());
1245 // Require legacy behavior - inner class name can be used without outer class name.
1246 EXPECT_NE(nullptr, parse_result);
1247 }
1248
TEST_F(AidlTest,ApiMappingAcceptsUnstructuredParcelables)1249 TEST_F(AidlTest, ApiMappingAcceptsUnstructuredParcelables) {
1250 io_delegate_.SetFileContents("p/Foo.aidl", "package p; parcelable Foo;");
1251
1252 Options options1 = Options::From("aidl -I . --apimapping mapping.txt p/Foo.aidl");
1253 CaptureStderr();
1254 EXPECT_EQ(0, aidl_entry(options1, io_delegate_));
1255 EXPECT_EQ("", GetCapturedStderr());
1256 }
1257
TEST_F(AidlTest,FailOnParcelable)1258 TEST_F(AidlTest, FailOnParcelable) {
1259 const string expected_foo_stderr =
1260 "ERROR: p/IFoo.aidl:1.22-27: Refusing to generate code with unstructured parcelables. "
1261 "Declared parcelables should be in their own file and/or cannot be used with --structured "
1262 "interfaces.\n";
1263 io_delegate_.SetFileContents("p/IFoo.aidl", "package p; parcelable IFoo;");
1264
1265 // By default, we shouldn't fail on parcelable.
1266 Options options1 = Options::From("aidl -I . p/IFoo.aidl");
1267 CaptureStderr();
1268 EXPECT_TRUE(compile_aidl(options1, io_delegate_));
1269 EXPECT_EQ("", GetCapturedStderr());
1270
1271 // -b considers this an error
1272 Options options2 = Options::From("aidl -I . -b p/IFoo.aidl");
1273 CaptureStderr();
1274 EXPECT_FALSE(compile_aidl(options2, io_delegate_));
1275 EXPECT_EQ(expected_foo_stderr, GetCapturedStderr());
1276
1277 const string expected_bar_stderr =
1278 "ERROR: p/IBar.aidl:1.22-26: Refusing to generate code with unstructured parcelables. "
1279 "Declared parcelables should be in their own file and/or cannot be used with --structured "
1280 "interfaces.\n";
1281 io_delegate_.SetFileContents("p/IBar.aidl", "package p; parcelable Foo; interface IBar{}");
1282
1283 // With '-b' option, a parcelable and an interface should fail.
1284 Options options3 = Options::From("aidl -I . p/IBar.aidl");
1285 CaptureStderr();
1286 EXPECT_TRUE(compile_aidl(options3, io_delegate_));
1287 EXPECT_EQ("", GetCapturedStderr());
1288 Options options4 = Options::From("aidl -I . -b p/IBar.aidl");
1289 CaptureStderr();
1290 EXPECT_FALSE(compile_aidl(options4, io_delegate_));
1291 EXPECT_EQ(expected_bar_stderr, GetCapturedStderr());
1292 }
1293
TEST_P(AidlTest,ImportingJavaStyleBuiltinTypesIsAllowed)1294 TEST_P(AidlTest, ImportingJavaStyleBuiltinTypesIsAllowed) {
1295 string contents = R"(
1296 import android.os.IBinder;
1297 import android.os.IInterface;
1298 interface IFoo {
1299 void foo(in IBinder b);
1300 }
1301 )";
1302 EXPECT_NE(nullptr, Parse("IFoo.aidl", contents, typenames_, GetLanguage()));
1303 }
1304
TEST_P(AidlTest,StructuredFailOnUnstructuredParcelable)1305 TEST_P(AidlTest, StructuredFailOnUnstructuredParcelable) {
1306 const string expected_stderr =
1307 "o.WhoKnowsWhat is not structured, but this is a structured interface";
1308 io_delegate_.SetFileContents("o/WhoKnowsWhat.aidl",
1309 "package o; parcelable WhoKnowsWhat cpp_header \"who_knows.h\" "
1310 "ndk_header \"ndk/who_knows.h\" rust_type \"WhoKnows\";");
1311 import_paths_.emplace("");
1312 AidlError error;
1313 CaptureStderr();
1314 EXPECT_EQ(
1315 nullptr,
1316 Parse("p/IFoo.aidl",
1317 "package p; import o.WhoKnowsWhat; interface IFoo { void f(in WhoKnowsWhat thisIs); }",
1318 typenames_, GetLanguage(), &error, {"--structured"}));
1319 EXPECT_THAT(GetCapturedStderr(), HasSubstr(expected_stderr));
1320 EXPECT_EQ(AidlError::NOT_STRUCTURED, error);
1321 }
1322
TEST_P(AidlTest,FailOnDuplicateConstantNames)1323 TEST_P(AidlTest, FailOnDuplicateConstantNames) {
1324 AidlError error;
1325 const string expected_stderr =
1326 "ERROR: p/IFoo.aidl:4.34-45: Found duplicate constant name 'DUPLICATED'\n";
1327 CaptureStderr();
1328 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1329 R"(package p;
1330 interface IFoo {
1331 const String DUPLICATED = "d";
1332 const int DUPLICATED = 1;
1333 }
1334 )",
1335 typenames_, GetLanguage(), &error));
1336 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1337 EXPECT_EQ(AidlError::BAD_TYPE, error);
1338 }
1339
TEST_P(AidlTest,FailOnDoubleUnderscore)1340 TEST_P(AidlTest, FailOnDoubleUnderscore) {
1341 AidlError error;
1342 const string expected_stderr = "ERROR: p/IFoo.aidl:3.52-57: Could not parse integer: 1__0\n";
1343 CaptureStderr();
1344 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1345 R"(package p;
1346 interface IFoo {
1347 const int UNDERSCORE_USER = 1__0;
1348 }
1349 )",
1350 typenames_, GetLanguage(), &error));
1351 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1352 EXPECT_EQ(AidlError::PARSE_ERROR, error);
1353 }
1354
TEST_P(AidlTest,FailOnUnderscoreBeforeModifier)1355 TEST_P(AidlTest, FailOnUnderscoreBeforeModifier) {
1356 AidlError error;
1357 const string expected_stderr = "ERROR: p/IFoo.aidl:3.52-59: Could not parse hexvalue: 0xFF_L\n";
1358 CaptureStderr();
1359 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1360 R"(package p;
1361 interface IFoo {
1362 const int UNDERSCORE_USER = 0xFF_L;
1363 }
1364 )",
1365 typenames_, GetLanguage(), &error));
1366 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1367 EXPECT_EQ(AidlError::PARSE_ERROR, error);
1368 }
1369
TEST_P(AidlTest,FailOnEndingUnderscore)1370 TEST_P(AidlTest, FailOnEndingUnderscore) {
1371 AidlError error;
1372 const string expected_stderr = "ERROR: p/IFoo.aidl:3.52-56: Could not parse integer: 10_\n";
1373 CaptureStderr();
1374 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1375 R"(package p;
1376 interface IFoo {
1377 const int UNDERSCORE_USER = 10_;
1378 }
1379 )",
1380 typenames_, GetLanguage(), &error));
1381 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1382 EXPECT_EQ(AidlError::PARSE_ERROR, error);
1383 }
1384
TEST_P(AidlTest,FailOnLeadingUnderscore)1385 TEST_P(AidlTest, FailOnLeadingUnderscore) {
1386 AidlError error;
1387 const string expected_stderr =
1388 "ERROR: p/IFoo.aidl:3.52-56: Can't find _10 in IFoo\nERROR: p/IFoo.aidl:3.52-56: Unknown "
1389 "reference '_10'\n";
1390 CaptureStderr();
1391 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1392 R"(package p;
1393 interface IFoo {
1394 const int UNDERSCORE_USER = _10;
1395 }
1396 )",
1397 typenames_, GetLanguage(), &error));
1398 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1399 EXPECT_EQ(AidlError::BAD_TYPE, error);
1400 }
1401
TEST_P(AidlTest,InvalidConstString)1402 TEST_P(AidlTest, InvalidConstString) {
1403 AidlError error;
1404 const string expected_stderr =
1405 "ERROR: p/IFoo.aidl:3.47-60: Found invalid character '\\' at index 4 in string constant "
1406 "'\"test\\\"test\"'\n";
1407 CaptureStderr();
1408 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1409 R"(package p;
1410 interface IFoo {
1411 const String someVar = "test\"test";
1412 }
1413 )",
1414 typenames_, GetLanguage(), &error));
1415 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1416 EXPECT_EQ(AidlError::BAD_TYPE, error);
1417 }
1418
TEST_F(AidlTest,InvalidCharLiteral)1419 TEST_F(AidlTest, InvalidCharLiteral) {
1420 auto filename = "Foo.aidl";
1421 char code[] = "parcelable Foo { char a = '\0'; char b = '\t'; }";
1422 io_delegate_.SetFileContents(filename,
1423 string{code, sizeof(code) - 1}); // -1 to drop nil at the end
1424 CaptureStderr();
1425 EXPECT_TRUE(Parser::Parse(filename, io_delegate_, typenames_, /*is_preprocessed=*/false));
1426 auto err = GetCapturedStderr();
1427 EXPECT_THAT(err, HasSubstr("Invalid character literal \\0"));
1428 EXPECT_THAT(err, HasSubstr("Invalid character literal \\t"));
1429 }
1430
TEST_P(AidlTest,RejectUnstructuredParcelablesInNDKandRust)1431 TEST_P(AidlTest, RejectUnstructuredParcelablesInNDKandRust) {
1432 io_delegate_.SetFileContents("o/Foo.aidl", "package o; parcelable Foo cpp_header \"cpp/Foo.h\";");
1433 const auto options =
1434 Options::From("aidl --lang=" + to_string(GetLanguage()) + " -o out -h out -I. o/Foo.aidl");
1435 const bool reject_unstructured_parcelables =
1436 GetLanguage() == Options::Language::NDK || GetLanguage() == Options::Language::RUST;
1437 const string expected_err = reject_unstructured_parcelables
1438 ? "Refusing to generate code with unstructured parcelables"
1439 : "";
1440 CaptureStderr();
1441 EXPECT_EQ(compile_aidl(options, io_delegate_), !reject_unstructured_parcelables);
1442 EXPECT_THAT(GetCapturedStderr(), HasSubstr(expected_err));
1443 }
1444
TEST_F(AidlTest,CosntantValueType)1445 TEST_F(AidlTest, CosntantValueType) {
1446 unique_ptr<AidlConstantValue> num{AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1")};
1447 EXPECT_EQ(num->GetType(), AidlConstantValue::Type::INT8);
1448 }
1449
TEST_P(AidlTest,FailOnTooBigConstant)1450 TEST_P(AidlTest, FailOnTooBigConstant) {
1451 AidlError error;
1452 const string expected_stderr =
1453 "ERROR: p/IFoo.aidl:3.48-52: Invalid type specifier for an int32 literal: byte (256).\n";
1454 CaptureStderr();
1455 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1456 R"(package p;
1457 interface IFoo {
1458 const byte type2small = 256;
1459 }
1460 )",
1461 typenames_, GetLanguage(), &error));
1462 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1463 EXPECT_EQ(AidlError::BAD_TYPE, error);
1464 }
1465
TEST_F(AidlTest,BoolConstantsEvaluatesToIntegers)1466 TEST_F(AidlTest, BoolConstantsEvaluatesToIntegers) {
1467 io_delegate_.SetFileContents("a/Foo.aidl", "package a; parcelable Foo { const int y = true; }");
1468 CaptureStderr();
1469 auto options = Options::From("aidl -I . --lang java -o out a/Foo.aidl");
1470 EXPECT_TRUE(compile_aidl(options, io_delegate_));
1471 EXPECT_EQ("", GetCapturedStderr());
1472 string code;
1473 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &code));
1474 EXPECT_THAT(code, testing::HasSubstr("public static final int y = 1;"));
1475 }
1476
TEST_F(AidlTest,AidlConstantValue_EvaluatedValue)1477 TEST_F(AidlTest, AidlConstantValue_EvaluatedValue) {
1478 using Ptr = unique_ptr<AidlConstantValue>;
1479 const AidlLocation& loc = AIDL_LOCATION_HERE;
1480
1481 EXPECT_EQ('c', Ptr(AidlConstantValue::Character(loc, "'c'"))->EvaluatedValue<char16_t>());
1482 EXPECT_EQ("abc", Ptr(AidlConstantValue::String(loc, "\"abc\""))->EvaluatedValue<string>());
1483 EXPECT_FLOAT_EQ(1.0f, Ptr(AidlConstantValue::Floating(loc, "1.0f"))->EvaluatedValue<float>());
1484 EXPECT_EQ(true, Ptr(AidlConstantValue::Boolean(loc, true))->EvaluatedValue<bool>());
1485
1486 AidlBinaryConstExpression one_plus_one(loc, Ptr(AidlConstantValue::Integral(loc, "1")), "+",
1487 Ptr(AidlConstantValue::Integral(loc, "1")));
1488 EXPECT_EQ(2, one_plus_one.EvaluatedValue<int32_t>());
1489
1490 auto values = unique_ptr<vector<Ptr>>{new vector<Ptr>};
1491 values->emplace_back(AidlConstantValue::String(loc, "\"hello\""));
1492 values->emplace_back(AidlConstantValue::String(loc, "\"world\""));
1493 vector<string> expected{"hello", "world"};
1494 EXPECT_EQ(
1495 expected,
1496 Ptr(AidlConstantValue::Array(loc, std::move(values)))->EvaluatedValue<vector<string>>());
1497
1498 // evaluate array of floating
1499 vector<float> testFloats({32.f, 14.f, 50.f});
1500 auto testFloatValues = unique_ptr<vector<Ptr>>{new vector<Ptr>()};
1501 testFloatValues->emplace_back(AidlConstantValue::Floating(loc, "32.f"));
1502 testFloatValues->emplace_back(AidlConstantValue::Floating(loc, "14.f"));
1503 testFloatValues->emplace_back(AidlConstantValue::Floating(loc, "50.f"));
1504 EXPECT_EQ(testFloats, Ptr(AidlConstantValue::Array(loc, std::move(testFloatValues)))
1505 ->EvaluatedValue<vector<float>>());
1506 }
1507
1508 // TODO: b/313951203 add floating/string operands test
TEST_F(AidlTest,AidlBinaryConstExpression_CompatibleTypes)1509 TEST_F(AidlTest, AidlBinaryConstExpression_CompatibleTypes) {
1510 const AidlLocation& loc = AIDL_LOCATION_HERE;
1511 static const std::unordered_map<AidlConstantValue::Type,
1512 const std::unordered_set<AidlConstantValue::Type>>
1513 compatibleTypesMap({{AidlConstantValue::Type::BOOLEAN,
1514 {AidlConstantValue::Type::BOOLEAN, AidlConstantValue::Type::INT8,
1515 AidlConstantValue::Type::INT32, AidlConstantValue::Type::INT64}},
1516 {AidlConstantValue::Type::INT8,
1517 {AidlConstantValue::Type::BOOLEAN, AidlConstantValue::Type::INT8,
1518 AidlConstantValue::Type::INT32, AidlConstantValue::Type::INT64}},
1519 {AidlConstantValue::Type::INT32,
1520 {AidlConstantValue::Type::BOOLEAN, AidlConstantValue::Type::INT8,
1521 AidlConstantValue::Type::INT32, AidlConstantValue::Type::INT64}},
1522 {AidlConstantValue::Type::INT64,
1523 {AidlConstantValue::Type::BOOLEAN, AidlConstantValue::Type::INT8,
1524 AidlConstantValue::Type::INT32, AidlConstantValue::Type::INT64}},
1525 {AidlConstantValue::Type::ARRAY, {AidlConstantValue::Type::ARRAY}},
1526 {AidlConstantValue::Type::STRING, {AidlConstantValue::Type::STRING}}});
1527
1528 // go over all possible combination
1529 for (int l = 0; l <= (int)AidlConstantValue::Type::ERROR; ++l) {
1530 for (int r = 0; r <= (int)AidlConstantValue::Type::ERROR; ++r) {
1531 const AidlConstantValue::Type lType = static_cast<AidlConstantValue::Type>(l),
1532 rType = static_cast<AidlConstantValue::Type>(r);
1533 const auto typeItor = compatibleTypesMap.find(lType);
1534 const bool isCompatibleOperandType = typeItor != compatibleTypesMap.end() &&
1535 typeItor->second.find(rType) != typeItor->second.end();
1536 const bool isCompatibleArrayType =
1537 isCompatibleOperandType || (lType == AidlConstantValue::Type::FLOATING &&
1538 rType == AidlConstantValue::Type::FLOATING);
1539 EXPECT_EQ(isCompatibleOperandType,
1540 AidlBinaryConstExpression::AreCompatibleOperandTypes(lType, rType))
1541 << AidlConstantValue::ToString(lType) << ", " << AidlConstantValue::ToString(rType);
1542 EXPECT_EQ(isCompatibleArrayType,
1543 AidlBinaryConstExpression::AreCompatibleArrayTypes(lType, rType))
1544 << AidlConstantValue::ToString(lType) << ", " << AidlConstantValue::ToString(rType);
1545 }
1546 }
1547 }
1548
TEST_F(AidlTest,AidlConstantCharacterDefault)1549 TEST_F(AidlTest, AidlConstantCharacterDefault) {
1550 auto char_type = typenames_.MakeResolvedType(AIDL_LOCATION_HERE, "char", false);
1551 auto default_value = unique_ptr<AidlConstantValue>(AidlConstantValue::Default(*char_type));
1552 EXPECT_EQ("'\\0'", default_value->ValueString(*char_type, cpp::ConstantValueDecorator));
1553 EXPECT_EQ("'\\0'", default_value->ValueString(*char_type, ndk::ConstantValueDecorator));
1554 EXPECT_EQ("'\\0'", default_value->ValueString(*char_type, java::ConstantValueDecorator));
1555 }
1556
TEST_P(AidlTest,FailOnManyDefinedTypes)1557 TEST_P(AidlTest, FailOnManyDefinedTypes) {
1558 AidlError error;
1559 const string expected_stderr =
1560 "ERROR: p/IFoo.aidl:3.33-38: You must declare only one type per file.\n";
1561 CaptureStderr();
1562 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1563 R"(package p;
1564 interface IFoo {}
1565 parcelable IBar {}
1566 parcelable StructuredParcelable {}
1567 interface IBaz {}
1568 )",
1569 typenames_, GetLanguage(), &error));
1570 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1571 // Parse success is important for clear error handling even if the cases aren't
1572 // actually supported in code generation.
1573 EXPECT_EQ(AidlError::BAD_TYPE, error);
1574 }
1575
TEST_P(AidlTest,FailOnNoDefinedTypes)1576 TEST_P(AidlTest, FailOnNoDefinedTypes) {
1577 AidlError error;
1578 const string expected_stderr = "ERROR: p/IFoo.aidl:1.11-11: syntax error, unexpected $end\n";
1579 const string expected_stderr_newbison =
1580 "ERROR: p/IFoo.aidl:1.11-11: syntax error, unexpected end of file\n";
1581 CaptureStderr();
1582 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl", R"(package p;)", typenames_, GetLanguage(), &error));
1583 EXPECT_THAT(GetCapturedStderr(),
1584 testing::AnyOf(testing::Eq(expected_stderr), testing::Eq(expected_stderr_newbison)));
1585 EXPECT_EQ(AidlError::PARSE_ERROR, error);
1586 }
1587
TEST_P(AidlTest,FailOnEmptyListWithComma)1588 TEST_P(AidlTest, FailOnEmptyListWithComma) {
1589 AidlError error;
1590 const string expected_stderr =
1591 "ERROR: p/Foo.aidl:1.45-47: syntax error, unexpected ',', expecting '}'\n";
1592 CaptureStderr();
1593 EXPECT_EQ(nullptr, Parse("p/Foo.aidl", R"(package p; parcelable Foo { uint64_t[] a = { , }; })",
1594 typenames_, GetLanguage(), &error));
1595 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1596 EXPECT_EQ(AidlError::PARSE_ERROR, error);
1597 }
1598
TEST_P(AidlTest,FailOnMalformedConstHexValue)1599 TEST_P(AidlTest, FailOnMalformedConstHexValue) {
1600 AidlError error;
1601 const string expected_stderr =
1602 "ERROR: p/IFoo.aidl:3.50-71: Could not parse hexvalue: 0xffffffffffffffffff\n";
1603 CaptureStderr();
1604 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
1605 R"(package p;
1606 interface IFoo {
1607 const int BAD_HEX_VALUE = 0xffffffffffffffffff;
1608 }
1609 )",
1610 typenames_, GetLanguage(), &error));
1611 EXPECT_EQ(expected_stderr, GetCapturedStderr());
1612 EXPECT_EQ(AidlError::PARSE_ERROR, error);
1613 }
1614
TEST_P(AidlTest,FailOnMalformedQualifiedNameAsIdentifier)1615 TEST_P(AidlTest, FailOnMalformedQualifiedNameAsIdentifier) {
1616 AidlError error;
1617 const string expected_stderr =
1618 "ERROR: p/IFoo.aidl:1.25-26: syntax error, unexpected ';', expecting identifier";
1619 CaptureStderr();
1620 // Notice the trailing dot(.) in the name, which isn't a correct name
1621 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl", R"(package p; parcelable A.; )", typenames_,
1622 GetLanguage(), &error));
1623 EXPECT_THAT(GetCapturedStderr(), HasSubstr(expected_stderr));
1624 EXPECT_EQ(AidlError::PARSE_ERROR, error);
1625 }
1626
TEST_P(AidlTest,FailOnAssigningByteSizeIntToByteWithHelp)1627 TEST_P(AidlTest, FailOnAssigningByteSizeIntToByteWithHelp) {
1628 EvaluateInvalidAssignment(
1629 R"(package a; interface IFoo { const byte INT_VALUE = 0xFF; })",
1630 "Invalid type specifier for an int32 literal: byte (0xFF). Did you mean: 0xFFu8?", typenames_,
1631 GetLanguage());
1632 }
1633
TEST_P(AidlTest,FailOnAssigningDoubleInFloatConst)1634 TEST_P(AidlTest, FailOnAssigningDoubleInFloatConst) {
1635 EvaluateInvalidAssignment(R"(package a; interface IFoo { const float DOUBLE_VALUE = 1.1; })",
1636 INVALID_FLOAT_VALUE, typenames_, GetLanguage());
1637 }
1638
TEST_P(AidlTest,FailOnAssigningFloatInDoubleConst)1639 TEST_P(AidlTest, FailOnAssigningFloatInDoubleConst) {
1640 EvaluateValidAssignment(R"(package a; interface IFoo { const double FLOAT_VALUE = 1.1f; })", "",
1641 typenames_, GetLanguage());
1642 }
1643
TEST_P(AidlTest,FailOnAssigningIntInFloatConst)1644 TEST_P(AidlTest, FailOnAssigningIntInFloatConst) {
1645 EvaluateInvalidAssignment(R"(package a; interface IFoo { const float INT_VALUE = 1; })",
1646 INVALID_INT8_VALUE, typenames_, GetLanguage());
1647 }
1648
TEST_P(AidlTest,FailOnAssigningFloatInIntConst)1649 TEST_P(AidlTest, FailOnAssigningFloatInIntConst) {
1650 EvaluateInvalidAssignment(R"(package a; interface IFoo { const int FLOAT_VALUE = 1.1f; })",
1651 INVALID_FLOAT_VALUE, typenames_, GetLanguage());
1652 }
1653
TEST_P(AidlTest,FailOnAssigningIntInDoubleConst)1654 TEST_P(AidlTest, FailOnAssigningIntInDoubleConst) {
1655 EvaluateInvalidAssignment(R"(package a; interface IFoo { const double INT_VALUE = 1; })",
1656 INVALID_INT8_VALUE, typenames_, GetLanguage());
1657 }
1658
TEST_P(AidlTest,FailOnAssigningDoubleInIntConst)1659 TEST_P(AidlTest, FailOnAssigningDoubleInIntConst) {
1660 EvaluateInvalidAssignment(R"(package a; interface IFoo { const int DOUBLE_VALUE = 1.1; })",
1661 INVALID_FLOAT_VALUE, typenames_, GetLanguage());
1662 }
1663
TEST_P(AidlTest,FailOnAssigningFloatPlusIntConst)1664 TEST_P(AidlTest, FailOnAssigningFloatPlusIntConst) {
1665 EvaluateInvalidAssignment(R"(package a; interface IFoo { const float FLOAT_VALUE = 1.1f + 1; })",
1666 INVALID_OPERATION, typenames_, GetLanguage());
1667 }
1668
TEST_P(AidlTest,FailOnAssigningIntPlusFloatConst)1669 TEST_P(AidlTest, FailOnAssigningIntPlusFloatConst) {
1670 EvaluateInvalidAssignment(R"(package a; interface IFoo { const float FLOAT_VALUE = 1 + 1.1f; })",
1671 INVALID_OPERATION, typenames_, GetLanguage());
1672 }
1673
TEST_P(AidlTest,FailOnAssigningDoublePlusIntConst)1674 TEST_P(AidlTest, FailOnAssigningDoublePlusIntConst) {
1675 EvaluateInvalidAssignment(R"(package a; interface IFoo { const double DOUBLE_VALUE = 1.1 + 1; })",
1676 INVALID_OPERATION, typenames_, GetLanguage());
1677 }
1678
TEST_P(AidlTest,FailOnAssigningIntPlusDoubleConst)1679 TEST_P(AidlTest, FailOnAssigningIntPlusDoubleConst) {
1680 EvaluateInvalidAssignment(R"(package a; interface IFoo { const double DOUBLE_VALUE = 1 + 1.1; })",
1681 INVALID_OPERATION, typenames_, GetLanguage());
1682 }
1683
TEST_P(AidlTest,FailOnAssigningTooLargeFloatConst)1684 TEST_P(AidlTest, FailOnAssigningTooLargeFloatConst) {
1685 EvaluateInvalidAssignment(R"(package a; interface IFoo { const float DOUBLE_VALUE = 1e50f; })",
1686 INVALID_FLOAT_VALUE, typenames_, GetLanguage());
1687 }
1688
TEST_P(AidlTest,FailOnAssigningTooLargeDoubleConst)1689 TEST_P(AidlTest, FailOnAssigningTooLargeDoubleConst) {
1690 EvaluateInvalidAssignment(R"(package a; interface IFoo { const double DOUBLE_VALUE = 1e310; })",
1691 INVALID_FLOAT_VALUE, typenames_, GetLanguage());
1692 }
1693
TEST_P(AidlTest,PassOnAssigningLargeFloatConst)1694 TEST_P(AidlTest, PassOnAssigningLargeFloatConst) {
1695 EvaluateValidAssignment(R"(package a; interface IFoo { const float DOUBLE_VALUE = 1e20f; })", "",
1696 typenames_, GetLanguage());
1697 }
1698
TEST_P(AidlTest,PassOnAssigningLargeDoubleConst)1699 TEST_P(AidlTest, PassOnAssigningLargeDoubleConst) {
1700 EvaluateValidAssignment(R"(package a; interface IFoo { const double DOUBLE_VALUE = 1e150; })", "",
1701 typenames_, GetLanguage());
1702 }
1703
TEST_P(AidlTest,FailOnMalformedQualifiedNameAsPackage)1704 TEST_P(AidlTest, FailOnMalformedQualifiedNameAsPackage) {
1705 AidlError error;
1706 const string expected_stderr =
1707 "ERROR: p/IFoo.aidl:1.11-12: syntax error, unexpected ';', expecting identifier";
1708 CaptureStderr();
1709 // Notice the trailing dot(.) in the package name
1710 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl", R"(package p.; parcelable A; )", typenames_,
1711 GetLanguage(), &error));
1712 EXPECT_THAT(GetCapturedStderr(), HasSubstr(expected_stderr));
1713 EXPECT_EQ(AidlError::PARSE_ERROR, error);
1714 }
1715
TEST_P(AidlTest,ParsePositiveConstHexValue)1716 TEST_P(AidlTest, ParsePositiveConstHexValue) {
1717 AidlError error;
1718 auto parse_result = Parse("p/IFoo.aidl",
1719 R"(package p;
1720 interface IFoo {
1721 const int POSITIVE_HEX_VALUE = 0xf5;
1722 }
1723 )",
1724 typenames_, GetLanguage(), &error);
1725 EXPECT_NE(nullptr, parse_result);
1726 const AidlInterface* interface = parse_result->AsInterface();
1727 ASSERT_NE(nullptr, interface);
1728 const auto& cpp_constants = interface->GetConstantDeclarations();
1729 EXPECT_EQ((size_t)1, cpp_constants.size());
1730 EXPECT_EQ("POSITIVE_HEX_VALUE", cpp_constants[0]->GetName());
1731 EXPECT_TRUE(cpp_constants[0]->CheckValid(typenames_));
1732 EXPECT_EQ("245", cpp_constants[0]->ValueString(cpp::ConstantValueDecorator));
1733 }
1734
TEST_P(AidlTest,ParseNegativeConstHexValue)1735 TEST_P(AidlTest, ParseNegativeConstHexValue) {
1736 AidlError error;
1737 auto parse_result = Parse("p/IFoo.aidl",
1738 R"(package p;
1739 interface IFoo {
1740 const int NEGATIVE_HEX_VALUE = 0xffffffff;
1741 }
1742 )",
1743 typenames_, GetLanguage(), &error);
1744 ASSERT_NE(nullptr, parse_result);
1745 const AidlInterface* interface = parse_result->AsInterface();
1746 ASSERT_NE(nullptr, interface);
1747 const auto& cpp_constants = interface->GetConstantDeclarations();
1748 EXPECT_EQ((size_t)1, cpp_constants.size());
1749 EXPECT_EQ("NEGATIVE_HEX_VALUE", cpp_constants[0]->GetName());
1750 EXPECT_EQ(true, cpp_constants[0]->CheckValid(typenames_));
1751 EXPECT_EQ("-1", cpp_constants[0]->ValueString(cpp::ConstantValueDecorator));
1752 }
1753
TEST_F(AidlTest,ByteAndByteArrayDifferInCpp)1754 TEST_F(AidlTest, ByteAndByteArrayDifferInCpp) {
1755 auto type = Parse("p/Foo.aidl",
1756 R"(
1757 package p;
1758 parcelable Foo {
1759 byte a = -1;
1760 byte[] b = {-1, 1};
1761 @nullable byte[] c = {-1, 1};
1762 }
1763 )",
1764 typenames_, Options::Language::CPP);
1765 ASSERT_NE(nullptr, type);
1766 auto& fields = type->GetFields();
1767 ASSERT_EQ(3ul, fields.size());
1768 EXPECT_EQ("-1", fields[0]->ValueString(cpp::ConstantValueDecorator));
1769 EXPECT_EQ("{uint8_t(-1), 1}", fields[1]->ValueString(cpp::ConstantValueDecorator));
1770 EXPECT_EQ("{{uint8_t(-1), 1}}", fields[2]->ValueString(cpp::ConstantValueDecorator));
1771 }
1772
TEST_F(AidlTest,ByteAndByteArrayDifferInNdk)1773 TEST_F(AidlTest, ByteAndByteArrayDifferInNdk) {
1774 auto type = Parse("p/Foo.aidl",
1775 R"(
1776 package p;
1777 parcelable Foo {
1778 byte a = -1;
1779 byte[] b = {-1, 1};
1780 @nullable byte[] c = {-1, 1};
1781 }
1782 )",
1783 typenames_, Options::Language::NDK);
1784 ASSERT_NE(nullptr, type);
1785 auto& fields = type->GetFields();
1786 ASSERT_EQ(3ul, fields.size());
1787 EXPECT_EQ("-1", fields[0]->ValueString(ndk::ConstantValueDecorator));
1788 EXPECT_EQ("{uint8_t(-1), 1}", fields[1]->ValueString(ndk::ConstantValueDecorator));
1789 EXPECT_EQ("{{uint8_t(-1), 1}}", fields[2]->ValueString(ndk::ConstantValueDecorator));
1790 }
1791
TEST_P(AidlTest,UnderstandsNestedUnstructuredParcelables)1792 TEST_P(AidlTest, UnderstandsNestedUnstructuredParcelables) {
1793 io_delegate_.SetFileContents("p/Outer.aidl",
1794 "package p; parcelable Outer.Inner cpp_header \"baz/header\" "
1795 "ndk_header \"ndk/baz/header\" rust_type \"baz::Inner\";");
1796 import_paths_.emplace("");
1797 const string input_path = "p/IFoo.aidl";
1798 const string input =
1799 "package p; import p.Outer; interface IFoo"
1800 " { Outer.Inner get(); }";
1801
1802 auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
1803 EXPECT_NE(nullptr, parse_result);
1804
1805 EXPECT_TRUE(typenames_.ResolveTypename("p.Outer.Inner").is_resolved);
1806 // C++ uses "::" instead of "." to refer to a inner class.
1807 AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", /*array=*/std::nullopt,
1808 nullptr, {});
1809 EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
1810 }
1811
TEST_P(AidlTest,UnderstandsNestedUnstructuredParcelablesWithoutImports)1812 TEST_P(AidlTest, UnderstandsNestedUnstructuredParcelablesWithoutImports) {
1813 io_delegate_.SetFileContents("p/Outer.aidl",
1814 "package p; parcelable Outer.Inner cpp_header \"baz/header\" "
1815 "ndk_header \"ndk/baz/header\" rust_type \"baz::Inner\";");
1816 import_paths_.emplace("");
1817 const string input_path = "p/IFoo.aidl";
1818 const string input = "package p; interface IFoo { p.Outer.Inner get(); }";
1819
1820 auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
1821 EXPECT_NE(nullptr, parse_result);
1822
1823 EXPECT_TRUE(typenames_.ResolveTypename("p.Outer.Inner").is_resolved);
1824 // C++ uses "::" instead of "." to refer to a inner class.
1825 AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", /*array=*/std::nullopt,
1826 nullptr, {});
1827 EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
1828 }
1829
TEST_F(AidlTest,UnderstandsNestedTypes)1830 TEST_F(AidlTest, UnderstandsNestedTypes) {
1831 io_delegate_.SetFileContents("p/IOuter.aidl",
1832 "package p;\n"
1833 "interface IOuter {\n"
1834 " parcelable Inner {}\n"
1835 "}");
1836 import_paths_.emplace("");
1837 const string input_path = "p/IFoo.aidl";
1838 const string input =
1839 "package p;\n"
1840 "import p.IOuter;\n"
1841 "interface IFoo {\n"
1842 " IOuter.Inner get();\n"
1843 "}";
1844 CaptureStderr();
1845 EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
1846 EXPECT_EQ(GetCapturedStderr(), "");
1847
1848 EXPECT_TRUE(typenames_.ResolveTypename("p.IOuter.Inner").is_resolved);
1849 // C++ uses "::" instead of "." to refer to a inner class.
1850 AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.IOuter.Inner", /*array=*/std::nullopt,
1851 nullptr, {});
1852 EXPECT_EQ("::p::IOuter::Inner", cpp::CppNameOf(nested_type, typenames_));
1853 }
1854
TEST_F(AidlTest,DefinedTypeKnowsItsParentScope)1855 TEST_F(AidlTest, DefinedTypeKnowsItsParentScope) {
1856 const string input_path = "p/IFoo.aidl";
1857 const string input =
1858 "package p;\n"
1859 "interface IFoo {\n"
1860 " parcelable Inner {\n"
1861 " enum Enum { A }\n"
1862 " }\n"
1863 "}";
1864 CaptureStderr();
1865 EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
1866 EXPECT_EQ(GetCapturedStderr(), "");
1867
1868 auto enum_type = typenames_.ResolveTypename("p.IFoo.Inner.Enum");
1869 auto inner_type = typenames_.ResolveTypename("p.IFoo.Inner");
1870 auto ifoo_type = typenames_.ResolveTypename("p.IFoo");
1871 EXPECT_TRUE(enum_type.is_resolved);
1872 EXPECT_TRUE(inner_type.is_resolved);
1873 EXPECT_TRUE(ifoo_type.is_resolved);
1874 // GetParentType()
1875 EXPECT_EQ(inner_type.defined_type, enum_type.defined_type->GetParentType());
1876 EXPECT_EQ(ifoo_type.defined_type, inner_type.defined_type->GetParentType());
1877 EXPECT_EQ(nullptr, ifoo_type.defined_type->GetParentType());
1878 // GetRootType()
1879 EXPECT_EQ(ifoo_type.defined_type, enum_type.defined_type->GetRootType());
1880 EXPECT_EQ(ifoo_type.defined_type, inner_type.defined_type->GetRootType());
1881 EXPECT_EQ(ifoo_type.defined_type, ifoo_type.defined_type->GetRootType());
1882 // GetDocument()
1883 auto main_document = &typenames_.MainDocument();
1884 EXPECT_EQ(main_document, &enum_type.defined_type->GetDocument());
1885 EXPECT_EQ(main_document, &inner_type.defined_type->GetDocument());
1886 EXPECT_EQ(main_document, &ifoo_type.defined_type->GetDocument());
1887 }
1888
TEST_F(AidlTest,UnderstandsNestedTypesViaFullyQualifiedName)1889 TEST_F(AidlTest, UnderstandsNestedTypesViaFullyQualifiedName) {
1890 io_delegate_.SetFileContents("p/IOuter.aidl",
1891 "package p;\n"
1892 "interface IOuter {\n"
1893 " parcelable Inner {}\n"
1894 "}");
1895 import_paths_.emplace("");
1896 const string input_path = "p/IFoo.aidl";
1897 const string input =
1898 "package p;\n"
1899 "interface IFoo {\n"
1900 " p.IOuter.Inner get();\n"
1901 "}";
1902 CaptureStderr();
1903 EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
1904 EXPECT_EQ(GetCapturedStderr(), "");
1905
1906 EXPECT_TRUE(typenames_.ResolveTypename("p.IOuter.Inner").is_resolved);
1907 }
1908
TEST_F(AidlTest,IncludeParentsRawHeaderForNestedInterface)1909 TEST_F(AidlTest, IncludeParentsRawHeaderForNestedInterface) {
1910 CaptureStderr();
1911 EXPECT_NE(nullptr, Parse("p/Outer.aidl",
1912 "package p;\n"
1913 "parcelable Outer {\n"
1914 " interface IInner {}\n"
1915 "}",
1916 typenames_, Options::Language::CPP));
1917
1918 EXPECT_EQ(GetCapturedStderr(), "");
1919 auto resolved = typenames_.ResolveTypename("p.Outer.IInner");
1920 ASSERT_TRUE(resolved.defined_type);
1921 EXPECT_EQ(cpp::HeaderFile(*resolved.defined_type, cpp::ClassNames::CLIENT), "p/Outer.h");
1922 }
1923
TEST_F(AidlTest,UnderstandsNestedTypesViaFullyQualifiedImport)1924 TEST_F(AidlTest, UnderstandsNestedTypesViaFullyQualifiedImport) {
1925 io_delegate_.SetFileContents("p/IOuter.aidl",
1926 "package p;\n"
1927 "interface IOuter {\n"
1928 " parcelable Inner {}\n"
1929 "}");
1930 import_paths_.emplace("");
1931 const string input_path = "p/IFoo.aidl";
1932 const string input =
1933 "package p;\n"
1934 "import p.IOuter.Inner;"
1935 "interface IFoo {\n"
1936 " Inner get();\n"
1937 "}";
1938 CaptureStderr();
1939 EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
1940 EXPECT_EQ(GetCapturedStderr(), "");
1941
1942 EXPECT_TRUE(typenames_.ResolveTypename("p.IOuter.Inner").is_resolved);
1943 }
1944
TEST_F(AidlTest,UnderstandsNestedTypesInTheSameScope)1945 TEST_F(AidlTest, UnderstandsNestedTypesInTheSameScope) {
1946 const string input_path = "p/IFoo.aidl";
1947 const string input =
1948 "package p;\n"
1949 "interface IFoo {\n"
1950 " parcelable Result {}\n"
1951 " Result get();\n"
1952 "}";
1953 CaptureStderr();
1954 EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
1955 EXPECT_EQ(GetCapturedStderr(), "");
1956
1957 EXPECT_TRUE(typenames_.ResolveTypename("p.IFoo.Result").is_resolved);
1958 }
1959
1960 // Finding the type of nested named member.
1961 struct TypeFinder : AidlVisitor {
1962 string name;
1963 const AidlTypeSpecifier* type = nullptr;
TypeFinderandroid::aidl::TypeFinder1964 TypeFinder(std::string name) : name(name) {}
Visitandroid::aidl::TypeFinder1965 void Visit(const AidlVariableDeclaration& v) override {
1966 if (v.GetName() == name) {
1967 type = &v.GetType();
1968 }
1969 }
Visitandroid::aidl::TypeFinder1970 void Visit(const AidlMethod& m) override {
1971 if (m.GetName() == name) {
1972 type = &m.GetType();
1973 }
1974 }
Getandroid::aidl::TypeFinder1975 static string Get(const AidlDefinedType& type, const string& name) {
1976 TypeFinder v(name);
1977 VisitTopDown(v, type);
1978 return v.type ? v.type->Signature() : "(null)";
1979 };
1980 };
1981
TEST_F(AidlTest,UnderstandsNestedTypesViaQualifiedInTheSameScope)1982 TEST_F(AidlTest, UnderstandsNestedTypesViaQualifiedInTheSameScope) {
1983 io_delegate_.SetFileContents("q/IBar.aidl",
1984 "package q;\n"
1985 "interface IBar {\n"
1986 " parcelable Baz {}\n"
1987 "}");
1988 import_paths_.emplace("");
1989 const string input_path = "p/IFoo.aidl";
1990 const string input =
1991 "package p;\n"
1992 "import q.IBar;\n"
1993 "interface IFoo {\n"
1994 " parcelable Nested {\n"
1995 " Baz t1;\n"
1996 " }\n"
1997 " parcelable Baz { }\n"
1998 " IBar.Baz t2();\n"
1999 " Baz t3();\n"
2000 "}";
2001 CaptureStderr();
2002 auto foo = Parse(input_path, input, typenames_, Options::Language::CPP);
2003 EXPECT_EQ(GetCapturedStderr(), "");
2004 ASSERT_NE(nullptr, foo);
2005
2006 EXPECT_EQ(TypeFinder::Get(*foo, "t1"), "p.IFoo.Baz");
2007 EXPECT_EQ(TypeFinder::Get(*foo, "t2"), "q.IBar.Baz");
2008 EXPECT_EQ(TypeFinder::Get(*foo, "t3"), "p.IFoo.Baz");
2009 }
2010
TEST_F(AidlTest,NestedTypeResolutionWithNoPackage)2011 TEST_F(AidlTest, NestedTypeResolutionWithNoPackage) {
2012 const string input_path = "Foo.aidl";
2013 const string input =
2014 "parcelable Foo {\n"
2015 " parcelable Bar {\n"
2016 " enum Baz { BAZ }\n"
2017 " Baz baz = Baz.BAZ;\n"
2018 " }\n"
2019 " Bar bar;\n"
2020 "}";
2021 CaptureStderr();
2022 auto foo = Parse(input_path, input, typenames_, Options::Language::CPP);
2023 EXPECT_EQ(GetCapturedStderr(), "");
2024 ASSERT_NE(nullptr, foo);
2025
2026 EXPECT_EQ(TypeFinder::Get(*foo, "bar"), "Foo.Bar");
2027 EXPECT_EQ(TypeFinder::Get(*foo, "baz"), "Foo.Bar.Baz");
2028 }
2029
TEST_F(AidlTest,RejectsNestedTypesWithParentsName)2030 TEST_F(AidlTest, RejectsNestedTypesWithParentsName) {
2031 const string input_path = "p/Foo.aidl";
2032 const string input =
2033 "package p;\n"
2034 "parcelable Foo {\n"
2035 " parcelable Foo {}\n"
2036 "}";
2037 CaptureStderr();
2038 EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
2039 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Nested type 'Foo' has the same name as its parent."));
2040 }
2041
TEST_F(AidlTest,RejectUnstructuredParcelableAsNestedTypes)2042 TEST_F(AidlTest, RejectUnstructuredParcelableAsNestedTypes) {
2043 const string input_path = "p/IFoo.aidl";
2044 const string input =
2045 "package p;\n"
2046 "interface IFoo {\n"
2047 " parcelable Bar cpp_header \"Bar.h\";\n"
2048 "}";
2049 CaptureStderr();
2050 EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
2051 EXPECT_THAT(GetCapturedStderr(),
2052 HasSubstr("Unstructured parcelables should be at the root scope"));
2053 }
2054
TEST_F(AidlTest,RejectGenericTypeWithNestedTypes)2055 TEST_F(AidlTest, RejectGenericTypeWithNestedTypes) {
2056 const string input_path = "p/Foo.aidl";
2057 const string input =
2058 "package p;\n"
2059 "parcelable Foo<T> {\n"
2060 " parcelable Bar {}\n"
2061 "}";
2062 CaptureStderr();
2063 EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
2064 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Generic types can't have nested types."));
2065 }
2066
TEST_F(AidlTest,HandleSyntaxErrorsInNestedDecl)2067 TEST_F(AidlTest, HandleSyntaxErrorsInNestedDecl) {
2068 const string input_path = "p/IFoo.aidl";
2069 const string input =
2070 "package p;\n"
2071 "interface IFoo {\n"
2072 " parcelable;\n" // missing identifier
2073 "}";
2074 CaptureStderr();
2075 EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
2076 EXPECT_THAT(GetCapturedStderr(), HasSubstr("expecting identifier"));
2077 }
2078
TEST_F(AidlTest,RejectsNestedTypesWithDuplicateNames)2079 TEST_F(AidlTest, RejectsNestedTypesWithDuplicateNames) {
2080 const string input_path = "p/Foo.aidl";
2081 const string input =
2082 "package p;\n"
2083 "interface Foo {\n"
2084 " parcelable Bar {}\n"
2085 " parcelable Bar {}\n"
2086 "}";
2087 CaptureStderr();
2088 EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
2089 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Redefinition of 'Bar'"));
2090 }
2091
TEST_F(AidlTest,TypeResolutionWithMultipleLevelsOfNesting)2092 TEST_F(AidlTest, TypeResolutionWithMultipleLevelsOfNesting) {
2093 struct Failure {
2094 string err;
2095 };
2096 struct TestCase {
2097 string type;
2098 variant<string, Failure> expected; // success<0> or failure<1>
2099 };
2100 vector<TestCase> cases = {
2101 {"foo.A", "foo.A"},
2102 {"foo.A.B", "foo.A.B"},
2103 {"@nullable(heap=true) A", "foo.A.B.A"},
2104 // In the scope of foo.A.B.A, B is resolved to A.B.A.B first.
2105 {"B.A", Failure{"Failed to resolve 'B.A'"}},
2106 {"B", "foo.A.B.A.B"},
2107 {"A.B", "foo.A.B.A.B"},
2108 };
2109 const string input_path = "foo/A.aidl";
2110 for (auto& [type, expected] : cases) {
2111 AidlTypenames typenames;
2112 // clang-format off
2113 const string input =
2114 "package foo;\n"
2115 "parcelable A {\n"
2116 " parcelable B {\n"
2117 " parcelable A {\n"
2118 " parcelable B {\n"
2119 " }\n"
2120 " " + type + " m;\n"
2121 " }\n"
2122 " }\n"
2123 "}";
2124 // clang-format on
2125 CaptureStderr();
2126 auto foo = Parse(input_path, input, typenames, Options::Language::CPP);
2127 if (auto failure = std::get_if<Failure>(&expected); failure) {
2128 ASSERT_EQ(nullptr, foo);
2129 EXPECT_THAT(GetCapturedStderr(), HasSubstr(failure->err));
2130 } else {
2131 EXPECT_EQ(GetCapturedStderr(), "");
2132 ASSERT_NE(nullptr, foo);
2133 EXPECT_EQ(TypeFinder::Get(*foo, "m"), std::get<string>(expected));
2134 }
2135 }
2136 }
2137
TEST_F(AidlTest,HeaderForNestedTypeShouldPointToTopMostParent)2138 TEST_F(AidlTest, HeaderForNestedTypeShouldPointToTopMostParent) {
2139 const string input_path = "p/IFoo.aidl";
2140 const string input =
2141 "package p;\n"
2142 "interface IFoo {\n"
2143 " parcelable Result {}\n"
2144 "}";
2145 CaptureStderr();
2146 auto foo = Parse(input_path, input, typenames_, Options::Language::CPP);
2147 ASSERT_NE(nullptr, foo);
2148 EXPECT_EQ(GetCapturedStderr(), "");
2149
2150 auto result = typenames_.ResolveTypename("p.IFoo.Result").defined_type;
2151 ASSERT_NE(nullptr, result);
2152 EXPECT_EQ("p/IFoo.h", cpp::CppHeaderForType(*result));
2153 }
2154
TEST_F(AidlTest,ReorderNestedTypesForCppOutput)2155 TEST_F(AidlTest, ReorderNestedTypesForCppOutput) {
2156 const string input_path = "p/IFoo.aidl";
2157 const string input = R"(
2158 package p;
2159 interface IFoo {
2160 // partial orderings for [A, D, G]:
2161 // D - A
2162 // A - G
2163 parcelable A {
2164 // partial orderings for [B, C]:
2165 // C - B
2166 parcelable B {
2167 C c;
2168 D.E d;
2169 }
2170 parcelable C {}
2171 }
2172 parcelable D {
2173 // partial orderings for [E, F]:
2174 // F - E
2175 parcelable E {
2176 F f;
2177 }
2178 parcelable F {}
2179 }
2180 parcelable G {
2181 A.B b;
2182 }
2183 }
2184 )";
2185 Options options = Options::From("aidl --lang cpp -I. -oout -hout p/IFoo.aidl");
2186 io_delegate_.SetFileContents(input_path, input);
2187 CaptureStderr();
2188 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2189 EXPECT_EQ(GetCapturedStderr(), "");
2190
2191 string code;
2192 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/p/IFoo.h", &code));
2193 // check partial orderings: a should comes before b
2194 EXPECT_LE(code.find("class D"), code.find("class A"));
2195 EXPECT_LE(code.find("class A"), code.find("class G"));
2196 EXPECT_LE(code.find("class C"), code.find("class B"));
2197 EXPECT_LE(code.find("class F"), code.find("class E"));
2198 }
2199
TEST_F(AidlTest,RejectsNestedTypesWithCyclicDeps)2200 TEST_F(AidlTest, RejectsNestedTypesWithCyclicDeps) {
2201 const string input_path = "p/IFoo.aidl";
2202 const string input = R"(
2203 package p;
2204 interface IFoo {
2205 // Cycles:
2206 // D - A
2207 // A - G
2208 // G - D
2209 parcelable A {
2210 parcelable B {
2211 C c;
2212 }
2213 }
2214 parcelable C {
2215 parcelable D {
2216 E e;
2217 }
2218 }
2219 parcelable E {
2220 parcelable F {
2221 A a;
2222 }
2223 }
2224 }
2225 )";
2226 Options options = Options::From("aidl --lang cpp -I. -oout -hout p/IFoo.aidl");
2227 io_delegate_.SetFileContents(input_path, input);
2228 CaptureStderr();
2229 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2230 EXPECT_THAT(GetCapturedStderr(), HasSubstr("IFoo has nested types with cyclic references."));
2231 }
2232
TEST_F(AidlTest,RejectsCyclicNestedInterfaces)2233 TEST_F(AidlTest, RejectsCyclicNestedInterfaces) {
2234 Options options = Options::From(
2235 "aidl --lang cpp -I. -oout -hout "
2236 "p/IFoo.aidl p/IBar.aidl p/IQux.aidl");
2237 io_delegate_.SetFileContents("p/IFoo.aidl",
2238 "package p; import p.IBar; "
2239 "interface IFoo { IBar getBar(); }");
2240 io_delegate_.SetFileContents("p/IBar.aidl",
2241 "package p; import p.IQux; "
2242 "interface IBar { IQux.Inner getQux(); }");
2243 io_delegate_.SetFileContents("p/IQux.aidl",
2244 "package p; import p.IFoo; "
2245 "interface IQux { interface Inner { IFoo getFoo(); } }");
2246 CaptureStderr();
2247 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2248 EXPECT_THAT(GetCapturedStderr(),
2249 HasSubstr("ERROR: p/IQux.aidl:1.43-53: has cyclic references to nested types."));
2250 }
2251
TEST_F(AidlTest,RejectsCyclicNestedInterfacesAndParcelables)2252 TEST_F(AidlTest, RejectsCyclicNestedInterfacesAndParcelables) {
2253 Options options = Options::From(
2254 "aidl --lang cpp -I. -oout -hout "
2255 "p/IFoo.aidl p/Bar.aidl");
2256 io_delegate_.SetFileContents("p/IFoo.aidl",
2257 "package p; import p.Bar; "
2258 "interface IFoo { interface Inner { Bar getBar(); } }");
2259 io_delegate_.SetFileContents("p/Bar.aidl",
2260 "package p; import p.IFoo; "
2261 "parcelable Bar { IFoo.Inner foo; }");
2262 CaptureStderr();
2263 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2264 EXPECT_THAT(GetCapturedStderr(),
2265 HasSubstr("ERROR: p/IFoo.aidl:1.42-52: has cyclic references to nested types."));
2266 }
2267
TEST_F(AidlTest,CppNameOf_GenericType)2268 TEST_F(AidlTest, CppNameOf_GenericType) {
2269 const string input_path = "p/Wrapper.aidl";
2270 const string input = "package p; parcelable Wrapper<T> {}";
2271
2272 auto parse_result = Parse(input_path, input, typenames_, Options::Language::CPP);
2273 EXPECT_NE(nullptr, parse_result);
2274
2275 auto type = [](std::string name, auto&&... type_params) -> std::unique_ptr<AidlTypeSpecifier> {
2276 auto params = new std::vector<std::unique_ptr<AidlTypeSpecifier>>;
2277 (..., params->emplace_back(std::move(type_params)));
2278 return std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, name, std::nullopt, params,
2279 Comments{});
2280 };
2281
2282 auto set_nullable = [](std::unique_ptr<AidlTypeSpecifier>&& type) {
2283 std::vector<std::unique_ptr<AidlAnnotation>> annotations;
2284 annotations.emplace_back(std::unique_ptr<AidlAnnotation>(
2285 AidlAnnotation::Parse(AIDL_LOCATION_HERE, "nullable", {}, {})));
2286 type->Annotate(std::move(annotations));
2287 return std::move(type);
2288 };
2289
2290 auto set_array = [](std::unique_ptr<AidlTypeSpecifier>&& type) {
2291 (void)type->MakeArray(DynamicArray{});
2292 return std::move(type);
2293 };
2294
2295 auto w = type("p.Wrapper", type("String"));
2296 EXPECT_EQ("::p::Wrapper<::android::String16>", cpp::CppNameOf(*w, typenames_));
2297
2298 auto nullable_w = set_nullable(type("p.Wrapper", type("String")));
2299 EXPECT_EQ("::std::optional<::p::Wrapper<::android::String16>>",
2300 cpp::CppNameOf(*nullable_w, typenames_));
2301
2302 auto array_w = set_array(type("p.Wrapper", type("String")));
2303 EXPECT_EQ("::std::vector<::p::Wrapper<::android::String16>>",
2304 cpp::CppNameOf(*array_w, typenames_));
2305
2306 auto nullable_array_w = set_nullable(set_array(type("p.Wrapper", type("String"))));
2307 EXPECT_EQ("::std::optional<::std::vector<::std::optional<::p::Wrapper<::android::String16>>>>",
2308 cpp::CppNameOf(*nullable_array_w, typenames_));
2309
2310 auto list_w = type("List", type("p.Wrapper", type("String")));
2311 EXPECT_EQ("::std::vector<::p::Wrapper<::android::String16>>",
2312 cpp::CppNameOf(*list_w, typenames_));
2313
2314 auto nullable_list_w = set_nullable(type("List", type("p.Wrapper", type("String"))));
2315 EXPECT_EQ("::std::optional<::std::vector<::std::optional<::p::Wrapper<::android::String16>>>>",
2316 cpp::CppNameOf(*nullable_list_w, typenames_));
2317 }
2318
TEST_P(AidlTest,UnderstandsNativeParcelables)2319 TEST_P(AidlTest, UnderstandsNativeParcelables) {
2320 io_delegate_.SetFileContents("p/Bar.aidl",
2321 "package p; parcelable Bar cpp_header \"baz/header\";");
2322 import_paths_.emplace("");
2323 const string input_path = "p/IFoo.aidl";
2324 const string input = "package p; import p.Bar; interface IFoo { }";
2325 auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
2326 EXPECT_NE(nullptr, parse_result);
2327 EXPECT_TRUE(typenames_.ResolveTypename("p.Bar").is_resolved);
2328 AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", /*array=*/std::nullopt, nullptr, {});
2329 native_type.Resolve(typenames_, parse_result);
2330
2331 EXPECT_EQ("p.Bar", java::InstantiableJavaSignatureOf(native_type));
2332 // C++ understands C++ specific stuff
2333 EXPECT_EQ("::p::Bar", cpp::CppNameOf(native_type, typenames_));
2334 set<string> headers;
2335 cpp::AddHeaders(native_type, typenames_, &headers);
2336 EXPECT_EQ(1u, headers.size());
2337 EXPECT_EQ(1u, headers.count("baz/header"));
2338 }
2339
TEST_F(AidlTest,WritesCorrectDependencyFile)2340 TEST_F(AidlTest, WritesCorrectDependencyFile) {
2341 // While the in tree build system always gives us an output file name,
2342 // other android tools take advantage of our ability to infer the intended
2343 // file name. This test makes sure we handle this correctly.
2344 vector<string> args = {"aidl", "-I .", "-d dep/file/path", "-o place/for/output", "p/IFoo.aidl"};
2345 Options options = Options::From(args);
2346 io_delegate_.SetFileContents(options.InputFiles().front(), "package p; interface IFoo {}");
2347 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2348 string actual_dep_file_contents;
2349 EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
2350 EXPECT_EQ(actual_dep_file_contents, kExpectedDepFileContents);
2351 }
2352
TEST_F(AidlTest,WritesCorrectDependencyFileNinja)2353 TEST_F(AidlTest, WritesCorrectDependencyFileNinja) {
2354 // While the in tree build system always gives us an output file name,
2355 // other android tools take advantage of our ability to infer the intended
2356 // file name. This test makes sure we handle this correctly.
2357 vector<string> args = {"aidl", "-I .", "-d dep/file/path", "--ninja", "-o place/for/output",
2358 "p/IFoo.aidl"};
2359 Options options = Options::From(args);
2360 io_delegate_.SetFileContents(options.InputFiles().front(), "package p; interface IFoo {}");
2361 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2362 string actual_dep_file_contents;
2363 EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
2364 EXPECT_EQ(actual_dep_file_contents, kExpectedNinjaDepFileContents);
2365 }
2366
TEST_F(AidlTest,WritesTrivialDependencyFileForParcelableDeclaration)2367 TEST_F(AidlTest, WritesTrivialDependencyFileForParcelableDeclaration) {
2368 // The SDK uses aidl to decide whether a .aidl file is a parcelable. It does
2369 // this by calling aidl with every .aidl file it finds, then parsing the
2370 // generated dependency files. Those that reference .java output files are
2371 // for interfaces and those that do not are parcelables. However, for both
2372 // parcelables and interfaces, we *must* generate a non-empty dependency file.
2373 vector<string> args = {"aidl", "-I .", "-o place/for/output", "-d dep/file/path", "p/Foo.aidl"};
2374 Options options = Options::From(args);
2375 io_delegate_.SetFileContents(options.InputFiles().front(), "package p; parcelable Foo;");
2376 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2377 string actual_dep_file_contents;
2378 EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
2379 EXPECT_EQ(actual_dep_file_contents, kExpectedParcelableDeclarationDepFileContents);
2380 }
2381
TEST_F(AidlTest,WritesDependencyFileForStructuredParcelable)2382 TEST_F(AidlTest, WritesDependencyFileForStructuredParcelable) {
2383 vector<string> args = {
2384 "aidl", "-I .", "--structured", "-o place/for/output", "-d dep/file/path", "p/Foo.aidl"};
2385 Options options = Options::From(args);
2386 io_delegate_.SetFileContents(options.InputFiles().front(), "package p; parcelable Foo {int a;}");
2387 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2388 string actual_dep_file_contents;
2389 EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
2390 EXPECT_EQ(actual_dep_file_contents, kExpectedStructuredParcelableDepFileContents);
2391 }
2392
TEST_F(AidlTest,NoJavaOutputForParcelableDeclaration)2393 TEST_F(AidlTest, NoJavaOutputForParcelableDeclaration) {
2394 vector<string> args = {"aidl", "-I .", "--lang=java", "-o place/for/output", "p/Foo.aidl"};
2395 Options options = Options::From(args);
2396 io_delegate_.SetFileContents(options.InputFiles().front(), "package p; parcelable Foo;");
2397 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2398 string output_file_contents;
2399 EXPECT_FALSE(io_delegate_.GetWrittenContents(options.OutputFile(), &output_file_contents));
2400 }
2401
TEST_P(AidlTest,RejectsListArray)2402 TEST_P(AidlTest, RejectsListArray) {
2403 const string input = "package a; parcelable Foo { List<String>[] lists; }";
2404 CaptureStderr();
2405 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", input, typenames_, GetLanguage()));
2406 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Arrays of List are not supported"));
2407 }
2408
TEST_P(AidlTest,RejectsPrimitiveListInStableAidl)2409 TEST_P(AidlTest, RejectsPrimitiveListInStableAidl) {
2410 AidlError error;
2411 string expected_stderr =
2412 "ERROR: a/IFoo.aidl:2.7-11: "
2413 "Encountered an untyped List or Map. The use of untyped List/Map is "
2414 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
2415 "the receiving side. Consider switching to an array or a generic List/Map.\n";
2416 if (GetLanguage() != Options::Language::JAVA) {
2417 expected_stderr =
2418 "ERROR: a/IFoo.aidl:2.1-7: "
2419 "Currently, only the Java backend supports non-generic List.\n";
2420 }
2421
2422 const string primitive_interface =
2423 "package a; interface IFoo {\n"
2424 " List foo(); }";
2425 CaptureStderr();
2426 AidlTypenames tn1;
2427 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_interface, tn1, GetLanguage(), &error,
2428 {"--structured"}));
2429 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2430
2431 string primitive_parcelable =
2432 "package a; parcelable IFoo {\n"
2433 " List foo;}";
2434 CaptureStderr();
2435 AidlTypenames tn2;
2436 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", primitive_parcelable, tn2, GetLanguage(), &error,
2437 {"--structured"}));
2438 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2439 }
2440
TEST_P(AidlTest,ExtensionTest)2441 TEST_P(AidlTest, ExtensionTest) {
2442 CaptureStderr();
2443 string extendable_parcelable =
2444 "package a; parcelable Data {\n"
2445 " ParcelableHolder extension;\n"
2446 " ParcelableHolder extension2;\n"
2447 "}";
2448 EXPECT_NE(nullptr, Parse("a/Data.aidl", extendable_parcelable, typenames_, GetLanguage()));
2449 EXPECT_EQ("", GetCapturedStderr());
2450 }
2451
TEST_P(AidlTest,ParcelableHolderAsReturnType)2452 TEST_P(AidlTest, ParcelableHolderAsReturnType) {
2453 CaptureStderr();
2454 string parcelableholder_return_interface =
2455 "package a; interface IFoo {\n"
2456 " ParcelableHolder foo();\n"
2457 "}";
2458 EXPECT_EQ(nullptr,
2459 Parse("a/IFoo.aidl", parcelableholder_return_interface, typenames_, GetLanguage()));
2460
2461 EXPECT_EQ("ERROR: a/IFoo.aidl:2.19-23: ParcelableHolder cannot be a return type\n",
2462 GetCapturedStderr());
2463 }
2464
TEST_P(AidlTest,ParcelableHolderAsArgumentType)2465 TEST_P(AidlTest, ParcelableHolderAsArgumentType) {
2466 CaptureStderr();
2467 string extendable_parcelable_arg_interface =
2468 "package a; interface IFoo {\n"
2469 " void foo(in ParcelableHolder ph);\n"
2470 "}";
2471 EXPECT_EQ(nullptr,
2472 Parse("a/IFoo.aidl", extendable_parcelable_arg_interface, typenames_, GetLanguage()));
2473
2474 EXPECT_EQ("ERROR: a/IFoo.aidl:2.31-34: ParcelableHolder cannot be an argument type\n",
2475 GetCapturedStderr());
2476 }
2477
TEST_P(AidlTest,RejectNullableParcelableHolderField)2478 TEST_P(AidlTest, RejectNullableParcelableHolderField) {
2479 io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo { @nullable ParcelableHolder ext; }");
2480 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
2481 const string expected_stderr = "ERROR: Foo.aidl:1.27-44: ParcelableHolder cannot be nullable.\n";
2482 CaptureStderr();
2483 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2484 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2485 }
2486
TEST_P(AidlTest,ParcelablesWithConstants)2487 TEST_P(AidlTest, ParcelablesWithConstants) {
2488 io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo { const int BIT = 0x1 << 3; }");
2489 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
2490 CaptureStderr();
2491 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2492 EXPECT_EQ("", GetCapturedStderr());
2493 }
2494
TEST_P(AidlTest,UnionWithConstants)2495 TEST_P(AidlTest, UnionWithConstants) {
2496 io_delegate_.SetFileContents("Foo.aidl", "union Foo { const int BIT = 0x1 << 3; int n; }");
2497 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
2498 CaptureStderr();
2499 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2500 EXPECT_EQ("", GetCapturedStderr());
2501 }
2502
TEST_F(AidlTest,ConstantsWithAnnotations)2503 TEST_F(AidlTest, ConstantsWithAnnotations) {
2504 io_delegate_.SetFileContents("IFoo.aidl",
2505 "interface IFoo {\n"
2506 " @JavaPassthrough(annotation=\"@Foo\")\n"
2507 " const @JavaPassthrough(annotation=\"@Bar\") int FOO = 0;\n"
2508 "}");
2509 Options options = Options::From("aidl IFoo.aidl -I . --lang=java -o out");
2510 CaptureStderr();
2511 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2512 EXPECT_EQ("", GetCapturedStderr());
2513 string code;
2514 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/IFoo.java", &code));
2515 EXPECT_THAT(code, HasSubstr("@Foo\n"));
2516 EXPECT_THAT(code, HasSubstr("@Bar\n"));
2517 }
2518
TEST_F(AidlTest,ApiDump)2519 TEST_F(AidlTest, ApiDump) {
2520 io_delegate_.SetFileContents(
2521 "foo/bar/IFoo.aidl",
2522 "// comment\n"
2523 "package foo.bar;\n"
2524 "import foo.bar.Data;\n"
2525 "// commented /* @hide */\n"
2526 "interface IFoo {\n"
2527 " /* @hide applied \n"
2528 " @deprecated use foo2 */\n"
2529 " int foo(out int[] a, String b, boolean c, inout List<String> d);\n"
2530 " int foo2(@utf8InCpp String x, inout List<String> y);\n"
2531 " IFoo foo3(IFoo foo);\n"
2532 " void foo4(in int[2][3] fixedArray);\n"
2533 " Data getData();\n"
2534 " // @hide not applied\n"
2535 " /** blahblah\n"
2536 " @deprecated\n"
2537 " reason why... */\n"
2538 " const int A = 1;\n"
2539 " // @deprecated tags in line comments are ignored\n"
2540 " const String STR = \"Hello\";\n"
2541 "}\n");
2542 io_delegate_.SetFileContents("foo/bar/Data.aidl",
2543 "// comment\n"
2544 "package foo.bar;\n"
2545 "import foo.bar.IFoo;\n"
2546 "@JavaDerive(equals=true, toString=true)\n"
2547 "/* @hide*/\n"
2548 "parcelable Data {\n"
2549 " // @hide\n"
2550 " int x = 10;\n"
2551 " // @hide\n"
2552 " int y;\n"
2553 " /*@hide2*/\n"
2554 " IFoo foo;\n"
2555 " // Ignore @hide property in line comment\n"
2556 " @nullable String[] c;\n"
2557 "}\n");
2558 io_delegate_.SetFileContents("api.aidl", "");
2559 vector<string> args = {"aidl", "--dumpapi", "--out=dump",
2560 "--include=.", "foo/bar/IFoo.aidl", "foo/bar/Data.aidl"};
2561 Options options = Options::From(args);
2562 bool result = dump_api(options, io_delegate_);
2563 ASSERT_TRUE(result);
2564 string actual;
2565 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/IFoo.aidl", &actual));
2566 EXPECT_EQ(string("// comment\n").append(string(kPreamble)).append(R"(package foo.bar;
2567 interface IFoo {
2568 /**
2569 * @hide
2570 * @deprecated use foo2
2571 */
2572 int foo(out int[] a, String b, boolean c, inout List<String> d);
2573 int foo2(@utf8InCpp String x, inout List<String> y);
2574 foo.bar.IFoo foo3(foo.bar.IFoo foo);
2575 void foo4(in int[2][3] fixedArray);
2576 foo.bar.Data getData();
2577 /**
2578 * @deprecated reason why...
2579 */
2580 const int A = 1;
2581 const String STR = "Hello";
2582 }
2583 )"),
2584 actual);
2585
2586 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Data.aidl", &actual));
2587 EXPECT_EQ(string("// comment\n").append(string(kPreamble)).append(R"(package foo.bar;
2588 /* @hide */
2589 @JavaDerive(equals=true, toString=true)
2590 parcelable Data {
2591 int x = 10;
2592 int y;
2593 foo.bar.IFoo foo;
2594 @nullable String[] c;
2595 }
2596 )"),
2597 actual);
2598 }
2599
TEST_F(AidlTest,ApiDumpWithManualIds)2600 TEST_F(AidlTest, ApiDumpWithManualIds) {
2601 io_delegate_.SetFileContents("foo/bar/IFoo.aidl",
2602 "package foo.bar;\n"
2603 "interface IFoo {\n"
2604 " int foo() = 1;\n"
2605 " int bar() = 2;\n"
2606 " int baz() = 10;\n"
2607 "}\n");
2608
2609 vector<string> args = {"aidl", "-I . ", "--dumpapi", "-o dump", "foo/bar/IFoo.aidl"};
2610 Options options = Options::From(args);
2611 bool result = dump_api(options, io_delegate_);
2612 ASSERT_TRUE(result);
2613 string actual;
2614 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/IFoo.aidl", &actual));
2615 EXPECT_EQ(actual, string(kPreamble).append(R"(package foo.bar;
2616 interface IFoo {
2617 int foo() = 1;
2618 int bar() = 2;
2619 int baz() = 10;
2620 }
2621 )"));
2622 }
2623
TEST_F(AidlTest,ApiDumpWithManualIdsOnlyOnSomeMethods)2624 TEST_F(AidlTest, ApiDumpWithManualIdsOnlyOnSomeMethods) {
2625 const string expected_stderr =
2626 "ERROR: foo/bar/IFoo.aidl:4.8-12: You must either assign id's to all methods or to none of "
2627 "them.\n";
2628 io_delegate_.SetFileContents("foo/bar/IFoo.aidl",
2629 "package foo.bar;\n"
2630 "interface IFoo {\n"
2631 " int foo() = 1;\n"
2632 " int bar();\n"
2633 " int baz() = 10;\n"
2634 "}\n");
2635
2636 vector<string> args = {"aidl", "-I . ", "--dumpapi", "-o dump", "foo/bar/IFoo.aidl"};
2637 Options options = Options::From(args);
2638 CaptureStderr();
2639 EXPECT_FALSE(dump_api(options, io_delegate_));
2640 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2641 }
2642
TEST_F(AidlTest,ApiDumpConstWithAnnotation)2643 TEST_F(AidlTest, ApiDumpConstWithAnnotation) {
2644 io_delegate_.SetFileContents("foo/bar/IFoo.aidl",
2645 "package foo.bar;\n"
2646 "interface IFoo {\n"
2647 " @utf8InCpp String foo();\n"
2648 " const @utf8InCpp String bar = \"bar\";\n"
2649 "}\n");
2650
2651 vector<string> args = {"aidl", "-I . ", "--dumpapi", "-o dump", "foo/bar/IFoo.aidl"};
2652 Options options = Options::From(args);
2653 CaptureStderr();
2654 EXPECT_TRUE(dump_api(options, io_delegate_));
2655 EXPECT_EQ("", GetCapturedStderr());
2656 string actual;
2657 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/IFoo.aidl", &actual));
2658 EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
2659 interface IFoo {
2660 @utf8InCpp String foo();
2661 const @utf8InCpp String bar = "bar";
2662 }
2663 )"),
2664 actual);
2665 }
2666
TEST_F(AidlTest,ApiDumpWithEnums)2667 TEST_F(AidlTest, ApiDumpWithEnums) {
2668 io_delegate_.SetFileContents("foo/bar/Enum.aidl",
2669 "package foo.bar;\n"
2670 "enum Enum {\n"
2671 " FOO,\n"
2672 " BAR = FOO + 1,\n"
2673 "}\n");
2674
2675 vector<string> args = {"aidl", "--dumpapi", "-I . ", "-o dump", "foo/bar/Enum.aidl"};
2676 Options options = Options::From(args);
2677 CaptureStderr();
2678 EXPECT_TRUE(dump_api(options, io_delegate_));
2679 EXPECT_EQ("", GetCapturedStderr());
2680 string actual;
2681 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Enum.aidl", &actual));
2682 EXPECT_EQ(string(kPreamble).append("package foo.bar;\n"
2683 "enum Enum {\n"
2684 " FOO,\n"
2685 " BAR = (FOO + 1) /* 1 */,\n"
2686 "}\n"),
2687 actual);
2688 }
2689
TEST_F(AidlTest,ApiDumpWithEnumDefaultValues)2690 TEST_F(AidlTest, ApiDumpWithEnumDefaultValues) {
2691 io_delegate_.SetFileContents("foo/bar/Enum.aidl",
2692 "package foo.bar;\n"
2693 "enum Enum {\n"
2694 " FOO,\n"
2695 "}\n");
2696 io_delegate_.SetFileContents("foo/bar/Foo.aidl",
2697 "package foo.bar;\n"
2698 "import foo.bar.Enum;\n"
2699 "parcelable Foo {\n"
2700 " Enum e = Enum.FOO;\n"
2701 " int n = Enum.FOO;\n"
2702 "}\n");
2703
2704 vector<string> args = {"aidl", "--dumpapi", "-I . ", "-o dump", "foo/bar/Foo.aidl"};
2705 Options options = Options::From(args);
2706 CaptureStderr();
2707 EXPECT_TRUE(dump_api(options, io_delegate_));
2708 EXPECT_EQ("", GetCapturedStderr());
2709 string actual;
2710 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Foo.aidl", &actual));
2711 EXPECT_EQ(string(kPreamble).append("package foo.bar;\n"
2712 "parcelable Foo {\n"
2713 " foo.bar.Enum e = foo.bar.Enum.FOO;\n"
2714 " int n = foo.bar.Enum.FOO /* 0 */;\n"
2715 "}\n"),
2716 actual);
2717 }
2718
TEST_F(AidlTest,ApiDumpWithGenerics)2719 TEST_F(AidlTest, ApiDumpWithGenerics) {
2720 io_delegate_.SetFileContents("foo/bar/Foo.aidl",
2721 "package foo.bar;\n"
2722 "parcelable Foo<T, U> {\n"
2723 "}\n");
2724
2725 vector<string> args = {"aidl", "--dumpapi", "-I . ", "-o dump", "foo/bar/Foo.aidl"};
2726 Options options = Options::From(args);
2727 CaptureStderr();
2728 EXPECT_TRUE(dump_api(options, io_delegate_));
2729 EXPECT_EQ("", GetCapturedStderr());
2730 string actual;
2731 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Foo.aidl", &actual));
2732 EXPECT_EQ(string(kPreamble).append("package foo.bar;\n"
2733 "parcelable Foo<T, U> {\n"
2734 "}\n"),
2735 actual);
2736 }
2737
TEST_F(AidlTest,ImportedDocumentHasDuplicateDefinitions)2738 TEST_F(AidlTest, ImportedDocumentHasDuplicateDefinitions) {
2739 io_delegate_.SetFileContents("IFoo.aidl", "interface IFoo; interface IFoo;\n");
2740 io_delegate_.SetFileContents("Bar.aidl", "enum Bar { CONST = IFoo.NONE }\n");
2741
2742 vector<string> args = {"aidl", "--dumpapi", "-I.", "-o out", "Bar.aidl"};
2743 Options options = Options::From(args);
2744 CaptureStderr();
2745 EXPECT_FALSE(dump_api(options, io_delegate_));
2746 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Can't find NONE in IFoo"));
2747 }
2748
TEST_F(AidlTest,CheckNumGenericTypeSecifier)2749 TEST_F(AidlTest, CheckNumGenericTypeSecifier) {
2750 const string expected_list_stderr =
2751 "ERROR: p/IFoo.aidl:1.37-41: List can only have one type parameter, but got: "
2752 "'List<String,String>'\n";
2753 const string expected_map_stderr =
2754 "ERROR: p/IFoo.aidl:1.37-40: Map must have 0 or 2 type parameters, but got 'Map<String>'\n";
2755 Options options = Options::From("aidl -I . p/IFoo.aidl IFoo.java");
2756 io_delegate_.SetFileContents(options.InputFiles().front(),
2757 "package p; interface IFoo {"
2758 "void foo(List<String, String> a);}");
2759 CaptureStderr();
2760 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2761 EXPECT_EQ(expected_list_stderr, GetCapturedStderr());
2762
2763 io_delegate_.SetFileContents(options.InputFiles().front(),
2764 "package p; interface IFoo {"
2765 "void foo(Map<String> a);}");
2766 CaptureStderr();
2767 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2768 EXPECT_EQ(expected_map_stderr, GetCapturedStderr());
2769 }
2770
TEST_F(AidlTest,CheckTypeParameterInMapType)2771 TEST_F(AidlTest, CheckTypeParameterInMapType) {
2772 const string expected_stderr =
2773 "ERROR: p/IFoo.aidl:1.28-31: The type of key in map must be String, but it is 'p.Bar'\n";
2774 Options options = Options::From("aidl -I . p/IFoo.aidl");
2775 io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar { String s; }");
2776
2777 io_delegate_.SetFileContents("p/IFoo.aidl",
2778 "package p; interface IFoo {"
2779 "Map<String, p.Bar> foo();}");
2780 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2781
2782 io_delegate_.SetFileContents("p/IFoo.aidl",
2783 "package p; interface IFoo {"
2784 "Map<p.Bar, p.Bar> foo();}");
2785 CaptureStderr();
2786 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2787 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2788
2789 io_delegate_.SetFileContents("p/IFoo.aidl",
2790 "package p; interface IFoo {"
2791 "Map<String, String> foo();}");
2792 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2793
2794 io_delegate_.SetFileContents("p/IFoo.aidl",
2795 "package p; interface IFoo {"
2796 "Map<String, ParcelFileDescriptor> foo();}");
2797 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2798 }
2799
TEST_F(AidlTest,WrongGenericType)2800 TEST_F(AidlTest, WrongGenericType) {
2801 const string expected_stderr = "ERROR: p/IFoo.aidl:1.28-34: String is not a generic type.\n";
2802 Options options = Options::From("aidl -I . p/IFoo.aidl IFoo.java");
2803 io_delegate_.SetFileContents(options.InputFiles().front(),
2804 "package p; interface IFoo {"
2805 "String<String> foo(); }");
2806 CaptureStderr();
2807 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2808 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2809 }
2810
TEST_F(AidlTest,UserDefinedUnstructuredGenericParcelableType)2811 TEST_F(AidlTest, UserDefinedUnstructuredGenericParcelableType) {
2812 Options optionsForParcelable = Options::From("aidl -I . p/Bar.aidl");
2813 io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T, T>;");
2814 CaptureStderr();
2815 EXPECT_FALSE(compile_aidl(optionsForParcelable, io_delegate_));
2816 EXPECT_EQ("ERROR: p/Bar.aidl:1.22-26: Every type parameter should be unique.\n",
2817 GetCapturedStderr());
2818
2819 Options options = Options::From("aidl -I . p/IFoo.aidl");
2820 io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar;");
2821 io_delegate_.SetFileContents("p/IFoo.aidl",
2822 "package p; interface IFoo {"
2823 "p.Bar<String, String> foo();}");
2824 CaptureStderr();
2825 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2826 EXPECT_THAT(GetCapturedStderr(), HasSubstr("p.Bar is not a generic type"));
2827 io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T>;");
2828 CaptureStderr();
2829 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2830 EXPECT_THAT(GetCapturedStderr(), HasSubstr("p.Bar must have 1 type parameters, but got 2"));
2831 io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T, V>;");
2832 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2833 io_delegate_.SetFileContents("p/IFoo.aidl",
2834 "package p; interface IFoo {"
2835 "p.Bar<String, ParcelFileDescriptor> foo();}");
2836 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2837
2838 io_delegate_.SetFileContents("p/IFoo.aidl",
2839 "package p; interface IFoo {"
2840 "p.Bar<int, long> foo();}");
2841
2842 io_delegate_.SetFileContents("p/IFoo.aidl",
2843 "package p; interface IFoo {"
2844 "p.Bar<int[], long[]> foo();}");
2845
2846 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2847 }
2848
TEST_F(AidlTest,FailOnMultipleTypesInSingleFile)2849 TEST_F(AidlTest, FailOnMultipleTypesInSingleFile) {
2850 std::vector<std::string> rawOptions{"aidl --lang=java -I . -o out foo/bar/Foo.aidl",
2851 "aidl --lang=cpp -I . -o out -h out/include foo/bar/Foo.aidl",
2852 "aidl --lang=rust -I . -o out foo/bar/Foo.aidl"};
2853 for (const auto& rawOption : rawOptions) {
2854 string expected_stderr =
2855 "ERROR: foo/bar/Foo.aidl:3.1-10: You must declare only one type per file.\n";
2856 Options options = Options::From(rawOption);
2857 io_delegate_.SetFileContents(options.InputFiles().front(),
2858 "package foo.bar;\n"
2859 "interface IFoo1 { int foo(); }\n"
2860 "interface IFoo2 { int foo(); }\n"
2861 "parcelable Data1 { int a; int b;}\n"
2862 "parcelable Data2 { int a; int b;}\n");
2863 CaptureStderr();
2864 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2865 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2866
2867 io_delegate_.SetFileContents(options.InputFiles().front(),
2868 "package foo.bar;\n"
2869 "interface IFoo1 { int foo(); }\n"
2870 "interface IFoo2 { int foo(); }\n");
2871 CaptureStderr();
2872 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2873 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2874
2875 expected_stderr = "ERROR: foo/bar/Foo.aidl:3.11-17: You must declare only one type per file.\n";
2876 io_delegate_.SetFileContents(options.InputFiles().front(),
2877 "package foo.bar;\n"
2878 "parcelable Data1 { int a; int b;}\n"
2879 "parcelable Data2 { int a; int b;}\n");
2880 CaptureStderr();
2881 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2882 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2883 }
2884 }
2885
TEST_P(AidlTest,FailParseOnEmptyFile)2886 TEST_P(AidlTest, FailParseOnEmptyFile) {
2887 const string contents = "";
2888 const string expected_stderr = "ERROR: a/IFoo.aidl:1.1-1: syntax error, unexpected $end\n";
2889 const string expected_stderr_newbison =
2890 "ERROR: a/IFoo.aidl:1.1-1: syntax error, unexpected end of file\n";
2891 CaptureStderr();
2892 EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", contents, typenames_, GetLanguage()));
2893 EXPECT_THAT(GetCapturedStderr(),
2894 testing::AnyOf(testing::Eq(expected_stderr), testing::Eq(expected_stderr_newbison)));
2895 }
2896
TEST_F(AidlTest,MultipleInputFiles)2897 TEST_F(AidlTest, MultipleInputFiles) {
2898 Options options =
2899 Options::From("aidl --lang=java -o out -I . foo/bar/IFoo.aidl foo/bar/Data.aidl");
2900
2901 io_delegate_.SetFileContents(options.InputFiles().at(0),
2902 "package foo.bar;\n"
2903 "import foo.bar.Data;\n"
2904 "interface IFoo { Data getData(); }\n");
2905
2906 io_delegate_.SetFileContents(options.InputFiles().at(1),
2907 "package foo.bar;\n"
2908 "import foo.bar.IFoo;\n"
2909 "parcelable Data { IFoo foo; }\n");
2910
2911 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2912
2913 string content;
2914 for (const auto file : {"out/foo/bar/IFoo.java", "out/foo/bar/Data.java"}) {
2915 content.clear();
2916 EXPECT_TRUE(io_delegate_.GetWrittenContents(file, &content));
2917 EXPECT_FALSE(content.empty());
2918 }
2919 }
2920
TEST_F(AidlTest,MultipleInputFilesCpp)2921 TEST_F(AidlTest, MultipleInputFilesCpp) {
2922 Options options = Options::From(
2923 "aidl --lang=cpp -I . -o out -h out/include "
2924 "-I . foo/bar/IFoo.aidl foo/bar/Data.aidl");
2925
2926 io_delegate_.SetFileContents(options.InputFiles().at(0),
2927 "package foo.bar;\n"
2928 "import foo.bar.Data;\n"
2929 "interface IFoo { Data getData(); }\n");
2930
2931 io_delegate_.SetFileContents(options.InputFiles().at(1),
2932 "package foo.bar;\n"
2933 "import foo.bar.IFoo;\n"
2934 "parcelable Data { IFoo foo; }\n");
2935
2936 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2937
2938 string content;
2939 for (const auto file :
2940 {"out/foo/bar/IFoo.cpp", "out/foo/bar/Data.cpp", "out/include/foo/bar/IFoo.h",
2941 "out/include/foo/bar/Data.h", "out/include/foo/bar/BpFoo.h", "out/include/foo/bar/BpData.h",
2942 "out/include/foo/bar/BnFoo.h", "out/include/foo/bar/BnData.h"}) {
2943 content.clear();
2944 EXPECT_TRUE(io_delegate_.GetWrittenContents(file, &content));
2945 EXPECT_FALSE(content.empty());
2946 }
2947 }
2948
TEST_F(AidlTest,MultipleInputFilesRust)2949 TEST_F(AidlTest, MultipleInputFilesRust) {
2950 Options options =
2951 Options::From("aidl --lang=rust -o out -I . foo/bar/IFoo.aidl foo/bar/Data.aidl");
2952
2953 io_delegate_.SetFileContents(options.InputFiles().at(0),
2954 "package foo.bar;\n"
2955 "import foo.bar.Data;\n"
2956 "interface IFoo { Data getData(); }\n");
2957
2958 io_delegate_.SetFileContents(options.InputFiles().at(1),
2959 "package foo.bar;\n"
2960 "import foo.bar.IFoo;\n"
2961 "parcelable Data { IFoo foo; }\n");
2962
2963 EXPECT_TRUE(compile_aidl(options, io_delegate_));
2964
2965 string content;
2966 for (const auto file : {"out/foo/bar/IFoo.rs", "out/foo/bar/Data.rs"}) {
2967 content.clear();
2968 EXPECT_TRUE(io_delegate_.GetWrittenContents(file, &content));
2969 EXPECT_FALSE(content.empty());
2970 }
2971 }
2972
TEST_F(AidlTest,ConflictWithMetaTransactionGetVersion)2973 TEST_F(AidlTest, ConflictWithMetaTransactionGetVersion) {
2974 const string expected_stderr =
2975 "ERROR: p/IFoo.aidl:1.31-51: method getInterfaceVersion() is reserved for internal use.\n";
2976 Options options = Options::From("aidl --lang=java -I . -o place/for/output p/IFoo.aidl");
2977 // int getInterfaceVersion() is one of the meta transactions
2978 io_delegate_.SetFileContents(options.InputFiles().front(),
2979 "package p; interface IFoo {"
2980 "int getInterfaceVersion(); }");
2981 CaptureStderr();
2982 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2983 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2984 }
2985
TEST_F(AidlTest,ConflictWithSimilarMetaTransaction)2986 TEST_F(AidlTest, ConflictWithSimilarMetaTransaction) {
2987 // boolean getInterfaceVersion() is not a meta transaction, but should be
2988 // prevented because return type is not part of a method signature
2989 const string expected_stderr =
2990 "ERROR: p/IFoo.aidl:1.35-55: method getInterfaceVersion() is reserved for internal use.\n";
2991 Options options = Options::From("aidl --lang=java -I . -o place/for/output p/IFoo.aidl");
2992 io_delegate_.SetFileContents(options.InputFiles().front(),
2993 "package p; interface IFoo {"
2994 "boolean getInterfaceVersion(); }");
2995 CaptureStderr();
2996 EXPECT_FALSE(compile_aidl(options, io_delegate_));
2997 EXPECT_EQ(expected_stderr, GetCapturedStderr());
2998 }
2999
TEST_F(AidlTest,ConflictWithMetaTransactionGetName)3000 TEST_F(AidlTest, ConflictWithMetaTransactionGetName) {
3001 // this is another reserved name
3002 const string expected_stderr =
3003 "ERROR: p/IFoo.aidl:1.34-53: method getTransactionName(int) is reserved for internal use.\n";
3004 Options options = Options::From("aidl --lang=java -I . -o place/for/output p/IFoo.aidl");
3005 io_delegate_.SetFileContents(options.InputFiles().front(),
3006 "package p; interface IFoo {"
3007 "String getTransactionName(int code); }");
3008 CaptureStderr();
3009 EXPECT_FALSE(compile_aidl(options, io_delegate_));
3010 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3011
3012 // this is not a meta interface method as it differs type arguments
3013 io_delegate_.SetFileContents(options.InputFiles().front(),
3014 "package p; interface IFoo {"
3015 "String getTransactionName(); }");
3016 EXPECT_TRUE(compile_aidl(options, io_delegate_));
3017 }
3018
TEST_F(AidlTest,CheckApiForEquality)3019 TEST_F(AidlTest, CheckApiForEquality) {
3020 CaptureStderr();
3021 Options options = Options::From("aidl --checkapi=equal old new");
3022
3023 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3024 "package p; interface IFoo{ @utf8InCpp @nullable String foo();}");
3025 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3026 "package p; interface IFoo{ @utf8InCpp String foo();}");
3027
3028 EXPECT_FALSE(::android::aidl::check_api(options, io_delegate_));
3029 EXPECT_THAT(GetCapturedStderr(), HasSubstr("+ @utf8InCpp String foo();"));
3030 }
3031
TEST_F(AidlTest,DifferentOrderAnnotationsInCheckAPI)3032 TEST_F(AidlTest, DifferentOrderAnnotationsInCheckAPI) {
3033 Options options = Options::From("aidl --checkapi old new");
3034 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3035 "package p; interface IFoo{ @utf8InCpp @nullable String foo();}");
3036 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3037 "package p; interface IFoo{ @nullable @utf8InCpp String foo();}");
3038
3039 EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
3040 }
3041
TEST_F(AidlTest,JavaPassthroughAnnotationAddedInCheckApi)3042 TEST_F(AidlTest, JavaPassthroughAnnotationAddedInCheckApi) {
3043 Options options = Options::From("aidl --checkapi old new");
3044 io_delegate_.SetFileContents("old/p/IFoo.aidl", "package p; interface IFoo{}");
3045 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3046 "package p; @JavaPassthrough(annotation=\"@foo\") interface IFoo{}");
3047
3048 EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
3049 }
3050
TEST_F(AidlTest,SuccessOnIdenticalApiDumps)3051 TEST_F(AidlTest, SuccessOnIdenticalApiDumps) {
3052 Options options = Options::From("aidl --checkapi old new");
3053 io_delegate_.SetFileContents("old/p/IFoo.aidl", "package p; interface IFoo{ void foo();}");
3054 io_delegate_.SetFileContents("new/p/IFoo.aidl", "package p; interface IFoo{ void foo();}");
3055
3056 EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
3057 }
3058
TEST_F(AidlTest,CheckApi_EnumFieldsWithDefaultValues)3059 TEST_F(AidlTest, CheckApi_EnumFieldsWithDefaultValues) {
3060 Options options = Options::From("aidl --checkapi old new");
3061 const string foo_definition = "package p; parcelable Foo{ p.Enum e = p.Enum.FOO; }";
3062 const string enum_definition = "package p; enum Enum { FOO }";
3063 io_delegate_.SetFileContents("old/p/Foo.aidl", foo_definition);
3064 io_delegate_.SetFileContents("old/p/Enum.aidl", enum_definition);
3065 io_delegate_.SetFileContents("new/p/Foo.aidl", foo_definition);
3066 io_delegate_.SetFileContents("new/p/Enum.aidl", enum_definition);
3067
3068 EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
3069 }
3070
TEST_F(AidlTest,CheckApi_EnumFieldsFromImported)3071 TEST_F(AidlTest, CheckApi_EnumFieldsFromImported) {
3072 Options options = Options::From("aidl --checkapi old new -I import");
3073
3074 io_delegate_.SetFileContents("old/p/Foo.aidl", "package p; parcelable Foo{ other.Enum e; }");
3075 io_delegate_.SetFileContents("new/p/Foo.aidl",
3076 "package p; parcelable Foo{ other.Enum e = other.Enum.FOO; }");
3077 io_delegate_.SetFileContents("import/other/Enum.aidl", "package other; enum Enum { FOO }");
3078
3079 EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
3080 }
3081
TEST_F(AidlTest,CheckApiEqual_EnumFieldsWithDefaultValues)3082 TEST_F(AidlTest, CheckApiEqual_EnumFieldsWithDefaultValues) {
3083 Options options = Options::From("aidl --checkapi=equal old new");
3084 const string foo_definition = "package p; parcelable Foo{ p.Enum e = p.Enum.FOO; }";
3085 const string enum_definition = "package p; enum Enum { FOO }";
3086 io_delegate_.SetFileContents("old/p/Foo.aidl", foo_definition);
3087 io_delegate_.SetFileContents("old/p/Enum.aidl", enum_definition);
3088 io_delegate_.SetFileContents("new/p/Foo.aidl", foo_definition);
3089 io_delegate_.SetFileContents("new/p/Enum.aidl", enum_definition);
3090 CaptureStderr();
3091 EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
3092 EXPECT_EQ("", GetCapturedStderr());
3093 }
3094
3095 class AidlTestCompatibleChanges : public AidlTest {
3096 protected:
3097 Options options_ = Options::From("aidl --checkapi old new");
3098 };
3099
TEST_F(AidlTestCompatibleChanges,NewType)3100 TEST_F(AidlTestCompatibleChanges, NewType) {
3101 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3102 "package p;"
3103 "interface IFoo {"
3104 " void foo(int a);"
3105 "}");
3106 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3107 "package p;"
3108 "interface IFoo {"
3109 " void foo(int a);"
3110 "}");
3111 io_delegate_.SetFileContents("new/p/IBar.aidl",
3112 "package p;"
3113 "interface IBar {"
3114 " void bar();"
3115 "}");
3116 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3117 }
3118
TEST_F(AidlTestCompatibleChanges,NewMethod)3119 TEST_F(AidlTestCompatibleChanges, NewMethod) {
3120 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3121 "package p;"
3122 "interface IFoo {"
3123 " void foo(int a);"
3124 "}");
3125 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3126 "package p;"
3127 "interface IFoo {"
3128 " void foo(int a);"
3129 " void bar();"
3130 " void baz(in List<String> arg);"
3131 "}");
3132 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3133 }
3134
TEST_F(AidlTestCompatibleChanges,NewField)3135 TEST_F(AidlTestCompatibleChanges, NewField) {
3136 io_delegate_.SetFileContents("old/p/Data.aidl",
3137 "package p;"
3138 "parcelable Data {"
3139 " int foo;"
3140 "}");
3141 io_delegate_.SetFileContents("new/p/Data.aidl",
3142 "package p;"
3143 "parcelable Data {"
3144 " int foo;"
3145 " int bar = 0;"
3146 " @nullable List<Data> list;"
3147 "}");
3148 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3149 }
3150
TEST_F(AidlTestCompatibleChanges,NewField2)3151 TEST_F(AidlTestCompatibleChanges, NewField2) {
3152 io_delegate_.SetFileContents("old/p/Data.aidl",
3153 "package p;"
3154 "parcelable Data {"
3155 "}");
3156 io_delegate_.SetFileContents("new/p/Data.aidl",
3157 "package p;"
3158 "parcelable Data {"
3159 " int foo = 0;"
3160 "}");
3161 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3162 }
3163
TEST_F(AidlTestCompatibleChanges,NewEnumerator)3164 TEST_F(AidlTestCompatibleChanges, NewEnumerator) {
3165 io_delegate_.SetFileContents("old/p/Enum.aidl",
3166 "package p;"
3167 "enum Enum {"
3168 " FOO = 1,"
3169 "}");
3170 io_delegate_.SetFileContents("new/p/Enum.aidl",
3171 "package p;"
3172 "enum Enum {"
3173 " FOO = 1,"
3174 " BAR = 2,"
3175 "}");
3176 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3177 }
3178
TEST_F(AidlTestCompatibleChanges,ReorderedEnumerator)3179 TEST_F(AidlTestCompatibleChanges, ReorderedEnumerator) {
3180 io_delegate_.SetFileContents("old/p/Enum.aidl",
3181 "package p;"
3182 "enum Enum {"
3183 " FOO = 1,"
3184 " BAR = 2,"
3185 "}");
3186 io_delegate_.SetFileContents("new/p/Enum.aidl",
3187 "package p;"
3188 "enum Enum {"
3189 " BAR = 2,"
3190 " FOO = 1,"
3191 "}");
3192 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3193 }
3194
TEST_F(AidlTestCompatibleChanges,NewUnionField)3195 TEST_F(AidlTestCompatibleChanges, NewUnionField) {
3196 io_delegate_.SetFileContents("old/p/Union.aidl",
3197 "package p;"
3198 "union Union {"
3199 " String foo;"
3200 "}");
3201 io_delegate_.SetFileContents("new/p/Union.aidl",
3202 "package p;"
3203 "union Union {"
3204 " String foo;"
3205 " int num;"
3206 "}");
3207 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3208 }
3209
TEST_F(AidlTestCompatibleChanges,NewPackage)3210 TEST_F(AidlTestCompatibleChanges, NewPackage) {
3211 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3212 "package p;"
3213 "interface IFoo {"
3214 " void foo(int a);"
3215 "}");
3216 io_delegate_.SetFileContents("old/p/Data.aidl",
3217 "package p;"
3218 "parcelable Data {"
3219 " int foo;"
3220 "}");
3221 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3222 "package p;"
3223 "interface IFoo {"
3224 " void foo(int a);"
3225 "}");
3226 io_delegate_.SetFileContents("new/p/Data.aidl",
3227 "package p;"
3228 "parcelable Data {"
3229 " int foo;"
3230 "}");
3231 io_delegate_.SetFileContents("new/q/IFoo.aidl",
3232 "package q;"
3233 "interface IFoo {"
3234 " void foo(int a);"
3235 "}");
3236 io_delegate_.SetFileContents("new/q/Data.aidl",
3237 "package q;"
3238 "parcelable Data {"
3239 " int foo;"
3240 "}");
3241 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3242 }
3243
TEST_F(AidlTestCompatibleChanges,ArgNameChange)3244 TEST_F(AidlTestCompatibleChanges, ArgNameChange) {
3245 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3246 "package p;"
3247 "interface IFoo {"
3248 " void foo(int a);"
3249 "}");
3250 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3251 "package p;"
3252 "interface IFoo {"
3253 " void foo(int b);"
3254 "}");
3255 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3256 }
3257
TEST_F(AidlTestCompatibleChanges,AddedConstValue)3258 TEST_F(AidlTestCompatibleChanges, AddedConstValue) {
3259 io_delegate_.SetFileContents("old/p/I.aidl",
3260 "package p; interface I {"
3261 "const int A = 1; }");
3262 io_delegate_.SetFileContents("new/p/I.aidl",
3263 "package p ; interface I {"
3264 "const int A = 1; const int B = 2;}");
3265 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3266 }
3267
TEST_F(AidlTestCompatibleChanges,ChangedConstValueOrder)3268 TEST_F(AidlTestCompatibleChanges, ChangedConstValueOrder) {
3269 io_delegate_.SetFileContents("old/p/I.aidl",
3270 "package p; interface I {"
3271 "const int A = 1; const int B = 2;}");
3272 io_delegate_.SetFileContents("new/p/I.aidl",
3273 "package p ; interface I {"
3274 "const int B = 2; const int A = 1;}");
3275 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3276 }
3277
TEST_F(AidlTestCompatibleChanges,ReorderedAnnatations)3278 TEST_F(AidlTestCompatibleChanges, ReorderedAnnatations) {
3279 io_delegate_.SetFileContents("old/p/Foo.aidl",
3280 "package p;"
3281 "@JavaPassthrough(annotation=\"Alice\")"
3282 "@JavaPassthrough(annotation=\"Bob\")"
3283 "parcelable Foo {}");
3284 io_delegate_.SetFileContents("new/p/Foo.aidl",
3285 "package p;"
3286 "@JavaPassthrough(annotation=\"Bob\")"
3287 "@JavaPassthrough(annotation=\"Alice\")"
3288 "parcelable Foo {}");
3289 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3290 }
3291
TEST_F(AidlTestCompatibleChanges,OkayToDeprecate)3292 TEST_F(AidlTestCompatibleChanges, OkayToDeprecate) {
3293 io_delegate_.SetFileContents("old/p/Foo.aidl",
3294 "package p;"
3295 "parcelable Foo {}");
3296 io_delegate_.SetFileContents("new/p/Foo.aidl",
3297 "package p;"
3298 "@JavaPassthrough(annotation=\"@Deprecated\")"
3299 "parcelable Foo {}");
3300 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3301 }
3302
TEST_F(AidlTestCompatibleChanges,NewFieldOfNewType)3303 TEST_F(AidlTestCompatibleChanges, NewFieldOfNewType) {
3304 io_delegate_.SetFileContents("old/p/Data.aidl",
3305 "package p;"
3306 "parcelable Data {"
3307 " int num;"
3308 "}");
3309 io_delegate_.SetFileContents(
3310 "new/p/Data.aidl",
3311 "package p;"
3312 "parcelable Data {"
3313 " int num;"
3314 " p.Enum e;" // this is considered as valid since 0(enum default) is valid for "Enum" type
3315 "}");
3316 io_delegate_.SetFileContents("new/p/Enum.aidl",
3317 "package p;"
3318 "enum Enum {"
3319 " FOO = 0,"
3320 " BAR = 1,"
3321 "}");
3322 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3323 }
3324
TEST_F(AidlTestCompatibleChanges,CompatibleExplicitDefaults)3325 TEST_F(AidlTestCompatibleChanges, CompatibleExplicitDefaults) {
3326 io_delegate_.SetFileContents("old/p/Data.aidl",
3327 "package p;\n"
3328 "parcelable Data {\n"
3329 " p.Enum e;\n"
3330 "}");
3331 io_delegate_.SetFileContents("old/p/Enum.aidl",
3332 "package p;\n"
3333 "enum Enum {\n"
3334 " FOO = 0,\n"
3335 " BAR = 1,\n"
3336 "}");
3337 io_delegate_.SetFileContents("new/p/Data.aidl",
3338 "package p;\n"
3339 "parcelable Data {\n"
3340 " p.Enum e = p.Enum.FOO;\n"
3341 "}");
3342 io_delegate_.SetFileContents("new/p/Enum.aidl",
3343 "package p;\n"
3344 "enum Enum {\n"
3345 " FOO = 0,\n"
3346 " BAR = 1,\n"
3347 "}");
3348 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3349 }
3350
TEST_F(AidlTestCompatibleChanges,NewNestedTypes)3351 TEST_F(AidlTestCompatibleChanges, NewNestedTypes) {
3352 io_delegate_.SetFileContents("old/p/Data.aidl",
3353 "package p;\n"
3354 "parcelable Data {\n"
3355 " int n;\n"
3356 "}");
3357 io_delegate_.SetFileContents("new/p/Data.aidl",
3358 "package p;\n"
3359 "parcelable Data {\n"
3360 " enum NewEnum { N = 3 }\n"
3361 " int n;\n"
3362 " NewEnum e = NewEnum.N;\n"
3363 "}");
3364 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3365 }
3366
TEST_F(AidlTestCompatibleChanges,NewJavaSuppressLint)3367 TEST_F(AidlTestCompatibleChanges, NewJavaSuppressLint) {
3368 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3369 "package p;"
3370 "interface IFoo {"
3371 " void foo(int a);"
3372 "}");
3373 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3374 "package p;"
3375 "@JavaSuppressLint({\"NewApi\"})"
3376 "interface IFoo {"
3377 " void foo(int a);"
3378 "}");
3379 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3380 }
3381
3382 class AidlTestIncompatibleChanges : public AidlTest {
3383 protected:
3384 Options options_ = Options::From("aidl --checkapi old new");
3385 };
3386
TEST_F(AidlTestIncompatibleChanges,RemovedType)3387 TEST_F(AidlTestIncompatibleChanges, RemovedType) {
3388 const string expected_stderr = "ERROR: old/p/IFoo.aidl:1.11-20: Removed type: p.IFoo\n";
3389 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3390 "package p;"
3391 "interface IFoo {"
3392 " void foo(in String[] str);"
3393 " void bar(@utf8InCpp String str);"
3394 "}");
3395 CaptureStderr();
3396 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3397 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3398 }
3399
TEST_F(AidlTestIncompatibleChanges,RemovedTypeNotInternal)3400 TEST_F(AidlTestIncompatibleChanges, RemovedTypeNotInternal) {
3401 // We create new Tag enums internal to unions and they show up in these logs
3402 const string expected_stderr =
3403 "ERROR: old/p/Foo.aidl:1.16-20: Removed type: p.Foo\n"
3404 "ERROR: (derived from)old/p/Foo.aidl:1.16-20: Removed type: p.Foo.Tag\n";
3405 io_delegate_.SetFileContents("old/p/Foo.aidl",
3406 "package p;"
3407 "union Foo {"
3408 " int foo;"
3409 " int bar;"
3410 "}");
3411 CaptureStderr();
3412 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3413 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3414 }
3415
TEST_F(AidlTestIncompatibleChanges,RemovedMethod)3416 TEST_F(AidlTestIncompatibleChanges, RemovedMethod) {
3417 const string expected_stderr =
3418 "ERROR: old/p/IFoo.aidl:1.61-65: Removed or changed method: p.IFoo.bar(String)\n";
3419 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3420 "package p;"
3421 "interface IFoo {"
3422 " void foo(in String[] str);"
3423 " void bar(@utf8InCpp String str);"
3424 "}");
3425 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3426 "package p;"
3427 "interface IFoo {"
3428 " void foo(in String[] str);"
3429 "}");
3430 CaptureStderr();
3431 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3432 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3433 }
3434
TEST_F(AidlTestIncompatibleChanges,UntypedListInInterface)3435 TEST_F(AidlTestIncompatibleChanges, UntypedListInInterface) {
3436 const string expected_stderr =
3437 "ERROR: new/p/IFoo.aidl:1.61-65: "
3438 "Encountered an untyped List or Map. The use of untyped List/Map is "
3439 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
3440 "the receiving side. Consider switching to an array or a generic List/Map.\n"
3441 "ERROR: new/p/IFoo.aidl: Failed to read.\n";
3442 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3443 "package p;"
3444 "interface IFoo {"
3445 " void foo(in String[] str);"
3446 "}");
3447 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3448 "package p;"
3449 "interface IFoo {"
3450 " void foo(in String[] str);"
3451 " void bar(in List arg);"
3452 "}");
3453 CaptureStderr();
3454 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3455 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3456 }
3457
TEST_F(AidlTestCompatibleChanges,UntypedListInParcelable)3458 TEST_F(AidlTestCompatibleChanges, UntypedListInParcelable) {
3459 const string expected_stderr =
3460 "ERROR: new/p/Data.aidl:1.54-59: "
3461 "Encountered an untyped List or Map. The use of untyped List/Map is "
3462 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
3463 "the receiving side. Consider switching to an array or a generic List/Map.\n"
3464 "ERROR: new/p/Data.aidl: Failed to read.\n";
3465 io_delegate_.SetFileContents("old/p/Data.aidl",
3466 "package p;"
3467 "parcelable Data {"
3468 " int foo;"
3469 "}");
3470 io_delegate_.SetFileContents("new/p/Data.aidl",
3471 "package p;"
3472 "parcelable Data {"
3473 " int foo;"
3474 " @nullable List list;"
3475 "}");
3476 CaptureStderr();
3477 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3478 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3479 }
3480
TEST_F(AidlTestIncompatibleChanges,RemovedField)3481 TEST_F(AidlTestIncompatibleChanges, RemovedField) {
3482 const string expected_stderr =
3483 "ERROR: new/p/Data.aidl:1.21-26: Number of fields in p.Data is reduced from 2 to 1.\n";
3484 io_delegate_.SetFileContents("old/p/Data.aidl",
3485 "package p;"
3486 "parcelable Data {"
3487 " int foo;"
3488 " int bar;"
3489 "}");
3490 io_delegate_.SetFileContents("new/p/Data.aidl",
3491 "package p;"
3492 "parcelable Data {"
3493 " int foo;"
3494 "}");
3495 CaptureStderr();
3496 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3497 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3498 }
3499
TEST_F(AidlTestIncompatibleChanges,NewFieldWithNoDefault)3500 TEST_F(AidlTestIncompatibleChanges, NewFieldWithNoDefault) {
3501 const string expected_stderr =
3502 "ERROR: new/p/Data.aidl:1.46-50: Field 'str' does not have a useful default in some "
3503 "backends. Please either provide a default value for this field or mark the field as "
3504 "@nullable. This value or a null value will be used automatically when an old version of "
3505 "this parcelable is sent to a process which understands a new version of this parcelable. In "
3506 "order to make sure your code continues to be backwards compatible, make sure the default or "
3507 "null value does not cause a semantic change to this parcelable.\n";
3508 io_delegate_.SetFileContents("old/p/Data.aidl",
3509 "package p;"
3510 "parcelable Data {"
3511 " int num;"
3512 "}");
3513 io_delegate_.SetFileContents("new/p/Data.aidl",
3514 "package p;"
3515 "parcelable Data {"
3516 " int num;"
3517 " String str;"
3518 "}");
3519 CaptureStderr();
3520 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3521 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3522 }
3523
TEST_F(AidlTestIncompatibleChanges,NewFieldWithNonZeroEnum)3524 TEST_F(AidlTestIncompatibleChanges, NewFieldWithNonZeroEnum) {
3525 const string expected_stderr =
3526 "ERROR: new/p/Data.aidl:1.46-48: Field 'e' of enum 'Enum' can't be initialized as '0'. "
3527 "Please make sure 'Enum' has '0' as a valid value.\n";
3528 io_delegate_.SetFileContents("old/p/Data.aidl",
3529 "package p;"
3530 "parcelable Data {"
3531 " int num;"
3532 "}");
3533 io_delegate_.SetFileContents("new/p/Data.aidl",
3534 "package p;"
3535 "parcelable Data {"
3536 " int num;"
3537 " p.Enum e;"
3538 "}");
3539 io_delegate_.SetFileContents("new/p/Enum.aidl",
3540 "package p;"
3541 "enum Enum {"
3542 " FOO = 1,"
3543 " BAR = 2,"
3544 "}");
3545 CaptureStderr();
3546 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3547 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3548 }
3549
TEST_F(AidlTestIncompatibleChanges,RemovedEnumerator)3550 TEST_F(AidlTestIncompatibleChanges, RemovedEnumerator) {
3551 const string expected_stderr =
3552 "ERROR: new/p/Enum.aidl:1.15-20: Removed enumerator from p.Enum: FOO\n";
3553 io_delegate_.SetFileContents("old/p/Enum.aidl",
3554 "package p;"
3555 "enum Enum {"
3556 " FOO = 1,"
3557 " BAR = 2,"
3558 "}");
3559 io_delegate_.SetFileContents("new/p/Enum.aidl",
3560 "package p;"
3561 "enum Enum {"
3562 " BAR = 2,"
3563 "}");
3564 CaptureStderr();
3565 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3566 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3567 }
3568
TEST_F(AidlTestIncompatibleChanges,RemovedUnionField)3569 TEST_F(AidlTestIncompatibleChanges, RemovedUnionField) {
3570 const string expected_stderr =
3571 "ERROR: new/p/Union.aidl:1.16-22: Number of fields in p.Union is reduced from 2 to 1.\n"
3572 "ERROR: (derived from)new/p/Union.aidl:1.16-22: Removed enumerator from p.Union.Tag: num\n";
3573 io_delegate_.SetFileContents("old/p/Union.aidl",
3574 "package p;"
3575 "union Union {"
3576 " String str;"
3577 " int num;"
3578 "}");
3579 io_delegate_.SetFileContents("new/p/Union.aidl",
3580 "package p;"
3581 "union Union {"
3582 " String str;"
3583 "}");
3584 CaptureStderr();
3585 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3586 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3587 }
3588
TEST_F(AidlTestIncompatibleChanges,RenamedMethod)3589 TEST_F(AidlTestIncompatibleChanges, RenamedMethod) {
3590 const string expected_stderr =
3591 "ERROR: old/p/IFoo.aidl:1.61-65: Removed or changed method: p.IFoo.bar(String)\n";
3592 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3593 "package p;"
3594 "interface IFoo {"
3595 " void foo(in String[] str);"
3596 " void bar(@utf8InCpp String str);"
3597 "}");
3598 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3599 "package p;"
3600 "interface IFoo {"
3601 " void foo(in String[] str);"
3602 " void bar2(@utf8InCpp String str);"
3603 "}");
3604 CaptureStderr();
3605 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3606 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3607 }
3608
TEST_F(AidlTestIncompatibleChanges,RenamedType)3609 TEST_F(AidlTestIncompatibleChanges, RenamedType) {
3610 const string expected_stderr = "ERROR: old/p/IFoo.aidl:1.11-20: Removed type: p.IFoo\n";
3611 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3612 "package p;"
3613 "interface IFoo {"
3614 " void foo(in String[] str);"
3615 " void bar(@utf8InCpp String str);"
3616 "}");
3617 io_delegate_.SetFileContents("new/p/IFoo2.aidl",
3618 "package p;"
3619 "interface IFoo2 {"
3620 " void foo(in String[] str);"
3621 " void bar(@utf8InCpp String str);"
3622 "}");
3623 CaptureStderr();
3624 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3625 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3626 }
3627
TEST_F(AidlTestIncompatibleChanges,ChangedEnumerator)3628 TEST_F(AidlTestIncompatibleChanges, ChangedEnumerator) {
3629 const string expected_stderr =
3630 "ERROR: new/p/Enum.aidl:1.15-20: Changed enumerator value: p.Enum::FOO from 1 to 3.\n";
3631 io_delegate_.SetFileContents("old/p/Enum.aidl",
3632 "package p;"
3633 "enum Enum {"
3634 " FOO = 1,"
3635 " BAR = 2,"
3636 "}");
3637 io_delegate_.SetFileContents("new/p/Enum.aidl",
3638 "package p;"
3639 "enum Enum {"
3640 " FOO = 3,"
3641 " BAR = 2,"
3642 "}");
3643 CaptureStderr();
3644 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3645 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3646 }
3647
TEST_F(AidlTestIncompatibleChanges,ReorderedMethod)3648 TEST_F(AidlTestIncompatibleChanges, ReorderedMethod) {
3649 const string expected_stderr =
3650 "ERROR: new/p/IFoo.aidl:1.67-71: Transaction ID changed: p.IFoo.foo(String[]) is changed "
3651 "from 0 to 1.\n"
3652 "ERROR: new/p/IFoo.aidl:1.33-37: Transaction ID changed: p.IFoo.bar(String) is changed from "
3653 "1 to 0.\n";
3654 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3655 "package p;"
3656 "interface IFoo {"
3657 " void foo(in String[] str);"
3658 " void bar(@utf8InCpp String str);"
3659 "}");
3660 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3661 "package p;"
3662 "interface IFoo {"
3663 " void bar(@utf8InCpp String str);"
3664 " void foo(in String[] str);"
3665 "}");
3666 CaptureStderr();
3667 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3668 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3669 }
3670
TEST_F(AidlTestIncompatibleChanges,ReorderedField)3671 TEST_F(AidlTestIncompatibleChanges, ReorderedField) {
3672 const string expected_stderr =
3673 "ERROR: new/p/Data.aidl:1.33-37: Reordered bar from 1 to 0.\n"
3674 "ERROR: new/p/Data.aidl:1.43-47: Reordered foo from 0 to 1.\n";
3675 io_delegate_.SetFileContents("old/p/Data.aidl",
3676 "package p;"
3677 "parcelable Data {"
3678 " int foo;"
3679 " int bar;"
3680 "}");
3681 io_delegate_.SetFileContents("new/p/Data.aidl",
3682 "package p;"
3683 "parcelable Data {"
3684 " int bar;"
3685 " int foo;"
3686 "}");
3687 CaptureStderr();
3688 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3689 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3690 }
3691
TEST_F(AidlTestIncompatibleChanges,ChangedDirectionSpecifier)3692 TEST_F(AidlTestIncompatibleChanges, ChangedDirectionSpecifier) {
3693 const string expected_stderr = "ERROR: new/p/IFoo.aidl:1.33-37: Direction changed: in to out.\n";
3694 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3695 "package p;"
3696 "interface IFoo {"
3697 " void foo(in String[] str);"
3698 " void bar(@utf8InCpp String str);"
3699 "}");
3700 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3701 "package p;"
3702 "interface IFoo {"
3703 " void foo(out String[] str);"
3704 " void bar(@utf8InCpp String str);"
3705 "}");
3706 CaptureStderr();
3707 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3708 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3709 }
3710
TEST_F(AidlTestIncompatibleChanges,AddedAnnotation)3711 TEST_F(AidlTestIncompatibleChanges, AddedAnnotation) {
3712 const string expected_stderr =
3713 "ERROR: new/p/IFoo.aidl:1.51-58: Changed annotations: (empty) to @utf8InCpp\n";
3714 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3715 "package p;"
3716 "interface IFoo {"
3717 " void foo(in String[] str);"
3718 " void bar(@utf8InCpp String str);"
3719 "}");
3720 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3721 "package p;"
3722 "interface IFoo {"
3723 " void foo(in @utf8InCpp String[] str);"
3724 " void bar(@utf8InCpp String str);"
3725 "}");
3726 CaptureStderr();
3727 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3728 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3729 }
3730
TEST_F(AidlTestIncompatibleChanges,RemovedAnnotation)3731 TEST_F(AidlTestIncompatibleChanges, RemovedAnnotation) {
3732 const string expected_stderr =
3733 "ERROR: new/p/IFoo.aidl:1.66-72: Changed annotations: @utf8InCpp to (empty)\n";
3734 io_delegate_.SetFileContents("old/p/IFoo.aidl",
3735 "package p;"
3736 "interface IFoo {"
3737 " void foo(in String[] str);"
3738 " void bar(@utf8InCpp String str);"
3739 "}");
3740 io_delegate_.SetFileContents("new/p/IFoo.aidl",
3741 "package p;"
3742 "interface IFoo {"
3743 " void foo(in String[] str);"
3744 " void bar(String str);"
3745 "}");
3746 CaptureStderr();
3747 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3748 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3749 }
3750
TEST_F(AidlTestIncompatibleChanges,ChangedFixedSizeArraySize)3751 TEST_F(AidlTestIncompatibleChanges, ChangedFixedSizeArraySize) {
3752 const string expected_stderr =
3753 "ERROR: new/p/Data.aidl:1.28-33: Type changed: int[8] to int[9].\n";
3754 io_delegate_.SetFileContents("old/p/Data.aidl",
3755 "package p;"
3756 "parcelable Data {"
3757 " int[8] bar;"
3758 "}");
3759 io_delegate_.SetFileContents("new/p/Data.aidl",
3760 "package p;"
3761 "parcelable Data {"
3762 " int[9] bar;"
3763 "}");
3764 CaptureStderr();
3765 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3766 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3767 }
3768
TEST_F(AidlTestIncompatibleChanges,ChangedAnnatationParams)3769 TEST_F(AidlTestIncompatibleChanges, ChangedAnnatationParams) {
3770 // this is also the test for backing type remaining the same
3771 const string expected_stderr =
3772 "ERROR: new/p/Foo.aidl:1.36-40: Changed annotations: @Backing(type=\"int\") "
3773 "to @Backing(type=\"long\")\n";
3774 io_delegate_.SetFileContents("old/p/Foo.aidl",
3775 "package p;"
3776 "@Backing(type=\"int\")"
3777 "enum Foo {A}");
3778 io_delegate_.SetFileContents("new/p/Foo.aidl",
3779 "package p;"
3780 "@Backing(type=\"long\")"
3781 "enum Foo {A}");
3782
3783 CaptureStderr();
3784 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3785 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3786 }
3787
TEST_F(AidlTestIncompatibleChanges,AddedParcelableAnnotation)3788 TEST_F(AidlTestIncompatibleChanges, AddedParcelableAnnotation) {
3789 const string expected_stderr =
3790 "ERROR: new/p/Foo.aidl:1.32-36: Changed annotations: (empty) to @FixedSize\n";
3791 io_delegate_.SetFileContents("old/p/Foo.aidl",
3792 "package p;"
3793 "parcelable Foo {"
3794 " int A;"
3795 "}");
3796 io_delegate_.SetFileContents("new/p/Foo.aidl",
3797 "package p;"
3798 "@FixedSize parcelable Foo {"
3799 " int A;"
3800 "}");
3801 CaptureStderr();
3802 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3803 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3804 }
3805
TEST_F(AidlTestIncompatibleChanges,RemovedParcelableAnnotation)3806 TEST_F(AidlTestIncompatibleChanges, RemovedParcelableAnnotation) {
3807 const string expected_stderr =
3808 "ERROR: new/p/Foo.aidl:1.21-25: Changed annotations: @FixedSize to (empty)\n";
3809 io_delegate_.SetFileContents("old/p/Foo.aidl",
3810 "package p;"
3811 "@FixedSize parcelable Foo {"
3812 " int A;"
3813 "}");
3814 io_delegate_.SetFileContents("new/p/Foo.aidl",
3815 "package p;"
3816 "parcelable Foo {"
3817 " int A;"
3818 "}");
3819 CaptureStderr();
3820 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3821 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3822 }
3823
TEST_F(AidlTestIncompatibleChanges,RemovedPackage)3824 TEST_F(AidlTestIncompatibleChanges, RemovedPackage) {
3825 const string expected_stderr = "ERROR: old/q/IFoo.aidl:1.11-21: Removed type: q.IFoo\n";
3826 io_delegate_.SetFileContents("old/p/IFoo.aidl", "package p; interface IFoo{}");
3827 io_delegate_.SetFileContents("old/q/IFoo.aidl", "package q; interface IFoo{}");
3828 io_delegate_.SetFileContents("new/p/IFoo.aidl", "package p; interface IFoo{}");
3829 CaptureStderr();
3830 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3831 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3832 }
3833
TEST_F(AidlTestIncompatibleChanges,ChangedDefaultValue)3834 TEST_F(AidlTestIncompatibleChanges, ChangedDefaultValue) {
3835 const string expected_stderr = "ERROR: new/p/D.aidl:1.30-32: Changed default value: 1 to 2.\n";
3836 io_delegate_.SetFileContents("old/p/D.aidl", "package p; parcelable D { int a = 1; }");
3837 io_delegate_.SetFileContents("new/p/D.aidl", "package p; parcelable D { int a = 2; }");
3838 CaptureStderr();
3839 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3840 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3841 }
3842
TEST_F(AidlTestIncompatibleChanges,RemovedConstValue)3843 TEST_F(AidlTestIncompatibleChanges, RemovedConstValue) {
3844 const string expected_stderr =
3845 "ERROR: old/p/I.aidl:1.51-53: Removed constant declaration: p.I.B\n";
3846 io_delegate_.SetFileContents("old/p/I.aidl",
3847 "package p; interface I {"
3848 "const int A = 1; const int B = 2;}");
3849 io_delegate_.SetFileContents("new/p/I.aidl", "package p; interface I { const int A = 1; }");
3850 CaptureStderr();
3851 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3852 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3853 }
3854
TEST_F(AidlTestIncompatibleChanges,ChangedConstValue)3855 TEST_F(AidlTestIncompatibleChanges, ChangedConstValue) {
3856 const string expected_stderr =
3857 "ERROR: new/p/I.aidl:1.11-21: Changed constant value: p.I.A from 1 to 2.\n";
3858 io_delegate_.SetFileContents("old/p/I.aidl", "package p; interface I { const int A = 1; }");
3859 io_delegate_.SetFileContents("new/p/I.aidl", "package p; interface I { const int A = 2; }");
3860 CaptureStderr();
3861 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3862 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3863 }
3864
TEST_F(AidlTestIncompatibleChanges,FixedSizeAddedField)3865 TEST_F(AidlTestIncompatibleChanges, FixedSizeAddedField) {
3866 const string expected_stderr =
3867 "ERROR: new/p/Foo.aidl:1.33-37: Number of fields in p.Foo is changed from 1 to 2. "
3868 "This is an incompatible change for FixedSize types.\n";
3869 io_delegate_.SetFileContents("old/p/Foo.aidl",
3870 "package p; @FixedSize parcelable Foo { int A = 1; }");
3871 io_delegate_.SetFileContents("new/p/Foo.aidl",
3872 "package p; @FixedSize parcelable Foo { int A = 1; int B = 2; }");
3873 CaptureStderr();
3874 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3875 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3876 }
3877
TEST_F(AidlTestIncompatibleChanges,UidRangeParcelAddedField)3878 TEST_F(AidlTestIncompatibleChanges, UidRangeParcelAddedField) {
3879 const string expected_stderr =
3880 "ERROR: new/android/net/UidRangeParcel.aidl:1.32-47: Number of fields in "
3881 "android.net.UidRangeParcel is changed from 1 to 2. "
3882 "But it is forbidden because of legacy support.\n";
3883 io_delegate_.SetFileContents("old/android/net/UidRangeParcel.aidl",
3884 "package android.net; parcelable UidRangeParcel { int A = 1; }");
3885 io_delegate_.SetFileContents(
3886 "new/android/net/UidRangeParcel.aidl",
3887 "package android.net; parcelable UidRangeParcel { int A = 1; int B = 2; }");
3888 CaptureStderr();
3889 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3890 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3891 }
3892
TEST_F(AidlTestIncompatibleChanges,FixedSizeRemovedField)3893 TEST_F(AidlTestIncompatibleChanges, FixedSizeRemovedField) {
3894 const string expected_stderr =
3895 "ERROR: new/p/Foo.aidl:1.33-37: Number of fields in p.Foo is reduced from 2 to 1.\n";
3896 io_delegate_.SetFileContents("old/p/Foo.aidl",
3897 "package p; @FixedSize parcelable Foo { int A = 1; int B = 1; }");
3898 io_delegate_.SetFileContents("new/p/Foo.aidl",
3899 "package p; @FixedSize parcelable Foo { int A = 1; }");
3900 CaptureStderr();
3901 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3902 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3903 }
3904
TEST_F(AidlTestIncompatibleChanges,IncompatibleChangesInNestedType)3905 TEST_F(AidlTestIncompatibleChanges, IncompatibleChangesInNestedType) {
3906 const string expected_stderr =
3907 "ERROR: new/p/Foo.aidl:1.33-37: Number of fields in p.Foo is reduced from 2 to 1.\n";
3908 io_delegate_.SetFileContents("old/p/Foo.aidl",
3909 "package p;\n"
3910 "parcelable Foo {\n"
3911 " interface IBar {\n"
3912 " void foo();"
3913 " }\n"
3914 "}");
3915 io_delegate_.SetFileContents("new/p/Foo.aidl",
3916 "package p;\n"
3917 "parcelable Foo {\n"
3918 " interface IBar {\n"
3919 " void foo(int n);" // incompatible: signature changed
3920 " }\n"
3921 "}");
3922 CaptureStderr();
3923 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3924 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Removed or changed method: p.Foo.IBar.foo()"));
3925 }
3926
TEST_F(AidlTestIncompatibleChanges,IncompatibleTwoWayToOneWay)3927 TEST_F(AidlTestIncompatibleChanges, IncompatibleTwoWayToOneWay) {
3928 io_delegate_.SetFileContents("old/p/IFoo.aidl", "package p; interface IFoo{ void foo();}");
3929 io_delegate_.SetFileContents("new/p/IFoo.aidl", "package p; interface IFoo{ oneway void foo();}");
3930
3931 CaptureStderr();
3932 EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
3933 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Oneway attribute added: p.IFoo.foo()"));
3934 }
3935
TEST_F(AidlTestCompatibleChanges,CompatibleOneWayToTwoWay)3936 TEST_F(AidlTestCompatibleChanges, CompatibleOneWayToTwoWay) {
3937 io_delegate_.SetFileContents("old/p/IFoo.aidl", "package p; interface IFoo{ oneway void foo();}");
3938 io_delegate_.SetFileContents("new/p/IFoo.aidl", "package p; interface IFoo{ void foo();}");
3939
3940 EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
3941 }
3942
TEST_P(AidlTest,RejectNonFixedSizeFromFixedSize)3943 TEST_P(AidlTest, RejectNonFixedSizeFromFixedSize) {
3944 const string expected_stderr =
3945 "ERROR: Foo.aidl:2.8-10: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3946 "a.\n"
3947 "ERROR: Foo.aidl:3.6-8: The @FixedSize parcelable 'Foo' has a non-fixed size field named b.\n"
3948 "ERROR: Foo.aidl:4.9-11: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3949 "c.\n"
3950 "ERROR: Foo.aidl:5.23-25: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3951 "d.\n"
3952 "ERROR: Foo.aidl:6.10-12: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3953 "e.\n"
3954 "ERROR: Foo.aidl:7.15-17: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3955 "f.\n"
3956 "ERROR: Foo.aidl:9.23-33: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3957 "nullable1.\n"
3958 "ERROR: Foo.aidl:10.34-44: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3959 "nullable2.\n";
3960
3961 io_delegate_.SetFileContents("Foo.aidl",
3962 "@FixedSize parcelable Foo {\n"
3963 " int[] a;\n"
3964 " Bar b;\n"
3965 " String c;\n"
3966 " ParcelFileDescriptor d;\n"
3967 " IBinder e;\n"
3968 " List<String> f;\n"
3969 " int isFixedSize;\n"
3970 " @nullable OtherFixed nullable1;\n"
3971 " @nullable(heap=true) OtherFixed nullable2;\n"
3972 " float[16] floats;\n"
3973 "}");
3974 io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { int a; }");
3975 io_delegate_.SetFileContents("OtherFixed.aidl", "@FixedSize parcelable OtherFixed { int a; }");
3976 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
3977
3978 CaptureStderr();
3979 EXPECT_FALSE(compile_aidl(options, io_delegate_));
3980 EXPECT_EQ(expected_stderr, GetCapturedStderr());
3981 }
3982
TEST_P(AidlTest,RejectNonFixedSizeFromFixedSize_Union)3983 TEST_P(AidlTest, RejectNonFixedSizeFromFixedSize_Union) {
3984 const string expected_stderr =
3985 "ERROR: Foo.aidl:2.8-10: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3986 "a.\n"
3987 "ERROR: Foo.aidl:3.6-8: The @FixedSize parcelable 'Foo' has a non-fixed size field named b.\n"
3988 "ERROR: Foo.aidl:4.9-11: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3989 "c.\n"
3990 "ERROR: Foo.aidl:5.23-25: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3991 "d.\n"
3992 "ERROR: Foo.aidl:6.10-12: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3993 "e.\n"
3994 "ERROR: Foo.aidl:7.15-17: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3995 "f.\n"
3996 "ERROR: Foo.aidl:9.23-33: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3997 "nullable1.\n"
3998 "ERROR: Foo.aidl:10.34-44: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
3999 "nullable2.\n";
4000
4001 io_delegate_.SetFileContents("Foo.aidl",
4002 "@FixedSize union Foo {\n"
4003 " int[] a = {};\n"
4004 " Bar b;\n"
4005 " String c;\n"
4006 " ParcelFileDescriptor d;\n"
4007 " IBinder e;\n"
4008 " List<String> f;\n"
4009 " int isFixedSize;\n"
4010 " @nullable OtherFixed nullable1;\n"
4011 " @nullable(heap=true) OtherFixed nullable2;\n"
4012 " float[16] floats;\n"
4013 "}");
4014 io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { int a; }");
4015 io_delegate_.SetFileContents("OtherFixed.aidl", "@FixedSize parcelable OtherFixed { int a; }");
4016 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
4017
4018 CaptureStderr();
4019 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4020 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4021 }
4022
TEST_P(AidlTest,AcceptFixedSizeFromFixedSize)4023 TEST_P(AidlTest, AcceptFixedSizeFromFixedSize) {
4024 const string expected_stderr = "";
4025
4026 io_delegate_.SetFileContents("Foo.aidl", "@FixedSize parcelable Foo { int a; Bar b; }");
4027 io_delegate_.SetFileContents("Bar.aidl", "@FixedSize parcelable Bar { Val c; }");
4028 io_delegate_.SetFileContents("Val.aidl", "enum Val { A, B, }");
4029 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
4030
4031 CaptureStderr();
4032 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4033 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4034 }
4035
TEST_F(AidlTest,RejectAmbiguousImports)4036 TEST_F(AidlTest, RejectAmbiguousImports) {
4037 const string expected_stderr =
4038 "ERROR: p/IFoo.aidl: Duplicate files found for q.IBar from:\n"
4039 "dir1/q/IBar.aidl\n"
4040 "dir2/q/IBar.aidl\n";
4041 Options options = Options::From("aidl --lang=java -o out -I . -I dir1 -I dir2 p/IFoo.aidl");
4042 io_delegate_.SetFileContents("p/IFoo.aidl", "package p; import q.IBar; interface IFoo{}");
4043 io_delegate_.SetFileContents("dir1/q/IBar.aidl", "package q; interface IBar{}");
4044 io_delegate_.SetFileContents("dir2/q/IBar.aidl", "package q; interface IBar{}");
4045
4046 CaptureStderr();
4047 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4048 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4049 }
4050
TEST_F(AidlTest,HandleManualIdAssignments)4051 TEST_F(AidlTest, HandleManualIdAssignments) {
4052 const string expected_stderr =
4053 "ERROR: new/p/IFoo.aidl:1.32-36: Transaction ID changed: p.IFoo.foo() is changed from 10 to "
4054 "11.\n";
4055 Options options = Options::From("aidl --checkapi old new");
4056 io_delegate_.SetFileContents("old/p/IFoo.aidl", "package p; interface IFoo{ void foo() = 10;}");
4057 io_delegate_.SetFileContents("new/p/IFoo.aidl", "package p; interface IFoo{ void foo() = 10;}");
4058
4059 EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
4060
4061 io_delegate_.SetFileContents("new/p/IFoo.aidl", "package p; interface IFoo{ void foo() = 11;}");
4062 CaptureStderr();
4063 EXPECT_FALSE(::android::aidl::check_api(options, io_delegate_));
4064 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4065 }
4066
TEST_P(AidlTest,ParcelFileDescriptorIsBuiltinType)4067 TEST_P(AidlTest, ParcelFileDescriptorIsBuiltinType) {
4068 Options options =
4069 Options::From("aidl -I . --lang=" + to_string(GetLanguage()) + " -h out -o out p/IFoo.aidl");
4070
4071 // use without import
4072 io_delegate_.SetFileContents("p/IFoo.aidl",
4073 "package p; interface IFoo{ void foo(in ParcelFileDescriptor fd);}");
4074 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4075
4076 // capture output files
4077 map<string, string> outputs = io_delegate_.OutputFiles();
4078
4079 // use without import but with full name
4080 io_delegate_.SetFileContents(
4081 "p/IFoo.aidl",
4082 "package p; interface IFoo{ void foo(in android.os.ParcelFileDescriptor fd);}");
4083 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4084 // output files should be the same
4085 EXPECT_EQ(outputs, io_delegate_.OutputFiles());
4086
4087 // use with import (as before)
4088 io_delegate_.SetFileContents("p/IFoo.aidl",
4089 "package p;"
4090 "import android.os.ParcelFileDescriptor;"
4091 "interface IFoo{"
4092 " void foo(in ParcelFileDescriptor fd);"
4093 "}");
4094 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4095 // output files should be the same
4096 EXPECT_EQ(outputs, io_delegate_.OutputFiles());
4097 }
4098
TEST_P(AidlTest,RejectsOutputParcelFileDescriptor)4099 TEST_P(AidlTest, RejectsOutputParcelFileDescriptor) {
4100 Options options = Options::From("aidl p/IFoo.aidl -I . --lang=" + to_string(GetLanguage()));
4101 CaptureStderr();
4102 io_delegate_.SetFileContents("p/IFoo.aidl",
4103 "package p;"
4104 "interface IFoo{"
4105 " void foo(out ParcelFileDescriptor fd);"
4106 "}");
4107 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4108 EXPECT_THAT(GetCapturedStderr(), HasSubstr("can't be an out parameter"));
4109 }
4110
TEST_P(AidlTest,RejectsArgumentDirectionNotSpecified)4111 TEST_P(AidlTest, RejectsArgumentDirectionNotSpecified) {
4112 Options options = Options::From("aidl p/IFoo.aidl -I . --lang=" + to_string(GetLanguage()));
4113 CaptureStderr();
4114 io_delegate_.SetFileContents("p/IFoo.aidl",
4115 "package p;"
4116 "interface IFoo{"
4117 " void foo(ParcelFileDescriptor fd);"
4118 "}");
4119 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4120 EXPECT_THAT(GetCapturedStderr(),
4121 HasSubstr("ParcelFileDescriptor can be an in or inout parameter."));
4122 }
4123
TEST_F(AidlTest,ManualIds)4124 TEST_F(AidlTest, ManualIds) {
4125 Options options = Options::From("aidl --lang=java -I . -o out IFoo.aidl");
4126 io_delegate_.SetFileContents("IFoo.aidl",
4127 "interface IFoo {\n"
4128 " void foo() = 0;\n"
4129 " void bar() = 1;\n"
4130 "}");
4131 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4132 }
4133
TEST_F(AidlTest,ManualIdsWithMetaTransactions)4134 TEST_F(AidlTest, ManualIdsWithMetaTransactions) {
4135 Options options = Options::From("aidl --lang=java -I . --version 10 -o out IFoo.aidl");
4136 io_delegate_.SetFileContents("IFoo.aidl",
4137 "interface IFoo {\n"
4138 " void foo() = 0;\n"
4139 " void bar() = 1;\n"
4140 "}");
4141 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4142 }
4143
TEST_F(AidlTest,FailOnDuplicatedIds)4144 TEST_F(AidlTest, FailOnDuplicatedIds) {
4145 const string expected_stderr =
4146 "ERROR: IFoo.aidl:3.7-11: Found duplicate method id (3) for method bar\n";
4147 Options options = Options::From("aidl --lang=java -I . --version 10 -o out IFoo.aidl");
4148 io_delegate_.SetFileContents("IFoo.aidl",
4149 "interface IFoo {\n"
4150 " void foo() = 3;\n"
4151 " void bar() = 3;\n"
4152 "}");
4153 CaptureStderr();
4154 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4155 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4156 }
4157
TEST_F(AidlTest,FailOnOutOfRangeIds)4158 TEST_F(AidlTest, FailOnOutOfRangeIds) {
4159 // 16777115 is kLastMetaMethodId + 1
4160 const string expected_stderr =
4161 "ERROR: IFoo.aidl:3.7-11: Found out of bounds id (16777115) for method bar. "
4162 "Value for id must be between 0 and 16777114 inclusive.\n";
4163 Options options = Options::From("aidl --lang=java -I . --version 10 -o out IFoo.aidl");
4164 io_delegate_.SetFileContents("IFoo.aidl",
4165 "interface IFoo {\n"
4166 " void foo() = 3;\n"
4167 " void bar() = 16777115;\n"
4168 "}");
4169 CaptureStderr();
4170 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4171 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4172 }
4173
TEST_F(AidlTest,FailOnPartiallyAssignedIds)4174 TEST_F(AidlTest, FailOnPartiallyAssignedIds) {
4175 const string expected_stderr =
4176 "ERROR: IFoo.aidl:3.7-11: You must either assign id's to all methods or to none of them.\n";
4177 Options options = Options::From("aidl --lang=java -I . --version 10 -o out IFoo.aidl");
4178 io_delegate_.SetFileContents("IFoo.aidl",
4179 "interface IFoo {\n"
4180 " void foo() = 3;\n"
4181 " void bar();\n"
4182 "}");
4183 CaptureStderr();
4184 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4185 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4186 }
4187
TEST_F(AidlTest,AssignedIds)4188 TEST_F(AidlTest, AssignedIds) {
4189 CaptureStderr();
4190 EXPECT_NE(nullptr, Parse("IFoo.aidl",
4191 "interface IFoo {\n"
4192 " void foo();\n"
4193 " void bar();\n"
4194 " interface INested {\n"
4195 " void foo();\n"
4196 " void bar();\n"
4197 " }\n"
4198 "}",
4199 typenames_, Options::Language::JAVA));
4200 EXPECT_EQ("", GetCapturedStderr());
4201 auto foo = typenames_.ResolveTypename("IFoo").defined_type;
4202 ASSERT_EQ(2u, foo->GetMethods().size());
4203 EXPECT_EQ(0, foo->GetMethods()[0]->GetId());
4204 EXPECT_EQ(1, foo->GetMethods()[1]->GetId());
4205 auto nested = typenames_.ResolveTypename("IFoo.INested").defined_type;
4206 ASSERT_EQ(2u, nested->GetMethods().size());
4207 EXPECT_EQ(0, nested->GetMethods()[0]->GetId());
4208 EXPECT_EQ(1, nested->GetMethods()[1]->GetId());
4209 }
4210
TEST_F(AidlTest,AllowDuplicatedImportPaths)4211 TEST_F(AidlTest, AllowDuplicatedImportPaths) {
4212 Options options = Options::From("aidl --lang=java -I . -I dir -I dir IFoo.aidl");
4213 io_delegate_.SetFileContents("dir/IBar.aidl", "interface IBar{}");
4214 io_delegate_.SetFileContents("IFoo.aidl", "import IBar; interface IFoo{}");
4215 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4216 }
4217
TEST_F(AidlTest,UnusedImportDoesNotContributeInclude)4218 TEST_F(AidlTest, UnusedImportDoesNotContributeInclude) {
4219 io_delegate_.SetFileContents("a/b/IFoo.aidl",
4220 "package a.b;\n"
4221 "import a.b.IBar;\n"
4222 "import a.b.IQux;\n"
4223 "interface IFoo { IQux foo(); }\n");
4224 io_delegate_.SetFileContents("a/b/IBar.aidl", "package a.b; interface IBar { void foo(); }");
4225 io_delegate_.SetFileContents("a/b/IQux.aidl", "package a.b; interface IQux { void foo(); }");
4226
4227 Options options = Options::From("aidl --lang=ndk a/b/IFoo.aidl -I . -o out -h out/include");
4228 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4229
4230 string output;
4231 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/include/aidl/a/b/IFoo.h", &output));
4232 // IBar was imported but wasn't used. include is not expected.
4233 EXPECT_THAT(output, Not(testing::HasSubstr("#include <aidl/a/b/IBar.h>")));
4234 // IBar was imported and used. include is expected.
4235 EXPECT_THAT(output, (testing::HasSubstr("#include <aidl/a/b/IQux.h>")));
4236 }
4237
TEST_F(AidlTest,BasePathAsImportPath)4238 TEST_F(AidlTest, BasePathAsImportPath) {
4239 Options options = Options::From("aidl --lang=java -I some -I other some/dir/pkg/name/IFoo.aidl");
4240 io_delegate_.SetFileContents("some/dir/pkg/name/IFoo.aidl",
4241 "package pkg.name; interface IFoo { void foo(); }");
4242 const string expected_stderr =
4243 "ERROR: some/dir/pkg/name/IFoo.aidl:1.18-28: directory some/dir/ is not found in any of "
4244 "the import paths:\n - other/\n - some/\n";
4245 CaptureStderr();
4246 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4247 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4248 }
4249
TEST_F(AidlTest,ParseJavaPassthroughAnnotation)4250 TEST_F(AidlTest, ParseJavaPassthroughAnnotation) {
4251 io_delegate_.SetFileContents("a/IFoo.aidl", R"--(package a;
4252 import a.MyEnum;
4253 @JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
4254 @JavaPassthrough(annotation="@com.android.AliceTwo")
4255 interface IFoo {
4256 @JavaPassthrough(annotation="@com.android.Bob")
4257 void foo(@JavaPassthrough(annotation="@com.android.Cat") int x, MyEnum y);
4258 const @JavaPassthrough(annotation="@com.android.David") int A = 3;
4259 })--");
4260 // JavaPassthrough should work with other types as well (e.g. enum)
4261 io_delegate_.SetFileContents("a/MyEnum.aidl", R"--(package a;
4262 @JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
4263 @JavaPassthrough(annotation="@com.android.AliceTwo")
4264 @Backing(type="byte")
4265 enum MyEnum {
4266 a, b, c
4267 })--");
4268
4269 Options java_options = Options::From("aidl -I . --lang=java -o out a/IFoo.aidl a/MyEnum.aidl");
4270 EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
4271
4272 string java_out;
4273 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/IFoo.java", &java_out));
4274 // type-decl-level annotations with newline at the end
4275 EXPECT_THAT(java_out, testing::HasSubstr("@com.android.Alice(arg=com.android.Alice.Value.A)\n"));
4276 EXPECT_THAT(java_out, testing::HasSubstr("@com.android.AliceTwo\n"));
4277 // member-decl-level annotations with newline at the end
4278 EXPECT_THAT(java_out, testing::HasSubstr("@com.android.Bob\n"));
4279 EXPECT_THAT(java_out, testing::HasSubstr("@com.android.David\n"));
4280 // inline annotations with space at the end
4281 EXPECT_THAT(java_out, testing::HasSubstr("@com.android.Cat "));
4282
4283 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/MyEnum.java", &java_out));
4284 // type-decl-level annotations with newline at the end
4285 EXPECT_THAT(java_out, testing::HasSubstr("@com.android.Alice(arg=com.android.Alice.Value.A)\n"));
4286 EXPECT_THAT(java_out, testing::HasSubstr("@com.android.AliceTwo\n"));
4287
4288 // Other backends shouldn't be bothered
4289 Options cpp_options =
4290 Options::From("aidl -I . --lang=cpp -o out -h out a/IFoo.aidl a/MyEnum.aidl");
4291 EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
4292
4293 Options ndk_options =
4294 Options::From("aidl -I . --lang=ndk -o out -h out a/IFoo.aidl a/MyEnum.aidl");
4295 EXPECT_TRUE(compile_aidl(ndk_options, io_delegate_));
4296
4297 Options rust_options = Options::From("aidl -I . --lang=rust -o out a/IFoo.aidl a/MyEnum.aidl");
4298 EXPECT_TRUE(compile_aidl(rust_options, io_delegate_));
4299 }
4300
TEST_F(AidlTest,ParseRustDerive)4301 TEST_F(AidlTest, ParseRustDerive) {
4302 io_delegate_.SetFileContents("a/Foo.aidl", R"(package a;
4303 @RustDerive(Clone=true, Copy=false)
4304 parcelable Foo {
4305 int a;
4306 })");
4307
4308 Options rust_options = Options::From("aidl -I . --lang=rust -o out a/Foo.aidl");
4309 EXPECT_TRUE(compile_aidl(rust_options, io_delegate_));
4310
4311 string rust_out;
4312 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.rs", &rust_out));
4313 EXPECT_THAT(rust_out, testing::HasSubstr("#[derive(Debug, Clone)]"));
4314
4315 // Other backends shouldn't be bothered
4316 Options cpp_options = Options::From("aidl --lang=cpp -I . -o out -h out a/Foo.aidl");
4317 EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
4318
4319 Options ndk_options = Options::From("aidl --lang=ndk -I . -o out -h out a/Foo.aidl");
4320 EXPECT_TRUE(compile_aidl(ndk_options, io_delegate_));
4321
4322 Options java_options = Options::From("aidl --lang=java -I . -o out a/Foo.aidl");
4323 EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
4324 }
4325
TEST_P(AidlTest,TypesShouldHaveRustDerive)4326 TEST_P(AidlTest, TypesShouldHaveRustDerive) {
4327 CaptureStderr();
4328 string code =
4329 "@RustDerive(PartialEq=true)\n"
4330 "parcelable Foo {\n"
4331 " parcelable Bar {}\n"
4332 " Bar bar;\n"
4333 "}";
4334 EXPECT_EQ(nullptr, Parse("Foo.aidl", code, typenames_, GetLanguage(), nullptr, {}));
4335 EXPECT_THAT(
4336 GetCapturedStderr(),
4337 testing::HasSubstr("Field bar of type with @RustDerive PartialEq also needs to derive this"));
4338 }
4339
TEST_F(AidlTest,EmptyEnforceAnnotation)4340 TEST_F(AidlTest, EmptyEnforceAnnotation) {
4341 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4342 interface IFoo {
4343 @EnforcePermission()
4344 void Protected();
4345 })");
4346
4347 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4348 CaptureStderr();
4349 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4350 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Unable to parse @EnforcePermission annotation"));
4351 }
4352
TEST_F(AidlTest,InterfaceEnforceCondition)4353 TEST_F(AidlTest, InterfaceEnforceCondition) {
4354 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4355 @EnforcePermission("INTERNET")
4356 interface IFoo {
4357 void Protected();
4358 })");
4359
4360 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4361 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4362 }
4363
TEST_F(AidlTest,EnforceConditionAny)4364 TEST_F(AidlTest, EnforceConditionAny) {
4365 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4366 interface IFoo {
4367 @EnforcePermission(anyOf={"INTERNET", "READ_PHONE_STATE"})
4368 void Protected();
4369 })");
4370
4371 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4372 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4373 }
4374
TEST_F(AidlTest,EnforceConditionAll)4375 TEST_F(AidlTest, EnforceConditionAll) {
4376 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4377 interface IFoo {
4378 @EnforcePermission(allOf={"INTERNET", "READ_PHONE_STATE"})
4379 void Protected();
4380 })");
4381
4382 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4383 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4384 }
4385
TEST_F(AidlTest,InterfaceAndMethodEnforceCondition)4386 TEST_F(AidlTest, InterfaceAndMethodEnforceCondition) {
4387 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4388 @EnforcePermission("INTERNET")
4389 interface IFoo {
4390 @EnforcePermission("SYSTEM_UID")
4391 void Protected();
4392 })");
4393
4394 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4395 CaptureStderr();
4396 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4397 EXPECT_THAT(GetCapturedStderr(), HasSubstr("The interface IFoo uses a permission annotation but "
4398 "the method Protected is also annotated"));
4399 }
4400
TEST_F(AidlTest,NoPermissionInterfaceEnforceMethod)4401 TEST_F(AidlTest, NoPermissionInterfaceEnforceMethod) {
4402 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4403 @RequiresNoPermission
4404 interface IFoo {
4405 @EnforcePermission("INTERNET")
4406 void Protected();
4407 })");
4408
4409 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4410 CaptureStderr();
4411 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4412 EXPECT_THAT(GetCapturedStderr(), HasSubstr("The interface IFoo uses a permission annotation but "
4413 "the method Protected is also annotated"));
4414 }
4415
TEST_F(AidlTest,ManualPermissionInterfaceEnforceMethod)4416 TEST_F(AidlTest, ManualPermissionInterfaceEnforceMethod) {
4417 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4418 @PermissionManuallyEnforced
4419 interface IFoo {
4420 @EnforcePermission("INTERNET")
4421 void Protected();
4422 })");
4423
4424 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4425 CaptureStderr();
4426 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4427 EXPECT_THAT(GetCapturedStderr(), HasSubstr("The interface IFoo uses a permission annotation but "
4428 "the method Protected is also annotated"));
4429 }
4430
TEST_F(AidlTest,EnforceInterfaceNoPermissionsMethod)4431 TEST_F(AidlTest, EnforceInterfaceNoPermissionsMethod) {
4432 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4433 @EnforcePermission("INTERNET")
4434 interface IFoo {
4435 @RequiresNoPermission
4436 void Protected();
4437 })");
4438
4439 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4440 CaptureStderr();
4441 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4442 EXPECT_THAT(GetCapturedStderr(), HasSubstr("The interface IFoo uses a permission annotation but "
4443 "the method Protected is also annotated"));
4444 }
4445
TEST_F(AidlTest,EnforceInterfaceManualPermissionMethod)4446 TEST_F(AidlTest, EnforceInterfaceManualPermissionMethod) {
4447 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4448 @EnforcePermission("INTERNET")
4449 interface IFoo {
4450 @PermissionManuallyEnforced
4451 void Protected();
4452 })");
4453
4454 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4455 CaptureStderr();
4456 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4457 EXPECT_THAT(GetCapturedStderr(), HasSubstr("The interface IFoo uses a permission annotation but "
4458 "the method Protected is also annotated"));
4459 }
4460
TEST_F(AidlTest,JavaSuppressLint)4461 TEST_F(AidlTest, JavaSuppressLint) {
4462 io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
4463 @JavaSuppressLint({"NewApi"})
4464 interface IFoo {
4465 })");
4466
4467 Options options = Options::From("aidl --lang=java -I . -o out a/IFoo.aidl");
4468 CaptureStderr();
4469 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4470 EXPECT_EQ(GetCapturedStderr(), "");
4471 string code;
4472 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/IFoo.java", &code));
4473 EXPECT_THAT(code, HasSubstr("@android.annotation.SuppressLint(value = {\"NewApi\"})"));
4474 }
4475
4476 class AidlOutputPathTest : public AidlTest {
4477 protected:
SetUp()4478 void SetUp() override {
4479 AidlTest::SetUp();
4480 io_delegate_.SetFileContents("sub/dir/foo/bar/IFoo.aidl", "package foo.bar; interface IFoo {}");
4481 }
4482
Test(const Options & options,const std::string expected_output_path)4483 void Test(const Options& options, const std::string expected_output_path) {
4484 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4485 // check the existence
4486 EXPECT_TRUE(io_delegate_.GetWrittenContents(expected_output_path, nullptr));
4487 }
4488 };
4489
TEST_F(AidlOutputPathTest,OutDirWithNoOutputFile)4490 TEST_F(AidlOutputPathTest, OutDirWithNoOutputFile) {
4491 // <out_dir> / <package_name> / <type_name>.java
4492 Test(Options::From("aidl -I sub/dir -o out sub/dir/foo/bar/IFoo.aidl"), "out/foo/bar/IFoo.java");
4493 }
4494
TEST_F(AidlOutputPathTest,OutDirWithOutputFile)4495 TEST_F(AidlOutputPathTest, OutDirWithOutputFile) {
4496 // when output file is explicitly set, it is always respected. -o option is
4497 // ignored.
4498 Test(Options::From("aidl -I sub/dir -o out sub/dir/foo/bar/IFoo.aidl output/IFoo.java"),
4499 "output/IFoo.java");
4500 }
4501
TEST_F(AidlOutputPathTest,NoOutDirWithOutputFile)4502 TEST_F(AidlOutputPathTest, NoOutDirWithOutputFile) {
4503 Test(Options::From("aidl -I sub/dir -o out sub/dir/foo/bar/IFoo.aidl output/IFoo.java"),
4504 "output/IFoo.java");
4505 }
4506
TEST_F(AidlOutputPathTest,NoOutDirWithNoOutputFile)4507 TEST_F(AidlOutputPathTest, NoOutDirWithNoOutputFile) {
4508 // output is the same as the input file except for the suffix
4509 Test(Options::From("aidl -I sub/dir sub/dir/foo/bar/IFoo.aidl"), "sub/dir/foo/bar/IFoo.java");
4510 }
4511
TEST_P(AidlTest,PassOnValidUnsignedInt32Int)4512 TEST_P(AidlTest, PassOnValidUnsignedInt32Int) {
4513 EvaluateValidAssignment(
4514 R"(package a; interface IFoo { const int UINT32_VALUE = 2147483650u32; })", "", typenames_,
4515 GetLanguage());
4516 }
4517
TEST_P(AidlTest,FailOnOutOfBoundsUInt32MaxConstInt)4518 TEST_P(AidlTest, FailOnOutOfBoundsUInt32MaxConstInt) {
4519 AidlError error;
4520 const string expected_stderr =
4521 "ERROR: p/IFoo.aidl:3.59-73: Could not parse integer: 4294967300u32\n";
4522 CaptureStderr();
4523 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
4524 R"(package p;
4525 interface IFoo {
4526 const int uint32_max_oob = 4294967300u32;
4527 }
4528 )",
4529 typenames_, GetLanguage(), &error));
4530 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4531 EXPECT_EQ(AidlError::PARSE_ERROR, error);
4532 }
4533
TEST_P(AidlTest,PassOnValidUnsignedInt64Int)4534 TEST_P(AidlTest, PassOnValidUnsignedInt64Int) {
4535 EvaluateValidAssignment(
4536 R"(package a; interface IFoo { const long UINT64_VALUE = 18446744073709551615u64; })", "",
4537 typenames_, GetLanguage());
4538 }
4539
TEST_P(AidlTest,FailOnOutOfBoundsUInt64MaxConstInt)4540 TEST_P(AidlTest, FailOnOutOfBoundsUInt64MaxConstInt) {
4541 AidlError error;
4542 const string expected_stderr =
4543 "ERROR: p/IFoo.aidl:3.60-84: Could not parse integer: 18446744073709551620u64\n";
4544 CaptureStderr();
4545 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
4546 R"(package p;
4547 interface IFoo {
4548 const long uint64_max_oob = 18446744073709551620u64;
4549 }
4550 )",
4551 typenames_, GetLanguage(), &error));
4552 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4553 EXPECT_EQ(AidlError::PARSE_ERROR, error);
4554 }
4555
TEST_P(AidlTest,PassOnValidUnsignedInt32Hex)4556 TEST_P(AidlTest, PassOnValidUnsignedInt32Hex) {
4557 EvaluateValidAssignment(
4558 R"(package a; interface IFoo { const int UINT32_VALUE = 0xffffffffu32; })", "", typenames_,
4559 GetLanguage());
4560 }
4561
TEST_P(AidlTest,FailOnOutOfBoundsUInt32MaxConstHex)4562 TEST_P(AidlTest, FailOnOutOfBoundsUInt32MaxConstHex) {
4563 AidlError error;
4564 const string expected_stderr =
4565 "ERROR: p/IFoo.aidl:3.59-74: Invalid type specifier for an int64 literal: int "
4566 "(0xfffffffffu32).\n";
4567 CaptureStderr();
4568 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
4569 R"(package p;
4570 interface IFoo {
4571 const int uint32_max_oob = 0xfffffffffu32;
4572 }
4573 )",
4574 typenames_, GetLanguage(), &error));
4575 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4576 EXPECT_EQ(AidlError::BAD_TYPE, error);
4577 }
4578
TEST_P(AidlTest,PassOnValidUnsignedInt64Hex)4579 TEST_P(AidlTest, PassOnValidUnsignedInt64Hex) {
4580 EvaluateValidAssignment(
4581 R"(package a; interface IFoo { const int UINT64_VALUE = 0xffffffffffffffffu64; })", "",
4582 typenames_, GetLanguage());
4583 }
4584
TEST_P(AidlTest,FailOnOutOfBoundsUInt64MaxConstHex)4585 TEST_P(AidlTest, FailOnOutOfBoundsUInt64MaxConstHex) {
4586 AidlError error;
4587 const string expected_stderr =
4588 "ERROR: p/IFoo.aidl:3.59-82: Could not parse hexvalue: 0xfffffffffffffffffu64\n";
4589 CaptureStderr();
4590 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
4591 R"(package p;
4592 interface IFoo {
4593 const int uint64_max_oob = 0xfffffffffffffffffu64;
4594 }
4595 )",
4596 typenames_, GetLanguage(), &error));
4597 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4598 EXPECT_EQ(AidlError::PARSE_ERROR, error);
4599 }
4600
TEST_P(AidlTest,FailOnOutOfBoundsInt32MaxConstInt)4601 TEST_P(AidlTest, FailOnOutOfBoundsInt32MaxConstInt) {
4602 AidlError error;
4603 const string expected_stderr =
4604 "ERROR: p/IFoo.aidl:3.58-69: Invalid type specifier for an int64 literal: int "
4605 "(2147483650). Did you mean: 2147483650u32?\n";
4606 CaptureStderr();
4607 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
4608 R"(package p;
4609 interface IFoo {
4610 const int int32_max_oob = 2147483650;
4611 }
4612 )",
4613 typenames_, GetLanguage(), &error));
4614 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4615 EXPECT_EQ(AidlError::BAD_TYPE, error);
4616 }
4617
TEST_P(AidlTest,FailOnOutOfBoundsInt32MinConstInt)4618 TEST_P(AidlTest, FailOnOutOfBoundsInt32MinConstInt) {
4619 AidlError error;
4620 const string expected_stderr =
4621 "ERROR: p/IFoo.aidl:3.58-60: Invalid type specifier for an int64 literal: int "
4622 "(-2147483650).\n";
4623 CaptureStderr();
4624 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
4625 R"(package p;
4626 interface IFoo {
4627 const int int32_min_oob = -2147483650;
4628 }
4629 )",
4630 typenames_, GetLanguage(), &error));
4631 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4632 EXPECT_EQ(AidlError::BAD_TYPE, error);
4633 }
4634
TEST_P(AidlTest,FailOnOutOfBoundsInt64MaxConstInt)4635 TEST_P(AidlTest, FailOnOutOfBoundsInt64MaxConstInt) {
4636 AidlError error;
4637 const string expected_stderr =
4638 "ERROR: p/IFoo.aidl:3.59-86: Could not parse integer: 21474836509999999999999999\n";
4639 CaptureStderr();
4640 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
4641 R"(package p;
4642 interface IFoo {
4643 const long int64_max_oob = 21474836509999999999999999;
4644 }
4645 )",
4646 typenames_, GetLanguage(), &error));
4647 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4648 EXPECT_EQ(AidlError::PARSE_ERROR, error);
4649 }
4650
TEST_P(AidlTest,FailOnOutOfBoundsInt64MinConstInt)4651 TEST_P(AidlTest, FailOnOutOfBoundsInt64MinConstInt) {
4652 AidlError error;
4653 const string expected_stderr =
4654 "ERROR: p/IFoo.aidl:3.61-87: Could not parse integer: 21474836509999999999999999\n";
4655 CaptureStderr();
4656 EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
4657 R"(package p;
4658 interface IFoo {
4659 const long int64_min_oob = -21474836509999999999999999;
4660 }
4661 )",
4662 typenames_, GetLanguage(), &error));
4663 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4664 EXPECT_EQ(AidlError::PARSE_ERROR, error);
4665 }
4666
TEST_P(AidlTest,FailOnOutOfBoundsAutofilledEnum)4667 TEST_P(AidlTest, FailOnOutOfBoundsAutofilledEnum) {
4668 AidlError error;
4669 const string expected_stderr =
4670 "ERROR: p/TestEnum.aidl:5.1-36: Invalid type specifier for an int32 literal: byte (FOO+1).\n"
4671 "ERROR: p/TestEnum.aidl:5.1-36: Enumerator type differs from enum backing type.\n";
4672 CaptureStderr();
4673 EXPECT_EQ(nullptr, Parse("p/TestEnum.aidl",
4674 R"(package p;
4675 @Backing(type="byte")
4676 enum TestEnum {
4677 FOO = 127,
4678 BAR,
4679 }
4680 )",
4681 typenames_, GetLanguage(), &error));
4682 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4683 EXPECT_EQ(AidlError::BAD_TYPE, error);
4684 }
4685
TEST_P(AidlTest,FailOnUnsupportedBackingType)4686 TEST_P(AidlTest, FailOnUnsupportedBackingType) {
4687 AidlError error;
4688 const string expected_stderr =
4689 "ERROR: p/TestEnum.aidl:3.35-44: Invalid backing type: boolean. Backing type must be one of: "
4690 "byte, int, long\n";
4691 CaptureStderr();
4692 EXPECT_EQ(nullptr, Parse("p/TestEnum.aidl",
4693 R"(package p;
4694 @Backing(type="boolean")
4695 enum TestEnum {
4696 FOO = 0,
4697 BAR = 1,
4698 }
4699 )",
4700 typenames_, GetLanguage(), &error));
4701 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4702 EXPECT_EQ(AidlError::BAD_TYPE, error);
4703 }
4704
TEST_P(AidlTest,UnsupportedBackingAnnotationParam)4705 TEST_P(AidlTest, UnsupportedBackingAnnotationParam) {
4706 AidlError error;
4707 const string expected_stderr =
4708 "ERROR: p/TestEnum.aidl:2.1-51: Parameter foo not supported for annotation Backing. It must "
4709 "be one of: type\n";
4710 CaptureStderr();
4711 EXPECT_EQ(nullptr, Parse("p/TestEnum.aidl",
4712 R"(package p;
4713 @Backing(foo="byte")
4714 enum TestEnum {
4715 FOO = 1,
4716 BAR,
4717 }
4718 )",
4719 typenames_, GetLanguage(), &error));
4720 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4721 EXPECT_EQ(AidlError::BAD_TYPE, error);
4722 }
4723
TEST_P(AidlTest,BackingAnnotationRequireTypeParameter)4724 TEST_P(AidlTest, BackingAnnotationRequireTypeParameter) {
4725 const string expected_stderr = "ERROR: Enum.aidl:1.1-9: Missing 'type' on @Backing.\n";
4726 CaptureStderr();
4727 EXPECT_EQ(nullptr, Parse("Enum.aidl", "@Backing enum Enum { FOO }", typenames_, GetLanguage()));
4728 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4729 }
4730
TEST_F(AidlTest,SupportJavaOnlyImmutableAnnotation)4731 TEST_F(AidlTest, SupportJavaOnlyImmutableAnnotation) {
4732 io_delegate_.SetFileContents("Foo.aidl",
4733 "@JavaOnlyImmutable parcelable Foo { int a; Bar b; List<Bar> c; "
4734 "Map<String, Baz> d; Bar[] e; }");
4735 io_delegate_.SetFileContents("Bar.aidl", "@JavaOnlyImmutable parcelable Bar { String a; }");
4736 io_delegate_.SetFileContents("Baz.aidl",
4737 "@JavaOnlyImmutable @JavaOnlyStableParcelable parcelable Baz;");
4738 Options options = Options::From("aidl --lang=java -I . Foo.aidl");
4739 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4740 }
4741
TEST_F(AidlTest,RejectMutableParcelableFromJavaOnlyImmutableParcelable)4742 TEST_F(AidlTest, RejectMutableParcelableFromJavaOnlyImmutableParcelable) {
4743 io_delegate_.SetFileContents("Foo.aidl", "@JavaOnlyImmutable parcelable Foo { Bar bar; }");
4744 io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { String a; }");
4745 string expected_error =
4746 "ERROR: Foo.aidl:1.40-44: The @JavaOnlyImmutable 'Foo' has a non-immutable field "
4747 "named 'bar'.\n";
4748 CaptureStderr();
4749 Options options = Options::From("aidl --lang=java Foo.aidl -I .");
4750 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4751 EXPECT_EQ(expected_error, GetCapturedStderr());
4752 }
4753
TEST_F(AidlTest,JavaOnlyImmutableParcelableWithEnumFields)4754 TEST_F(AidlTest, JavaOnlyImmutableParcelableWithEnumFields) {
4755 io_delegate_.SetFileContents("Foo.aidl", "@JavaOnlyImmutable parcelable Foo { Bar bar; }");
4756 io_delegate_.SetFileContents("Bar.aidl", "enum Bar { FOO }");
4757 CaptureStderr();
4758 Options options = Options::From("aidl --lang=java Foo.aidl -I .");
4759 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4760 EXPECT_EQ("", GetCapturedStderr());
4761 }
4762
TEST_F(AidlTest,RejectMutableParcelableFromJavaOnlyImmutableUnion)4763 TEST_F(AidlTest, RejectMutableParcelableFromJavaOnlyImmutableUnion) {
4764 io_delegate_.SetFileContents("Foo.aidl", "@JavaOnlyImmutable union Foo { Bar bar; }");
4765 io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { String a; }");
4766 string expected_error =
4767 "ERROR: Foo.aidl:1.35-39: The @JavaOnlyImmutable 'Foo' has a non-immutable field "
4768 "named 'bar'.\n";
4769 CaptureStderr();
4770 Options options = Options::From("aidl --lang=java Foo.aidl -I .");
4771 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4772 EXPECT_EQ(expected_error, GetCapturedStderr());
4773 }
4774
TEST_F(AidlTest,ImmutableParcelableCannotBeInOut)4775 TEST_F(AidlTest, ImmutableParcelableCannotBeInOut) {
4776 io_delegate_.SetFileContents("Foo.aidl", "@JavaOnlyImmutable parcelable Foo { int a; }");
4777 io_delegate_.SetFileContents("IBar.aidl", "interface IBar { void my(inout Foo foo); }");
4778 string expected_error =
4779 "ERROR: IBar.aidl:1.35-39: 'foo' can't be an inout parameter because @JavaOnlyImmutable can "
4780 "only be an in parameter.\n";
4781 CaptureStderr();
4782 Options options = Options::From("aidl --lang=java IBar.aidl -I .");
4783 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4784 EXPECT_EQ(expected_error, GetCapturedStderr());
4785 }
4786
TEST_F(AidlTest,ImmutableParcelableCannotBeOut)4787 TEST_F(AidlTest, ImmutableParcelableCannotBeOut) {
4788 io_delegate_.SetFileContents("Foo.aidl", "@JavaOnlyImmutable parcelable Foo { int a; }");
4789 io_delegate_.SetFileContents("IBar.aidl", "interface IBar { void my(out Foo foo); }");
4790 string expected_error =
4791 "ERROR: IBar.aidl:1.33-37: 'foo' can't be an out parameter because @JavaOnlyImmutable can "
4792 "only be an in parameter.\n";
4793 CaptureStderr();
4794 Options options = Options::From("aidl --lang=java IBar.aidl -I .");
4795 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4796 EXPECT_EQ(expected_error, GetCapturedStderr());
4797 }
4798
TEST_F(AidlTest,ImmutableParcelableFieldNameRestriction)4799 TEST_F(AidlTest, ImmutableParcelableFieldNameRestriction) {
4800 io_delegate_.SetFileContents("Foo.aidl", "@JavaOnlyImmutable parcelable Foo { int a; int A; }");
4801 Options options = Options::From("aidl -I . --lang=java Foo.aidl");
4802 const string expected_stderr =
4803 "ERROR: Foo.aidl:1.47-49: 'Foo' has duplicate field name 'A' after capitalizing the first "
4804 "letter\n";
4805 CaptureStderr();
4806 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4807 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4808 }
4809
TEST_P(AidlTest,UnionInUnion)4810 TEST_P(AidlTest, UnionInUnion) {
4811 import_paths_.insert(".");
4812 io_delegate_.SetFileContents("Bar.aidl", "union Bar { int n = 42; long l; }");
4813 CaptureStderr();
4814 EXPECT_NE(nullptr, Parse("Foo.aidl", "union Foo { Bar b; int n; }", typenames_, GetLanguage()));
4815 EXPECT_THAT("", GetCapturedStderr());
4816 }
4817
TEST_P(AidlTest,UnionRejectsEmptyDecl)4818 TEST_P(AidlTest, UnionRejectsEmptyDecl) {
4819 const string method = "package a; union Foo {}";
4820 const string expected_stderr = "ERROR: a/Foo.aidl:1.17-21: The union 'Foo' has no fields.\n";
4821 CaptureStderr();
4822 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, GetLanguage()));
4823 EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr(expected_stderr));
4824 }
4825
TEST_P(AidlTest,UnionRejectsParcelableHolder)4826 TEST_P(AidlTest, UnionRejectsParcelableHolder) {
4827 const string method = "package a; union Foo { ParcelableHolder x; }";
4828 const string expected_stderr =
4829 "ERROR: a/Foo.aidl:1.40-42: A union can't have a member of ParcelableHolder 'x'\n";
4830 CaptureStderr();
4831 EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, GetLanguage()));
4832 EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr(expected_stderr));
4833 }
4834
TEST_P(AidlTest,UnionRejectsFirstEnumWithNoDefaults)4835 TEST_P(AidlTest, UnionRejectsFirstEnumWithNoDefaults) {
4836 import_paths_.insert(".");
4837 io_delegate_.SetFileContents("a/Enum.aidl", "package a; enum Enum { FOO, BAR }");
4838 const string expected_err = "The union's first member should have a useful default value.";
4839 CaptureStderr();
4840 EXPECT_EQ(nullptr,
4841 Parse("a/Foo.aidl", "package a; union Foo { a.Enum e; }", typenames_, GetLanguage()));
4842 EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr(expected_err));
4843 }
4844
TEST_P(AidlTest,GenericStructuredParcelable)4845 TEST_P(AidlTest, GenericStructuredParcelable) {
4846 io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo<T, U> { int a; int A; }");
4847 Options options = Options::From("aidl -I . Foo.aidl --lang=" + to_string(GetLanguage()));
4848 const string expected_stderr = "";
4849 CaptureStderr();
4850 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4851 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4852 }
4853
TEST_F(AidlTest,GenericStructuredParcelableWithStringConstants_Cpp)4854 TEST_F(AidlTest, GenericStructuredParcelableWithStringConstants_Cpp) {
4855 io_delegate_.SetFileContents("Foo.aidl",
4856 "parcelable Foo<T, U> { int a; const String s = \"\"; }");
4857 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(Options::Language::CPP) +
4858 " -o out -h out");
4859 const string expected_stderr = "";
4860 CaptureStderr();
4861 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4862 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4863
4864 string code;
4865 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/Foo.h", &code));
4866 EXPECT_THAT(code, testing::HasSubstr(R"--(template <typename T, typename U>
4867 const ::android::String16& Foo<T,U>::s() {
4868 static const ::android::String16 value(::android::String16(""));
4869 return value;
4870 })--"));
4871 }
4872
TEST_F(AidlTest,GenericStructuredParcelableWithStringConstants_Ndk)4873 TEST_F(AidlTest, GenericStructuredParcelableWithStringConstants_Ndk) {
4874 io_delegate_.SetFileContents("Foo.aidl",
4875 "parcelable Foo<T, U> { int a; const String s = \"\"; }");
4876 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(Options::Language::NDK) +
4877 " -o out -h out");
4878 const string expected_stderr = "";
4879 CaptureStderr();
4880 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4881 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4882
4883 string code;
4884 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/aidl/Foo.h", &code));
4885 EXPECT_THAT(code, testing::HasSubstr(R"--(template <typename T, typename U>
4886 const char* Foo<T, U>::s = "";
4887 )--"));
4888 }
4889
TEST_F(AidlTest,NestedTypeArgs)4890 TEST_F(AidlTest, NestedTypeArgs) {
4891 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar<A> { }");
4892 io_delegate_.SetFileContents("a/Baz.aidl", "package a; parcelable Baz<A, B> { }");
4893
4894 io_delegate_.SetFileContents("a/Foo.aidl",
4895 "package a; import a.Bar; import a.Baz; parcelable Foo { "
4896 "Baz<Bar<Bar<String[]>>[], Bar<String>> barss; }");
4897 Options options = Options::From("aidl a/Foo.aidl -I . -o out --lang=java");
4898 const string expected_stderr = "";
4899 CaptureStderr();
4900 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4901 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4902
4903 string code;
4904 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &code));
4905 EXPECT_THAT(code,
4906 testing::HasSubstr(
4907 "a.Baz<a.Bar<a.Bar<java.lang.String[]>>[],a.Bar<java.lang.String>> barss;"));
4908 }
4909
TEST_F(AidlTest,AcceptMultiDimensionalFixedSizeArray)4910 TEST_F(AidlTest, AcceptMultiDimensionalFixedSizeArray) {
4911 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[2][3] a; }");
4912
4913 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=ndk");
4914 CaptureStderr();
4915 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4916 EXPECT_EQ("", GetCapturedStderr());
4917 }
4918
TEST_F(AidlTest,AcceptBinarySizeArray)4919 TEST_F(AidlTest, AcceptBinarySizeArray) {
4920 io_delegate_.SetFileContents(
4921 "a/Bar.aidl", "package a; parcelable Bar { const int CONST = 3; String[CONST + 1] a; }");
4922
4923 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=ndk");
4924 CaptureStderr();
4925 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4926 EXPECT_EQ("", GetCapturedStderr());
4927 }
4928
TEST_F(AidlTest,AcceptRefSizeArray)4929 TEST_F(AidlTest, AcceptRefSizeArray) {
4930 io_delegate_.SetFileContents(
4931 "a/Bar.aidl", "package a; parcelable Bar { const int CONST = 3; String[CONST] a; }");
4932
4933 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=ndk");
4934 CaptureStderr();
4935 EXPECT_TRUE(compile_aidl(options, io_delegate_));
4936 EXPECT_EQ("", GetCapturedStderr());
4937 }
4938
TEST_F(AidlTest,RejectArrayOfFixedSizeArray)4939 TEST_F(AidlTest, RejectArrayOfFixedSizeArray) {
4940 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[2][] a; }");
4941
4942 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
4943 CaptureStderr();
4944 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4945 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
4946 }
4947
TEST_F(AidlTest,RejectFixedSizeArrayOfDynamicArray)4948 TEST_F(AidlTest, RejectFixedSizeArrayOfDynamicArray) {
4949 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[][3] a; }");
4950
4951 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
4952 CaptureStderr();
4953 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4954 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
4955 }
4956
TEST_F(AidlTest,RejectArrayOfArray)4957 TEST_F(AidlTest, RejectArrayOfArray) {
4958 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[][] a; }");
4959
4960 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
4961 CaptureStderr();
4962 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4963 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
4964 }
4965
TEST_F(AidlTest,RejectInvalidArraySize_Negative)4966 TEST_F(AidlTest, RejectInvalidArraySize_Negative) {
4967 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[-1] a; }");
4968
4969 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
4970 CaptureStderr();
4971 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4972 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Array size must be a positive number"));
4973 }
4974
TEST_F(AidlTest,RejectInvalidArraySize_WrongType)4975 TEST_F(AidlTest, RejectInvalidArraySize_WrongType) {
4976 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[\"3\"] a; }");
4977
4978 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
4979 CaptureStderr();
4980 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4981 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Array size must be a positive number"));
4982 }
4983
TEST_F(AidlTest,DoubleGenericError)4984 TEST_F(AidlTest, DoubleGenericError) {
4985 io_delegate_.SetFileContents("a/Bar.aidl",
4986 "package a; parcelable Bar { List<String><String> a; }");
4987
4988 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
4989 const string expected_stderr =
4990 "ERROR: a/Bar.aidl:1.28-33: Can only specify one set of type parameters.\n";
4991 CaptureStderr();
4992 EXPECT_FALSE(compile_aidl(options, io_delegate_));
4993 EXPECT_EQ(expected_stderr, GetCapturedStderr());
4994 }
4995
TEST_F(AidlTest,ArrayBeforeGenericError)4996 TEST_F(AidlTest, ArrayBeforeGenericError) {
4997 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { List[]<String> a; }");
4998
4999 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
5000 CaptureStderr();
5001 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5002 EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr("syntax error, unexpected '<'"));
5003 }
5004
TEST_F(AidlTest,NullableArraysAreNotSupported)5005 TEST_F(AidlTest, NullableArraysAreNotSupported) {
5006 io_delegate_.SetFileContents("a/Bar.aidl",
5007 "package a; parcelable Bar { String @nullable [] a; }");
5008
5009 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
5010 CaptureStderr();
5011 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5012 EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr("Annotations for arrays are not supported."));
5013 }
5014
TEST_F(AidlTest,ListOfNullablesAreNotSupported)5015 TEST_F(AidlTest, ListOfNullablesAreNotSupported) {
5016 io_delegate_.SetFileContents("a/Bar.aidl",
5017 "package a; parcelable Bar { List<@nullable String> a; }");
5018
5019 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
5020 CaptureStderr();
5021 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5022 EXPECT_THAT(GetCapturedStderr(),
5023 testing::HasSubstr("Annotations for type arguments are not supported."));
5024 }
5025
TEST_F(AidlTest,DefaultShouldMatchWithFixedSizeArray)5026 TEST_F(AidlTest, DefaultShouldMatchWithFixedSizeArray) {
5027 io_delegate_.SetFileContents("a/Bar.aidl",
5028 "package a;\n"
5029 "parcelable Bar {\n"
5030 " int[2][3] a = {{1,2,3}, {4,5,6}};\n"
5031 "}");
5032
5033 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=ndk");
5034 CaptureStderr();
5035 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5036 EXPECT_EQ("", GetCapturedStderr());
5037 }
5038
TEST_F(AidlTest,FixedSizeArrayWithWrongTypeDefaultValue)5039 TEST_F(AidlTest, FixedSizeArrayWithWrongTypeDefaultValue) {
5040 io_delegate_.SetFileContents("a/Bar.aidl",
5041 "package a;\n"
5042 "parcelable Bar {\n"
5043 " int[2][3] a = {{\"1\",\"2\",\"3\"}, {4,5,6}};\n"
5044 "}");
5045
5046 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
5047 CaptureStderr();
5048 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5049 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Invalid type specifier for a literal string: int"));
5050 }
5051
TEST_F(AidlTest,FixedSizeArrayWithMoreElements)5052 TEST_F(AidlTest, FixedSizeArrayWithMoreElements) {
5053 io_delegate_.SetFileContents("a/Bar.aidl",
5054 "package a;\n"
5055 "parcelable Bar {\n"
5056 " int[2][3] a = {{1,2,3,4}, {4,5,6}};\n"
5057 "}");
5058
5059 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
5060 CaptureStderr();
5061 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5062 EXPECT_THAT(GetCapturedStderr(),
5063 HasSubstr("Expected an array of 3 elements, but found one with 4 elements"));
5064 }
5065
TEST_F(AidlTest,FixedSizeArrayWithFewerElements)5066 TEST_F(AidlTest, FixedSizeArrayWithFewerElements) {
5067 io_delegate_.SetFileContents("a/Bar.aidl",
5068 "package a;\n"
5069 "parcelable Bar {\n"
5070 " int[2][3] a = {};\n"
5071 "}");
5072
5073 Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
5074 CaptureStderr();
5075 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5076 EXPECT_THAT(GetCapturedStderr(),
5077 HasSubstr("Expected an array of 2 elements, but found one with 0 elements"));
5078 }
5079
5080 struct GenericAidlTest : ::testing::Test {
5081 FakeIoDelegate io_delegate_;
Compileandroid::aidl::GenericAidlTest5082 void Compile(string cmd) {
5083 io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo { Bar<Baz<Qux>> x; }");
5084 io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar<T> { }");
5085 io_delegate_.SetFileContents("Baz.aidl", "parcelable Baz<T> { }");
5086 io_delegate_.SetFileContents("Qux.aidl", "parcelable Qux { }");
5087
5088 Options options = Options::From(cmd);
5089 CaptureStderr();
5090 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5091 EXPECT_EQ("", GetCapturedStderr());
5092 }
5093 };
5094
TEST_F(GenericAidlTest,ImportGenericParameterTypesCPP)5095 TEST_F(GenericAidlTest, ImportGenericParameterTypesCPP) {
5096 Compile("aidl Foo.aidl --lang=cpp -I . -o out -h out");
5097 string code;
5098 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/Foo.h", &code));
5099 EXPECT_THAT(code, testing::HasSubstr("#include <Bar.h>"));
5100 EXPECT_THAT(code, testing::HasSubstr("#include <Baz.h>"));
5101 EXPECT_THAT(code, testing::HasSubstr("#include <Qux.h>"));
5102 }
5103
TEST_F(GenericAidlTest,ImportGenericParameterTypesNDK)5104 TEST_F(GenericAidlTest, ImportGenericParameterTypesNDK) {
5105 Compile("aidl Foo.aidl --lang=ndk -I . -o out -h out");
5106 string code;
5107 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/aidl/Foo.h", &code));
5108 EXPECT_THAT(code, testing::HasSubstr("#include <aidl/Bar.h>"));
5109 EXPECT_THAT(code, testing::HasSubstr("#include <aidl/Baz.h>"));
5110 EXPECT_THAT(code, testing::HasSubstr("#include <aidl/Qux.h>"));
5111 }
5112
TEST_P(AidlTest,RejectGenericStructuredParcelabelRepeatedParam)5113 TEST_P(AidlTest, RejectGenericStructuredParcelabelRepeatedParam) {
5114 io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo<T,T> { int a; int A; }");
5115 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
5116 const string expected_stderr =
5117 "ERROR: Foo.aidl:1.11-15: Every type parameter should be unique.\n";
5118 CaptureStderr();
5119 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5120 EXPECT_EQ(expected_stderr, GetCapturedStderr());
5121 }
5122
TEST_P(AidlTest,RejectGenericStructuredParcelableField)5123 TEST_P(AidlTest, RejectGenericStructuredParcelableField) {
5124 io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo<T,T> { T a; int A; }");
5125 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
5126 const string expected_stderr =
5127 "ERROR: Foo.aidl: Couldn't find import for class T. Searched here:\n - ./\nERROR: "
5128 "Foo.aidl:1.22-24: Failed to resolve 'T'\n";
5129 CaptureStderr();
5130 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5131 EXPECT_EQ(expected_stderr, GetCapturedStderr());
5132 }
5133
TEST_P(AidlTest,LongCommentWithinConstExpression)5134 TEST_P(AidlTest, LongCommentWithinConstExpression) {
5135 io_delegate_.SetFileContents("Foo.aidl", "enum Foo { FOO = (1 << 1) /* comment */ | 0x0 }");
5136 Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
5137 CaptureStderr();
5138 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5139 EXPECT_EQ("", GetCapturedStderr());
5140 }
5141
TEST_F(AidlTest,RejectUntypdeListAndMapInUnion)5142 TEST_F(AidlTest, RejectUntypdeListAndMapInUnion) {
5143 io_delegate_.SetFileContents("a/Foo.aidl", "package a; union Foo { List l; Map m; }");
5144 Options options = Options::From("aidl a/Foo.aidl -I . --lang=java -o out");
5145 std::string expectedErr =
5146 "ERROR: a/Foo.aidl:1.28-30: "
5147 "Encountered an untyped List or Map. The use of untyped List/Map is "
5148 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
5149 "the receiving side. Consider switching to an array or a generic List/Map.\n"
5150 "ERROR: a/Foo.aidl:1.35-37: "
5151 "Encountered an untyped List or Map. The use of untyped List/Map is "
5152 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
5153 "the receiving side. Consider switching to an array or a generic List/Map.\n";
5154 CaptureStderr();
5155 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5156 EXPECT_EQ(expectedErr, GetCapturedStderr());
5157 }
5158
TEST_F(AidlTest,RejectUntypdeListAndMapInUnstructuredParcelable)5159 TEST_F(AidlTest, RejectUntypdeListAndMapInUnstructuredParcelable) {
5160 io_delegate_.SetFileContents("a/Foo.aidl", "package a; parcelable Foo { List l; Map m; }");
5161 Options options = Options::From("aidl a/Foo.aidl -I . --lang=java -o out");
5162 std::string expectedErr =
5163 "ERROR: a/Foo.aidl:1.33-35: "
5164 "Encountered an untyped List or Map. The use of untyped List/Map is "
5165 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
5166 "the receiving side. Consider switching to an array or a generic List/Map.\n"
5167 "ERROR: a/Foo.aidl:1.40-42: "
5168 "Encountered an untyped List or Map. The use of untyped List/Map is "
5169 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
5170 "the receiving side. Consider switching to an array or a generic List/Map.\n";
5171 CaptureStderr();
5172 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5173 EXPECT_EQ(expectedErr, GetCapturedStderr());
5174 }
5175
TEST_F(AidlTest,RejectNestedUntypedListAndMap)5176 TEST_F(AidlTest, RejectNestedUntypedListAndMap) {
5177 io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar<T>;");
5178 io_delegate_.SetFileContents(
5179 "a/Foo.aidl", "package a; import a.Bar; parcelable Foo { Bar<List> a; Bar<Map> b; }");
5180 Options options = Options::From("aidl a/Foo.aidl -I . --lang=java -o out");
5181 std::string expectedErr =
5182 "ERROR: a/Foo.aidl:1.52-54: "
5183 "Encountered an untyped List or Map. The use of untyped List/Map is "
5184 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
5185 "the receiving side. Consider switching to an array or a generic List/Map.\n"
5186 "ERROR: a/Foo.aidl:1.64-66: "
5187 "Encountered an untyped List or Map. The use of untyped List/Map is "
5188 "prohibited because it is not guaranteed that the objects in the list are recognizable in "
5189 "the receiving side. Consider switching to an array or a generic List/Map.\n";
5190 CaptureStderr();
5191 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5192 EXPECT_EQ(expectedErr, GetCapturedStderr());
5193 }
5194
TEST_F(AidlTest,EnumWithDefaults_Java)5195 TEST_F(AidlTest, EnumWithDefaults_Java) {
5196 io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO, BAR }");
5197 io_delegate_.SetFileContents("a/p/Foo.aidl", R"(
5198 package p;
5199 import p.Enum;
5200 parcelable Foo {
5201 Enum e = Enum.BAR;
5202 })");
5203 CaptureStderr();
5204 auto options = Options::From("aidl -I a --lang java -o out a/p/Foo.aidl");
5205 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5206 auto err = GetCapturedStderr();
5207 EXPECT_EQ("", err);
5208
5209 string code;
5210 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/p/Foo.java", &code));
5211 EXPECT_THAT(code, testing::HasSubstr("byte e = p.Enum.BAR"));
5212 }
5213
TEST_F(AidlTest,EnumWithDefaults_Cpp)5214 TEST_F(AidlTest, EnumWithDefaults_Cpp) {
5215 io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO, BAR }");
5216 io_delegate_.SetFileContents("a/p/Foo.aidl", R"(
5217 package p;
5218 import p.Enum;
5219 parcelable Foo {
5220 Enum e = Enum.BAR;
5221 })");
5222 CaptureStderr();
5223 auto options = Options::From("aidl -I a --lang cpp -o out -h out a/p/Foo.aidl");
5224 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5225 auto err = GetCapturedStderr();
5226 EXPECT_EQ("", err);
5227
5228 string code;
5229 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/p/Foo.h", &code));
5230 EXPECT_THAT(code, testing::HasSubstr("::p::Enum e = ::p::Enum::BAR;"));
5231 }
5232
TEST_F(AidlTest,EnumWithDefaults_Ndk)5233 TEST_F(AidlTest, EnumWithDefaults_Ndk) {
5234 io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO, BAR }");
5235 io_delegate_.SetFileContents("a/p/Foo.aidl", R"(
5236 package p;
5237 import p.Enum;
5238 parcelable Foo {
5239 Enum e = Enum.BAR;
5240 })");
5241 CaptureStderr();
5242 auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
5243 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5244 auto err = GetCapturedStderr();
5245 EXPECT_EQ("", err);
5246
5247 string code;
5248 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/aidl/p/Foo.h", &code));
5249 EXPECT_THAT(code, testing::HasSubstr("::aidl::p::Enum e = ::aidl::p::Enum::BAR;"));
5250 }
5251
TEST_F(AidlTest,EnumWithDefaults_Rust)5252 TEST_F(AidlTest, EnumWithDefaults_Rust) {
5253 io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO, BAR }");
5254 io_delegate_.SetFileContents("a/p/Foo.aidl", R"(
5255 package p;
5256 import p.Enum;
5257 parcelable Foo {
5258 int n = 42;
5259 Enum e = Enum.BAR;
5260 })");
5261 CaptureStderr();
5262 auto options = Options::From("aidl -I a --lang rust -o out -h out a/p/Foo.aidl");
5263 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5264 auto err = GetCapturedStderr();
5265 EXPECT_EQ("", err);
5266
5267 string code;
5268 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/p/Foo.rs", &code));
5269 EXPECT_THAT(code, testing::HasSubstr(R"(
5270 fn default() -> Self {
5271 Self {
5272 r#n: 42,
5273 r#e: crate::mangled::_1_p_4_Enum::BAR,
5274 }
5275 })"));
5276 }
5277
TEST_P(AidlTest,EnumeratorIsConstantValue_DefaultValue)5278 TEST_P(AidlTest, EnumeratorIsConstantValue_DefaultValue) {
5279 import_paths_.insert("a");
5280 io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO = 1, BAR = 2}");
5281 CaptureStderr();
5282 const AidlDefinedType* type = Parse("a/p/Foo.aidl", R"(
5283 package p;
5284 import p.Enum;
5285 parcelable Foo {
5286 int e = Enum.FOO | Enum.BAR;
5287 })",
5288 typenames_, GetLanguage());
5289 auto err = GetCapturedStderr();
5290 EXPECT_EQ("", err);
5291 EXPECT_TRUE(type);
5292 const auto& fields = type->AsStructuredParcelable()->GetFields();
5293 EXPECT_EQ("int e = 3", fields[0]->ToString());
5294 }
5295
TEST_F(AidlTest,EnumeratorIsConstantValue_CanDefineOtherEnumerator)5296 TEST_F(AidlTest, EnumeratorIsConstantValue_CanDefineOtherEnumerator) {
5297 CaptureStderr();
5298 const AidlDefinedType* type = Parse("a/p/Foo.aidl", R"(
5299 package a.p;
5300 @Backing(type="int")
5301 enum Foo {
5302 STANDARD_SHIFT = 16,
5303 STANDARD_BT709 = 1 << STANDARD_SHIFT,
5304 STANDARD_BT601_625 = 2 << STANDARD_SHIFT,
5305 }
5306 )",
5307 typenames_, Options::Language::JAVA);
5308 auto err = GetCapturedStderr();
5309 EXPECT_EQ("", err);
5310 ASSERT_NE(type, nullptr);
5311 const auto& enum_type = type->AsEnumDeclaration();
5312 string code;
5313 auto writer = CodeWriter::ForString(&code);
5314 DumpVisitor visitor(*writer, /*inline_constants=*/true);
5315 visitor.Visit(*enum_type);
5316 writer->Close();
5317 EXPECT_EQ(R"--(@Backing(type="int")
5318 enum Foo {
5319 STANDARD_SHIFT = 16,
5320 STANDARD_BT709 = 65536,
5321 STANDARD_BT601_625 = 131072,
5322 }
5323 )--",
5324 code);
5325 }
5326
TEST_F(AidlTest,DumpApiWithConstantReferences)5327 TEST_F(AidlTest, DumpApiWithConstantReferences) {
5328 io_delegate_.SetFileContents("foo/bar/Foo.aidl", R"(
5329 package foo.bar;
5330 import foo.bar.Bar;
5331 import foo.bar.Enum;
5332 parcelable Foo {
5333 int n = Bar.A + 1;
5334 int[] ns = {1, Bar.A, Bar.B + 1};
5335 Enum e = Enum.A;
5336 Enum[] es = {Enum.A, Enum.B};
5337 }
5338 )");
5339 io_delegate_.SetFileContents("foo/bar/Bar.aidl", R"(
5340 package foo.bar;
5341 parcelable Bar {
5342 const int A = 1;
5343 const int B = A + 1;
5344 }
5345 )");
5346 io_delegate_.SetFileContents("foo/bar/Enum.aidl", R"(
5347 package foo.bar;
5348 enum Enum {
5349 A,
5350 B = A + 2,
5351 }
5352 )");
5353 vector<string> args = {"aidl",
5354 "--dumpapi",
5355 "--out=dump",
5356 "--include=.",
5357 "foo/bar/Foo.aidl",
5358 "foo/bar/Bar.aidl",
5359 "foo/bar/Enum.aidl"};
5360 ASSERT_TRUE(dump_api(Options::From(args), io_delegate_));
5361
5362 string actual;
5363 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Foo.aidl", &actual));
5364 EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
5365 parcelable Foo {
5366 int n = (foo.bar.Bar.A + 1) /* 2 */;
5367 int[] ns = {1, foo.bar.Bar.A /* 1 */, (foo.bar.Bar.B + 1) /* 3 */};
5368 foo.bar.Enum e = foo.bar.Enum.A;
5369 foo.bar.Enum[] es = {foo.bar.Enum.A, foo.bar.Enum.B};
5370 }
5371 )"),
5372 actual);
5373 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Bar.aidl", &actual));
5374 EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
5375 parcelable Bar {
5376 const int A = 1;
5377 const int B = (A + 1) /* 2 */;
5378 }
5379 )"),
5380 actual);
5381 EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Enum.aidl", &actual));
5382 EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
5383 enum Enum {
5384 A,
5385 B = (A + 2) /* 2 */,
5386 }
5387 )"),
5388 actual);
5389 }
5390
TEST_F(AidlTest,EnumDefaultShouldBeEnumerators)5391 TEST_F(AidlTest, EnumDefaultShouldBeEnumerators) {
5392 io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO = 1, BAR = 2}");
5393 io_delegate_.SetFileContents("a/p/Foo.aidl", R"(
5394 package p;
5395 import p.Enum;
5396 parcelable Foo {
5397 Enum e = Enum.FOO | Enum.BAR;
5398 })");
5399 CaptureStderr();
5400 auto options = Options::From("aidl -I a --lang java -o out -h out a/p/Foo.aidl");
5401 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5402 auto err = GetCapturedStderr();
5403 EXPECT_EQ("ERROR: a/p/Foo.aidl:5.11-20: Invalid value (Enum.FOO|Enum.BAR) for enum p.Enum\n",
5404 err);
5405 }
5406
TEST_F(AidlTest,EnumDefaultShouldBeEnumerators_RejectsNumericValue)5407 TEST_F(AidlTest, EnumDefaultShouldBeEnumerators_RejectsNumericValue) {
5408 io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO = 1, BAR = 2}");
5409 io_delegate_.SetFileContents("a/p/Foo.aidl", R"(
5410 package p;
5411 import p.Enum;
5412 parcelable Foo {
5413 Enum e = 1;
5414 })");
5415 CaptureStderr();
5416 auto options = Options::From("aidl -I a --lang java -o out -h out a/p/Foo.aidl");
5417 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5418 EXPECT_THAT(GetCapturedStderr(), HasSubstr("Invalid value (1) for enum p.Enum"));
5419 }
5420
TEST_P(AidlTest,DefaultWithEmptyArray)5421 TEST_P(AidlTest, DefaultWithEmptyArray) {
5422 io_delegate_.SetFileContents("a/p/Foo.aidl", "package p; parcelable Foo { p.Bar[] bars = {}; }");
5423 io_delegate_.SetFileContents("a/p/Bar.aidl", "package p; parcelable Bar { }");
5424 CaptureStderr();
5425 auto options =
5426 Options::From("aidl -I a --lang " + to_string(GetLanguage()) + " -o out -h out a/p/Foo.aidl");
5427 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5428 auto err = GetCapturedStderr();
5429 EXPECT_EQ("", err);
5430 }
5431
TEST_P(AidlTest,RejectRefsInAnnotation)5432 TEST_P(AidlTest, RejectRefsInAnnotation) {
5433 io_delegate_.SetFileContents("a/p/IFoo.aidl",
5434 "package p; interface IFoo {\n"
5435 " const String ANNOTATION = \"@Annotation\";\n"
5436 " @JavaPassthrough(annotation=ANNOTATION) void foo();\n"
5437 "}");
5438 CaptureStderr();
5439 auto options = Options::From("aidl -I a --lang " + to_string(GetLanguage()) +
5440 " -o out -h out a/p/IFoo.aidl");
5441 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5442 auto err = GetCapturedStderr();
5443 EXPECT_EQ(
5444 "ERROR: a/p/IFoo.aidl:3.31-41: Value must be a constant expression but contains reference to "
5445 "ANNOTATION.\n",
5446 err);
5447 }
5448
TEST_F(AidlTest,DefaultWithEnumValues)5449 TEST_F(AidlTest, DefaultWithEnumValues) {
5450 io_delegate_.SetFileContents(
5451 "a/p/Foo.aidl",
5452 "package p; import p.Bar; parcelable Foo { Bar[] bars = { Bar.FOO, Bar.FOO }; }");
5453 io_delegate_.SetFileContents("a/p/Bar.aidl", "package p; enum Bar { FOO, BAR }");
5454 CaptureStderr();
5455 auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
5456 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5457 auto err = GetCapturedStderr();
5458 EXPECT_EQ("", err);
5459 string code;
5460 EXPECT_TRUE(io_delegate_.GetWrittenContents("out/aidl/p/Foo.h", &code));
5461 EXPECT_THAT(
5462 code, testing::HasSubstr(
5463 "std::vector<::aidl::p::Bar> bars = {::aidl::p::Bar::FOO, ::aidl::p::Bar::FOO};"));
5464 }
5465
TEST_F(AidlTest,RejectsCircularReferencingEnumerators)5466 TEST_F(AidlTest, RejectsCircularReferencingEnumerators) {
5467 io_delegate_.SetFileContents("a/p/Foo.aidl", "package p; enum Foo { A = B, B }");
5468 CaptureStderr();
5469 auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
5470 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5471 auto err = GetCapturedStderr();
5472 EXPECT_EQ("ERROR: a/p/Foo.aidl:1.26-28: Found a circular reference: B -> A -> B\n", err);
5473 }
5474
TEST_F(AidlTest,RejectsCircularReferencingConsts)5475 TEST_F(AidlTest, RejectsCircularReferencingConsts) {
5476 io_delegate_.SetFileContents("a/p/Foo.aidl",
5477 "package p; parcelable Foo { const int A = A + 1; }");
5478 CaptureStderr();
5479 auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
5480 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5481 auto err = GetCapturedStderr();
5482 EXPECT_EQ("ERROR: a/p/Foo.aidl:1.42-44: Found a circular reference: A -> A\n", err);
5483 }
5484
TEST_F(AidlTest,RecursiveReferences)5485 TEST_F(AidlTest, RecursiveReferences) {
5486 io_delegate_.SetFileContents("a/p/Foo.aidl",
5487 "package p; parcelable Foo { const int A = p.Bar.A + 1; }");
5488 io_delegate_.SetFileContents("a/p/Bar.aidl",
5489 "package p; parcelable Bar { const int A = p.Baz.A + 1; }");
5490 io_delegate_.SetFileContents("a/p/Baz.aidl", "package p; parcelable Baz { const int A = 1; }");
5491 CaptureStderr();
5492 auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
5493 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5494 EXPECT_EQ("", GetCapturedStderr());
5495 }
5496
TEST_P(AidlTest,CircularReferenceWithFullyQualified)5497 TEST_P(AidlTest, CircularReferenceWithFullyQualified) {
5498 io_delegate_.SetFileContents("Foo.aidl", "enum Foo { A = Foo.A }");
5499 auto options =
5500 Options::From("aidl --lang " + to_string(GetLanguage()) + " -I . -o out -h out Foo.aidl");
5501 const string err = "ERROR: Foo.aidl:1.15-21: Found a circular reference: Foo.A -> Foo.A\n";
5502 CaptureStderr();
5503 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5504 EXPECT_EQ(err, GetCapturedStderr());
5505 }
5506
TEST_P(AidlTest,ConstRefsCanPointToTheSameValue)5507 TEST_P(AidlTest, ConstRefsCanPointToTheSameValue) {
5508 io_delegate_.SetFileContents("Foo.aidl", "enum Foo { A = 0 }");
5509 // this demonstrates the case that "Foo.A" const-ref node is visited twice by B and C.
5510 io_delegate_.SetFileContents("Bar.aidl", "enum Bar { A = Foo.A, B = A, C = A }");
5511 auto options =
5512 Options::From("aidl --lang " + to_string(GetLanguage()) + " -I . -o out -h out Bar.aidl");
5513 CaptureStderr();
5514 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5515 EXPECT_EQ("", GetCapturedStderr());
5516 }
5517
TEST_P(AidlTest,UnknownConstReference)5518 TEST_P(AidlTest, UnknownConstReference) {
5519 io_delegate_.SetFileContents("Foo.aidl", " parcelable Foo { int field = UNKNOWN_REF; }");
5520 auto options =
5521 Options::From("aidl -I . --lang " + to_string(GetLanguage()) + " -o out -h out Foo.aidl");
5522 const string err =
5523 "ERROR: Foo.aidl:1.30-42: Can't find UNKNOWN_REF in Foo\n"
5524 "ERROR: Foo.aidl:1.30-42: Unknown reference 'UNKNOWN_REF'\n";
5525 CaptureStderr();
5526 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5527 EXPECT_EQ(err, GetCapturedStderr());
5528 }
5529
TEST_P(AidlTest,ConstExpressionArrays)5530 TEST_P(AidlTest, ConstExpressionArrays) {
5531 io_delegate_.SetFileContents("Foo.aidl", " parcelable Foo { int[] field = {} - {1,2}; }");
5532 auto options =
5533 Options::From("aidl -I . --lang " + to_string(GetLanguage()) + " -o out -h out Foo.aidl");
5534 const string err =
5535 "ERROR: Foo.aidl:1.32-35: Operation '-' is not supported with array literals\n";
5536 CaptureStderr();
5537 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5538 EXPECT_EQ(err, GetCapturedStderr());
5539 }
5540
TEST_P(AidlTest,JavaCompatibleBuiltinTypes)5541 TEST_P(AidlTest, JavaCompatibleBuiltinTypes) {
5542 string contents = R"(
5543 import android.os.IBinder;
5544 import android.os.IInterface;
5545 interface IFoo {}
5546 )";
5547 EXPECT_NE(nullptr, Parse("IFoo.aidl", contents, typenames_, GetLanguage()));
5548 }
5549
TEST_P(AidlTest,WarningInterfaceName)5550 TEST_P(AidlTest, WarningInterfaceName) {
5551 io_delegate_.SetFileContents("p/Foo.aidl", "package p; interface Foo {}");
5552 auto options = Options::From("aidl -I . --lang " + to_string(GetLanguage()) +
5553 " -Winterface-name -o out -h out p/Foo.aidl");
5554 CaptureStderr();
5555 EXPECT_TRUE(compile_aidl(options, io_delegate_));
5556 EXPECT_EQ(
5557 "WARNING: p/Foo.aidl:1.11-21: Interface names should start with I. [-Winterface-name]\n",
5558 GetCapturedStderr());
5559 }
5560
TEST_P(AidlTest,ErrorInterfaceName)5561 TEST_P(AidlTest, ErrorInterfaceName) {
5562 io_delegate_.SetFileContents("p/Foo.aidl", "package p; interface Foo {}");
5563 auto options = Options::From("aidl -I . --lang " + to_string(GetLanguage()) +
5564 " -Winterface-name -Werror -o out -h out p/Foo.aidl");
5565 CaptureStderr();
5566 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5567 EXPECT_EQ("ERROR: p/Foo.aidl:1.11-21: Interface names should start with I. [-Winterface-name]\n",
5568 GetCapturedStderr());
5569 }
5570
TEST_F(AidlTest,RejectsIncorrectOutputFilePathOnLegacyCppInput)5571 TEST_F(AidlTest, RejectsIncorrectOutputFilePathOnLegacyCppInput) {
5572 const std::string input_file = "base/p/q/IFoo.aidl";
5573 const std::string header_dir = "out/";
5574 const std::string output_file = "out/base/p/q/IFoo.cpp";
5575 io_delegate_.SetFileContents(input_file, "package p.q; interface IFoo {}");
5576
5577 auto options = Options::From({"aidl-cpp", "-I base", input_file, header_dir, output_file});
5578 CaptureStderr();
5579 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5580 EXPECT_THAT(
5581 GetCapturedStderr(),
5582 testing::StartsWith(
5583 "ERROR: base/p/q/IFoo.aidl:1.13-23: Output file is expected to be at out/p/q/IFoo.cpp, "
5584 "but is out/base/p/q/IFoo.cpp."));
5585 }
5586
TEST_F(AidlTest,FormatCommentsForJava)5587 TEST_F(AidlTest, FormatCommentsForJava) {
5588 using android::aidl::FormatCommentsForJava;
5589
5590 struct TestCase {
5591 vector<Comment> comments;
5592 string formatted;
5593 };
5594 vector<TestCase> testcases = {
5595 {{}, ""},
5596 {{{"// line comments\n"}}, "// line comments\n"},
5597 {{{"// @hide \n"}}, "// @hide \n"},
5598 // Transform the last block comment as Javadoc.
5599 {{{"/*\n"
5600 " * Hello, world!\n"
5601 " */"}},
5602 "/** Hello, world! */\n"},
5603 {{{"/* @hide */"}}, "/** @hide */\n"},
5604 {{{"/**\n"
5605 " @param foo ...\n"
5606 "*/"}},
5607 "/** @param foo ... */\n"},
5608 {{{"/* @hide */"}, {"/* @hide */"}}, "/* @hide */\n/** @hide */\n"},
5609 {{{"/* @deprecated first */"}, {"/* @deprecated second */"}},
5610 "/* @deprecated first */\n/** @deprecated second */\n"},
5611 {{{"/* @deprecated */"}, {"/** @param foo */"}}, "/* @deprecated */\n/** @param foo */\n"},
5612 // Line comments are printed as they are
5613 {{{"/* @deprecated */"}, {"// line comments\n"}}, "/* @deprecated */\n// line comments\n"},
5614 };
5615 for (const auto& [input, formatted] : testcases) {
5616 EXPECT_EQ(formatted, FormatCommentsForJava(input));
5617 }
5618 }
5619
TEST_F(AidlTest,SuppressWarningsIsNotForArgs)5620 TEST_F(AidlTest, SuppressWarningsIsNotForArgs) {
5621 io_delegate_.SetFileContents(
5622 "IFoo.aidl",
5623 "interface IFoo {\n"
5624 " void foo(in @SuppressWarnings(value={\"inout-parameter\"}) int x);\n"
5625 "}");
5626 auto options = Options::From("aidl -I . --lang=java IFoo.aidl");
5627 CaptureStderr();
5628 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5629 EXPECT_THAT(GetCapturedStderr(), HasSubstr("@SuppressWarnings is not available"));
5630 }
5631
TEST_F(AidlTest,VoidCantBeUsedInMethodParameterType)5632 TEST_F(AidlTest, VoidCantBeUsedInMethodParameterType) {
5633 io_delegate_.SetFileContents("p/IFoo.aidl", "package p; interface IFoo{ void j(void n);}");
5634 auto options = Options::From("aidl -I . --lang=java -o out p/IFoo.aidl");
5635 CaptureStderr();
5636 EXPECT_FALSE(compile_aidl(options, io_delegate_));
5637 EXPECT_THAT(GetCapturedStderr(), HasSubstr("'void' is an invalid type for the parameter 'n'"));
5638 }
5639
TEST_F(AidlTest,InterfaceVectorIsAvailableAfterTiramisu)5640 TEST_F(AidlTest, InterfaceVectorIsAvailableAfterTiramisu) {
5641 io_delegate_.SetFileContents("p/IFoo.aidl",
5642 "package p;\n"
5643 "interface IFoo{\n"
5644 " void foo(in IFoo[] n);\n"
5645 " void bar(in List<IFoo> n);\n"
5646 "}");
5647 CaptureStderr();
5648 EXPECT_FALSE(
5649 compile_aidl(Options::From("aidl -I . --lang=java --min_sdk_version 30 -o out p/IFoo.aidl"),
5650 io_delegate_));
5651 auto captured_stderr = GetCapturedStderr();
5652 EXPECT_THAT(captured_stderr, HasSubstr("Array of interfaces is available since"));
5653 EXPECT_THAT(captured_stderr, HasSubstr("List of interfaces is available since"));
5654
5655 CaptureStderr();
5656 EXPECT_TRUE(compile_aidl(
5657 Options::From("aidl -I . --lang=java --min_sdk_version Tiramisu -o out p/IFoo.aidl"),
5658 io_delegate_));
5659 EXPECT_EQ(GetCapturedStderr(), "");
5660 }
5661
TEST_F(AidlTest,RustNameOf_PfdFixedArray)5662 TEST_F(AidlTest, RustNameOf_PfdFixedArray) {
5663 auto pfd = typenames_.MakeResolvedType(AIDL_LOCATION_HERE, "ParcelFileDescriptor", false);
5664 ASSERT_TRUE(pfd->MakeArray(FixedSizeArray{
5665 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(AIDL_LOCATION_HERE, "2"))}));
5666 ASSERT_TRUE(pfd->MakeArray(FixedSizeArray{
5667 std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(AIDL_LOCATION_HERE, "3"))}));
5668 EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::PARCELABLE_FIELD, false),
5669 "[[Option<binder::ParcelFileDescriptor>; 3]; 2]");
5670 EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::DEFAULT_VALUE, false),
5671 "[[Option<binder::ParcelFileDescriptor>; 3]; 2]");
5672 EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::IN_ARGUMENT, false),
5673 "&[[binder::ParcelFileDescriptor; 3]; 2]");
5674 EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::VALUE, false),
5675 "[[binder::ParcelFileDescriptor; 3]; 2]");
5676 }
5677
TEST_F(AidlTest,RustNameOf_PfdDynamicArray)5678 TEST_F(AidlTest, RustNameOf_PfdDynamicArray) {
5679 auto pfd = typenames_.MakeResolvedType(AIDL_LOCATION_HERE, "ParcelFileDescriptor", true);
5680 EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::PARCELABLE_FIELD, false),
5681 "Vec<binder::ParcelFileDescriptor>");
5682 EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::DEFAULT_VALUE, false),
5683 "Vec<Option<binder::ParcelFileDescriptor>>");
5684 // we use UNSIZED_ARGUMENT mode for input argument of dynamic array
5685 EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::UNSIZED_ARGUMENT, false),
5686 "&[binder::ParcelFileDescriptor]");
5687 EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::VALUE, false),
5688 "Vec<binder::ParcelFileDescriptor>");
5689 }
5690
5691 struct TypeParam {
5692 string kind;
5693 string literal;
5694 };
5695
5696 const TypeParam kTypeParams[] = {
5697 {"primitive", "int"},
5698 {"primitiveArray", "int[]"},
5699 {"primitiveFixedArray", "int[3]"},
5700 {"String", "String"},
5701 {"StringArray", "String[]"},
5702 {"IBinder", "IBinder"},
5703 {"ParcelFileDescriptor", "ParcelFileDescriptor"},
5704 {"parcelable", "a.Foo"},
5705 {"enum", "a.Enum"},
5706 {"union", "a.Union"},
5707 {"interface", "a.IBar"},
5708 };
5709
5710 struct ExpectedResult {
5711 string expected_error;
5712 string expected_error_for_nullable;
5713 };
5714
5715 const std::map<std::string, ExpectedResult> kListSupportExpectations = {
5716 {"cpp_primitive", {"A generic type cannot", "A generic type cannot"}},
5717 {"java_primitive", {"A generic type cannot", "A generic type cannot"}},
5718 {"ndk_primitive", {"A generic type cannot", "A generic type cannot"}},
5719 {"rust_primitive", {"A generic type cannot", "A generic type cannot"}},
5720 {"cpp_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
5721 {"java_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
5722 {"ndk_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
5723 {"rust_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
5724 {"cpp_primitiveFixedArray",
5725 {"List of arrays is not supported", "List of arrays is not supported"}},
5726 {"java_primitiveFixedArray",
5727 {"List of arrays is not supported", "List of arrays is not supported"}},
5728 {"ndk_primitiveFixedArray",
5729 {"List of arrays is not supported", "List of arrays is not supported"}},
5730 {"rust_primitiveFixedArray",
5731 {"List of arrays is not supported", "List of arrays is not supported"}},
5732 {"cpp_String", {"", ""}},
5733 {"java_String", {"", ""}},
5734 {"ndk_String", {"", ""}},
5735 {"rust_String", {"", ""}},
5736 {"cpp_StringArray", {"List of arrays is not supported", "List of arrays is not supported"}},
5737 {"java_StringArray", {"List of arrays is not supported", "List of arrays is not supported"}},
5738 {"ndk_StringArray", {"List of arrays is not supported", "List of arrays is not supported"}},
5739 {"rust_StringArray", {"List of arrays is not supported", "List of arrays is not supported"}},
5740 {"cpp_IBinder", {"", ""}},
5741 {"java_IBinder", {"", ""}},
5742 {"ndk_IBinder", {"", ""}},
5743 {"rust_IBinder", {"", ""}},
5744 {"cpp_ParcelFileDescriptor", {"", ""}},
5745 {"java_ParcelFileDescriptor", {"", ""}},
5746 {"ndk_ParcelFileDescriptor", {"", ""}},
5747 {"rust_ParcelFileDescriptor", {"", ""}},
5748 {"cpp_interface", {"", ""}},
5749 {"java_interface", {"", ""}},
5750 {"ndk_interface", {"", ""}},
5751 {"rust_interface", {"", ""}},
5752 {"cpp_parcelable", {"", ""}},
5753 {"java_parcelable", {"", ""}},
5754 {"ndk_parcelable", {"", ""}},
5755 {"rust_parcelable", {"", ""}},
5756 {"cpp_enum", {"A generic type cannot", "A generic type cannot"}},
5757 {"java_enum", {"A generic type cannot", "A generic type cannot"}},
5758 {"ndk_enum", {"A generic type cannot", "A generic type cannot"}},
5759 {"rust_enum", {"A generic type cannot", "A generic type cannot"}},
5760 {"cpp_union", {"", ""}},
5761 {"java_union", {"", ""}},
5762 {"ndk_union", {"", ""}},
5763 {"rust_union", {"", ""}},
5764 };
5765
5766 const std::map<std::string, ExpectedResult> kArraySupportExpectations = {
5767 {"cpp_primitive", {"", ""}},
5768 {"java_primitive", {"", ""}},
5769 {"ndk_primitive", {"", ""}},
5770 {"rust_primitive", {"", ""}},
5771 {"cpp_primitiveArray",
5772 {"Multi-dimensional arrays must be fixed size.",
5773 "Multi-dimensional arrays must be fixed size."}},
5774 {"java_primitiveArray",
5775 {"Multi-dimensional arrays must be fixed size.",
5776 "Multi-dimensional arrays must be fixed size."}},
5777 {"ndk_primitiveArray",
5778 {"Multi-dimensional arrays must be fixed size.",
5779 "Multi-dimensional arrays must be fixed size."}},
5780 {"rust_primitiveArray",
5781 {"Multi-dimensional arrays must be fixed size.",
5782 "Multi-dimensional arrays must be fixed size."}},
5783 {"cpp_primitiveFixedArray",
5784 {"Multi-dimensional arrays must be fixed size.",
5785 "Multi-dimensional arrays must be fixed size."}},
5786 {"java_primitiveFixedArray",
5787 {"Multi-dimensional arrays must be fixed size.",
5788 "Multi-dimensional arrays must be fixed size."}},
5789 {"ndk_primitiveFixedArray",
5790 {"Multi-dimensional arrays must be fixed size.",
5791 "Multi-dimensional arrays must be fixed size."}},
5792 {"rust_primitiveFixedArray",
5793 {"Multi-dimensional arrays must be fixed size.",
5794 "Multi-dimensional arrays must be fixed size."}},
5795 {"cpp_String", {"", ""}},
5796 {"java_String", {"", ""}},
5797 {"ndk_String", {"", ""}},
5798 {"rust_String", {"", ""}},
5799 {"cpp_StringArray",
5800 {"Multi-dimensional arrays must be fixed size.",
5801 "Multi-dimensional arrays must be fixed size."}},
5802 {"java_StringArray",
5803 {"Multi-dimensional arrays must be fixed size.",
5804 "Multi-dimensional arrays must be fixed size."}},
5805 {"ndk_StringArray",
5806 {"Multi-dimensional arrays must be fixed size.",
5807 "Multi-dimensional arrays must be fixed size."}},
5808 {"rust_StringArray",
5809 {"Multi-dimensional arrays must be fixed size.",
5810 "Multi-dimensional arrays must be fixed size."}},
5811 {"cpp_IBinder", {"", ""}},
5812 {"java_IBinder", {"", ""}},
5813 {"ndk_IBinder", {"", ""}},
5814 {"rust_IBinder", {"", ""}},
5815 {"cpp_ParcelFileDescriptor", {"", ""}},
5816 {"java_ParcelFileDescriptor", {"", ""}},
5817 {"ndk_ParcelFileDescriptor", {"", ""}},
5818 {"rust_ParcelFileDescriptor", {"", ""}},
5819 {"cpp_interface", {"", ""}},
5820 {"java_interface", {"", ""}},
5821 {"ndk_interface", {"", ""}},
5822 {"rust_interface", {"", ""}},
5823 {"cpp_parcelable", {"", ""}},
5824 {"java_parcelable", {"", ""}},
5825 {"ndk_parcelable", {"", ""}},
5826 {"rust_parcelable", {"", ""}},
5827 {"cpp_enum", {"", ""}},
5828 {"java_enum", {"", ""}},
5829 {"ndk_enum", {"", ""}},
5830 {"rust_enum", {"", ""}},
5831 {"cpp_union", {"", ""}},
5832 {"java_union", {"", ""}},
5833 {"ndk_union", {"", ""}},
5834 {"rust_union", {"", ""}},
5835 };
5836
5837 const std::map<std::string, ExpectedResult> kFieldSupportExpectations = {
5838 {"cpp_primitive", {"", "cannot get nullable annotation"}},
5839 {"java_primitive", {"", "cannot get nullable annotation"}},
5840 {"ndk_primitive", {"", "cannot get nullable annotation"}},
5841 {"rust_primitive", {"", "cannot get nullable annotation"}},
5842 {"cpp_primitiveArray", {"", ""}},
5843 {"java_primitiveArray", {"", ""}},
5844 {"ndk_primitiveArray", {"", ""}},
5845 {"rust_primitiveArray", {"", ""}},
5846 {"cpp_primitiveFixedArray", {"", ""}},
5847 {"java_primitiveFixedArray", {"", ""}},
5848 {"ndk_primitiveFixedArray", {"", ""}},
5849 {"rust_primitiveFixedArray", {"", ""}},
5850 {"cpp_String", {"", ""}},
5851 {"java_String", {"", ""}},
5852 {"ndk_String", {"", ""}},
5853 {"rust_String", {"", ""}},
5854 {"cpp_StringArray", {"", ""}},
5855 {"java_StringArray", {"", ""}},
5856 {"ndk_StringArray", {"", ""}},
5857 {"rust_StringArray", {"", ""}},
5858 {"cpp_IBinder", {"", ""}},
5859 {"java_IBinder", {"", ""}},
5860 {"ndk_IBinder", {"", ""}},
5861 {"rust_IBinder", {"", ""}},
5862 {"cpp_ParcelFileDescriptor", {"", ""}},
5863 {"java_ParcelFileDescriptor", {"", ""}},
5864 {"ndk_ParcelFileDescriptor", {"", ""}},
5865 {"rust_ParcelFileDescriptor", {"", ""}},
5866 {"cpp_interface", {"", ""}},
5867 {"java_interface", {"", ""}},
5868 {"ndk_interface", {"", ""}},
5869 {"rust_interface", {"", ""}},
5870 {"cpp_parcelable", {"", ""}},
5871 {"java_parcelable", {"", ""}},
5872 {"ndk_parcelable", {"", ""}},
5873 {"rust_parcelable", {"", ""}},
5874 {"cpp_enum", {"", "cannot get nullable annotation"}},
5875 {"java_enum", {"", "cannot get nullable annotation"}},
5876 {"ndk_enum", {"", "cannot get nullable annotation"}},
5877 {"rust_enum", {"", "cannot get nullable annotation"}},
5878 {"cpp_union", {"", ""}},
5879 {"java_union", {"", ""}},
5880 {"ndk_union", {"", ""}},
5881 {"rust_union", {"", ""}},
5882 };
5883
5884 class AidlTypeParamTest
5885 : public testing::TestWithParam<std::tuple<Options::Language, TypeParam, bool>> {
5886 public:
Run(const std::string & generic_type_decl,const std::map<std::string,ExpectedResult> & expectations)5887 void Run(const std::string& generic_type_decl,
5888 const std::map<std::string, ExpectedResult>& expectations) {
5889 const auto& param = GetParam();
5890 const auto& lang = to_string(std::get<0>(param));
5891 const auto& kind = std::get<1>(param).kind;
5892 const bool nullable = std::get<2>(param);
5893
5894 FakeIoDelegate io;
5895 io.SetFileContents("a/IBar.aidl", "package a; interface IBar { }");
5896 io.SetFileContents("a/Enum.aidl", "package a; enum Enum { A }");
5897 io.SetFileContents("a/Union.aidl", "package a; union Union { int a; }");
5898 io.SetFileContents("a/Foo.aidl", "package a; parcelable Foo { int a; }");
5899 std::string decl =
5900 std::vformat(generic_type_decl, std::make_format_args(std::get<1>(param).literal));
5901 if (nullable) {
5902 decl = "@nullable " + decl;
5903 }
5904 io.SetFileContents("a/Target.aidl", "package a; parcelable Target { " + decl + " f; }");
5905
5906 const auto options = Options::From(std::format(
5907 "aidl -I . --min_sdk_version current --lang={} a/Target.aidl -o out -h out", lang));
5908 CaptureStderr();
5909 compile_aidl(options, io);
5910 auto it = expectations.find(lang + "_" + kind);
5911 ASSERT_TRUE(it != expectations.end()) << "missing expectation for " << lang << "_" << kind;
5912 const string err = GetCapturedStderr();
5913 const string expected_error =
5914 nullable ? it->second.expected_error_for_nullable : it->second.expected_error;
5915 if (expected_error.empty()) {
5916 EXPECT_EQ("", err);
5917 } else {
5918 EXPECT_THAT(err, testing::HasSubstr(expected_error));
5919 }
5920 }
5921 };
5922
5923 INSTANTIATE_TEST_SUITE_P(
5924 AidlTestSuite, AidlTypeParamTest,
5925 testing::Combine(testing::Values(Options::Language::CPP, Options::Language::JAVA,
5926 Options::Language::NDK, Options::Language::RUST),
5927 testing::ValuesIn(kTypeParams), testing::Values(true, false)),
__anon078f757c0702(const testing::TestParamInfo<std::tuple<Options::Language, TypeParam, bool>>& info) 5928 [](const testing::TestParamInfo<std::tuple<Options::Language, TypeParam, bool>>& info) {
5929 string name = to_string(std::get<0>(info.param)) + "_" + std::get<1>(info.param).kind;
5930 if (std::get<2>(info.param)) {
5931 name += "_nullable";
5932 }
5933 return name;
5934 });
5935
TEST_P(AidlTypeParamTest,ListSupportedTypes)5936 TEST_P(AidlTypeParamTest, ListSupportedTypes) {
5937 Run("List<{}>", kListSupportExpectations);
5938 }
5939
TEST_P(AidlTypeParamTest,ArraySupportedTypes)5940 TEST_P(AidlTypeParamTest, ArraySupportedTypes) {
5941 Run("{}[]", kArraySupportExpectations);
5942 }
5943
TEST_P(AidlTypeParamTest,ParcelableFieldTypes)5944 TEST_P(AidlTypeParamTest, ParcelableFieldTypes) {
5945 Run("{}", kFieldSupportExpectations);
5946 }
5947
5948 } // namespace aidl
5949 } // namespace android
5950