• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <memory>
18 #include <set>
19 #include <string>
20 #include <vector>
21 
22 #include <android-base/stringprintf.h>
23 #include <gtest/gtest.h>
24 
25 #include "aidl.h"
26 #include "aidl_language.h"
27 #include "tests/fake_io_delegate.h"
28 #include "type_cpp.h"
29 #include "type_java.h"
30 #include "type_namespace.h"
31 
32 using android::aidl::test::FakeIoDelegate;
33 using android::base::StringPrintf;
34 using std::set;
35 using std::string;
36 using std::unique_ptr;
37 using std::vector;
38 using android::aidl::internals::parse_preprocessed_file;
39 
40 namespace android {
41 namespace aidl {
42 namespace {
43 
44 const char kExpectedDepFileContents[] =
45 R"(place/for/output/p/IFoo.java : \
46   p/IFoo.aidl
47 
48 p/IFoo.aidl :
49 )";
50 
51 const char kExpectedNinjaDepFileContents[] =
52 R"(place/for/output/p/IFoo.java : \
53   p/IFoo.aidl
54 )";
55 
56 const char kExpectedParcelableDepFileContents[] =
57 R"( : \
58   p/Foo.aidl
59 
60 p/Foo.aidl :
61 )";
62 
63 }  // namespace
64 
65 class AidlTest : public ::testing::Test {
66  protected:
SetUp()67   void SetUp() override {
68     java_types_.Init();
69     cpp_types_.Init();
70   }
71 
Parse(const string & path,const string & contents,TypeNamespace * types,AidlError * error=nullptr)72   unique_ptr<AidlInterface> Parse(const string& path,
73                                   const string& contents,
74                                   TypeNamespace* types,
75                                   AidlError* error = nullptr) {
76     io_delegate_.SetFileContents(path, contents);
77     unique_ptr<AidlInterface> ret;
78     std::vector<std::unique_ptr<AidlImport>> imports;
79     AidlError actual_error = ::android::aidl::internals::load_and_validate_aidl(
80         preprocessed_files_,
81         import_paths_,
82         path,
83         false, /* generate_traces */
84         io_delegate_,
85         types,
86         &ret,
87         &imports);
88     if (error != nullptr) {
89       *error = actual_error;
90     }
91     return ret;
92   }
93 
94   FakeIoDelegate io_delegate_;
95   vector<string> preprocessed_files_;
96   vector<string> import_paths_;
97   java::JavaTypeNamespace java_types_;
98   cpp::TypeNamespace cpp_types_;
99 };
100 
TEST_F(AidlTest,JavaAcceptsMissingPackage)101 TEST_F(AidlTest, JavaAcceptsMissingPackage) {
102   EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { }", &java_types_));
103 }
104 
TEST_F(AidlTest,RejectsArraysOfBinders)105 TEST_F(AidlTest, RejectsArraysOfBinders) {
106   import_paths_.push_back("");
107   io_delegate_.SetFileContents("bar/IBar.aidl",
108                                "package bar; interface IBar {}");
109   string path = "foo/IFoo.aidl";
110   string contents = "package foo;\n"
111                     "import bar.IBar;\n"
112                     "interface IFoo { void f(in IBar[] input); }";
113   EXPECT_EQ(nullptr, Parse(path, contents, &java_types_));
114   EXPECT_EQ(nullptr, Parse(path, contents, &cpp_types_));
115 }
116 
TEST_F(AidlTest,CppRejectsMissingPackage)117 TEST_F(AidlTest, CppRejectsMissingPackage) {
118   EXPECT_EQ(nullptr, Parse("IFoo.aidl", "interface IFoo { }", &cpp_types_));
119   EXPECT_NE(nullptr,
120             Parse("a/IFoo.aidl", "package a; interface IFoo { }", &cpp_types_));
121 }
122 
TEST_F(AidlTest,RejectsOnewayOutParameters)123 TEST_F(AidlTest, RejectsOnewayOutParameters) {
124   string oneway_interface =
125       "package a; oneway interface IFoo { void f(out int bar); }";
126   string oneway_method =
127       "package a; interface IBar { oneway void f(out int bar); }";
128   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_interface, &cpp_types_));
129   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_interface, &java_types_));
130   EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, &cpp_types_));
131   EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, &java_types_));
132 }
133 
TEST_F(AidlTest,RejectsOnewayNonVoidReturn)134 TEST_F(AidlTest, RejectsOnewayNonVoidReturn) {
135   string oneway_method = "package a; interface IFoo { oneway int f(); }";
136   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_));
137   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_));
138 }
139 
TEST_F(AidlTest,RejectsNullablePrimitive)140 TEST_F(AidlTest, RejectsNullablePrimitive) {
141   string oneway_method = "package a; interface IFoo { @nullable int f(); }";
142   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_));
143   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_));
144 }
145 
TEST_F(AidlTest,ParsesNullableAnnotation)146 TEST_F(AidlTest, ParsesNullableAnnotation) {
147   for (auto is_nullable: {true, false}) {
148     auto parse_result = Parse(
149         "a/IFoo.aidl",
150         StringPrintf( "package a; interface IFoo {%s String f(); }",
151                      (is_nullable) ? "@nullable" : ""),
152         &cpp_types_);
153     ASSERT_NE(nullptr, parse_result);
154     ASSERT_FALSE(parse_result->GetMethods().empty());
155     EXPECT_EQ(parse_result->GetMethods()[0]->GetType().IsNullable(),
156               is_nullable);
157   }
158 }
159 
TEST_F(AidlTest,ParsesUtf8Annotations)160 TEST_F(AidlTest, ParsesUtf8Annotations) {
161   for (auto is_utf8: {true, false}) {
162     auto parse_result = Parse(
163         "a/IFoo.aidl",
164         StringPrintf( "package a; interface IFoo {%s String f(); }",
165                      (is_utf8) ? "@utf8InCpp" : ""),
166         &cpp_types_);
167     ASSERT_NE(nullptr, parse_result);
168     ASSERT_FALSE(parse_result->GetMethods().empty());
169     EXPECT_EQ(parse_result->GetMethods()[0]->GetType().IsUtf8InCpp(),
170               is_utf8);
171   }
172 }
173 
TEST_F(AidlTest,AcceptsOneway)174 TEST_F(AidlTest, AcceptsOneway) {
175   string oneway_method = "package a; interface IFoo { oneway void f(int a); }";
176   string oneway_interface =
177       "package a; oneway interface IBar { void f(int a); }";
178   EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_));
179   EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_));
180   EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, &cpp_types_));
181   EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, &java_types_));
182 }
183 
TEST_F(AidlTest,ParsesPreprocessedFile)184 TEST_F(AidlTest, ParsesPreprocessedFile) {
185   string simple_content = "parcelable a.Foo;\ninterface b.IBar;";
186   io_delegate_.SetFileContents("path", simple_content);
187   EXPECT_FALSE(java_types_.HasTypeByCanonicalName("a.Foo"));
188   EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &java_types_));
189   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("a.Foo"));
190   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("b.IBar"));
191 }
192 
TEST_F(AidlTest,ParsesPreprocessedFileWithWhitespace)193 TEST_F(AidlTest, ParsesPreprocessedFileWithWhitespace) {
194   string simple_content = "parcelable    a.Foo;\n  interface b.IBar  ;\t";
195   io_delegate_.SetFileContents("path", simple_content);
196   EXPECT_FALSE(java_types_.HasTypeByCanonicalName("a.Foo"));
197   EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &java_types_));
198   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("a.Foo"));
199   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("b.IBar"));
200 }
201 
TEST_F(AidlTest,PreferImportToPreprocessed)202 TEST_F(AidlTest, PreferImportToPreprocessed) {
203   io_delegate_.SetFileContents("preprocessed", "interface another.IBar;");
204   io_delegate_.SetFileContents("one/IBar.aidl", "package one; "
205                                                 "interface IBar {}");
206   preprocessed_files_.push_back("preprocessed");
207   import_paths_.push_back("");
208   auto parse_result = Parse(
209       "p/IFoo.aidl", "package p; import one.IBar; interface IFoo {}",
210       &java_types_);
211   EXPECT_NE(nullptr, parse_result);
212   // We expect to know about both kinds of IBar
213   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("one.IBar"));
214   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("another.IBar"));
215   // But if we request just "IBar" we should get our imported one.
216   AidlType ambiguous_type("IBar", 0, "", false /* not an array */);
217   const java::Type* type = java_types_.Find(ambiguous_type);
218   ASSERT_TRUE(type);
219   EXPECT_EQ("one.IBar", type->CanonicalName());
220 }
221 
TEST_F(AidlTest,WritePreprocessedFile)222 TEST_F(AidlTest, WritePreprocessedFile) {
223   io_delegate_.SetFileContents("p/Outer.aidl",
224                                "package p; parcelable Outer.Inner;");
225   io_delegate_.SetFileContents("one/IBar.aidl", "package one; import p.Outer;"
226                                                 "interface IBar {}");
227 
228   JavaOptions options;
229   options.output_file_name_ = "preprocessed";
230   options.files_to_preprocess_.resize(2);
231   options.files_to_preprocess_[0] = "p/Outer.aidl";
232   options.files_to_preprocess_[1] = "one/IBar.aidl";
233   EXPECT_TRUE(::android::aidl::preprocess_aidl(options, io_delegate_));
234 
235   string output;
236   EXPECT_TRUE(io_delegate_.GetWrittenContents("preprocessed", &output));
237   EXPECT_EQ("parcelable p.Outer.Inner;\ninterface one.IBar;\n", output);
238 }
239 
TEST_F(AidlTest,RequireOuterClass)240 TEST_F(AidlTest, RequireOuterClass) {
241   io_delegate_.SetFileContents("p/Outer.aidl",
242                                "package p; parcelable Outer.Inner;");
243   import_paths_.push_back("");
244   auto parse_result = Parse(
245       "p/IFoo.aidl",
246       "package p; import p.Outer; interface IFoo { void f(in Inner c); }",
247       &java_types_);
248   EXPECT_EQ(nullptr, parse_result);
249 }
250 
TEST_F(AidlTest,ParseCompoundParcelableFromPreprocess)251 TEST_F(AidlTest, ParseCompoundParcelableFromPreprocess) {
252   io_delegate_.SetFileContents("preprocessed",
253                                "parcelable p.Outer.Inner;");
254   preprocessed_files_.push_back("preprocessed");
255   auto parse_result = Parse(
256       "p/IFoo.aidl",
257       "package p; interface IFoo { void f(in Inner c); }",
258       &java_types_);
259   // TODO(wiley): This should actually return nullptr because we require
260   //              the outer class name.  However, for legacy reasons,
261   //              this behavior must be maintained.  b/17415692
262   EXPECT_NE(nullptr, parse_result);
263 }
264 
TEST_F(AidlTest,FailOnParcelable)265 TEST_F(AidlTest, FailOnParcelable) {
266   JavaOptions options;
267   options.input_file_name_ = "p/IFoo.aidl";
268   io_delegate_.SetFileContents(options.input_file_name_,
269                                "package p; parcelable IFoo;");
270   // By default, we shouldn't fail on parcelable.
271   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
272   options.fail_on_parcelable_ = true;
273   EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
274 }
275 
TEST_F(AidlTest,FailOnDuplicateConstantNames)276 TEST_F(AidlTest, FailOnDuplicateConstantNames) {
277   AidlError reported_error;
278   EXPECT_EQ(nullptr,
279             Parse("p/IFoo.aidl",
280                    R"(package p;
281                       interface IFoo {
282                         const String DUPLICATED = "d";
283                         const int DUPLICATED = 1;
284                       }
285                    )",
286                    &cpp_types_,
287                    &reported_error));
288   EXPECT_EQ(AidlError::BAD_CONSTANTS, reported_error);
289 }
290 
TEST_F(AidlTest,FailOnMalformedConstHexValue)291 TEST_F(AidlTest, FailOnMalformedConstHexValue) {
292   AidlError reported_error;
293   EXPECT_EQ(nullptr,
294             Parse("p/IFoo.aidl",
295                    R"(package p;
296                       interface IFoo {
297                         const int BAD_HEX_VALUE = 0xffffffffffffffffff;
298                       }
299                    )",
300                    &cpp_types_,
301                    &reported_error));
302   EXPECT_EQ(AidlError::BAD_CONSTANTS, reported_error);
303 }
304 
TEST_F(AidlTest,ParsePositiveConstHexValue)305 TEST_F(AidlTest, ParsePositiveConstHexValue) {
306   AidlError reported_error;
307   auto cpp_parse_result =
308     Parse("p/IFoo.aidl",
309            R"(package p;
310               interface IFoo {
311                 const int POSITIVE_HEX_VALUE = 0xf5;
312               }
313            )",
314            &cpp_types_,
315            &reported_error);
316   EXPECT_NE(nullptr, cpp_parse_result);
317   const auto& cpp_int_constants = cpp_parse_result->GetIntConstants();
318   EXPECT_EQ((size_t)1, cpp_int_constants.size());
319   EXPECT_EQ("POSITIVE_HEX_VALUE", cpp_int_constants[0]->GetName());
320   EXPECT_EQ(245, cpp_int_constants[0]->GetValue());
321 }
322 
TEST_F(AidlTest,ParseNegativeConstHexValue)323 TEST_F(AidlTest, ParseNegativeConstHexValue) {
324   AidlError reported_error;
325   auto cpp_parse_result =
326     Parse("p/IFoo.aidl",
327            R"(package p;
328               interface IFoo {
329                 const int NEGATIVE_HEX_VALUE = 0xffffffff;
330               }
331            )",
332            &cpp_types_,
333            &reported_error);
334   EXPECT_NE(nullptr, cpp_parse_result);
335   const auto& cpp_int_constants = cpp_parse_result->GetIntConstants();
336   EXPECT_EQ((size_t)1, cpp_int_constants.size());
337   EXPECT_EQ("NEGATIVE_HEX_VALUE", cpp_int_constants[0]->GetName());
338   EXPECT_EQ(-1, cpp_int_constants[0]->GetValue());
339 }
340 
TEST_F(AidlTest,UnderstandsNestedParcelables)341 TEST_F(AidlTest, UnderstandsNestedParcelables) {
342   io_delegate_.SetFileContents(
343       "p/Outer.aidl",
344       "package p; parcelable Outer.Inner cpp_header \"baz/header\";");
345   import_paths_.push_back("");
346   const string input_path = "p/IFoo.aidl";
347   const string input = "package p; import p.Outer; interface IFoo"
348                        " { Outer.Inner get(); }";
349 
350   auto cpp_parse_result = Parse(input_path, input, &cpp_types_);
351   EXPECT_NE(nullptr, cpp_parse_result);
352   auto cpp_type = cpp_types_.FindTypeByCanonicalName("p.Outer.Inner");
353   ASSERT_NE(nullptr, cpp_type);
354   // C++ uses "::" instead of "." to refer to a inner class.
355   EXPECT_EQ("::p::Outer::Inner", cpp_type->CppType());
356 }
357 
TEST_F(AidlTest,UnderstandsNativeParcelables)358 TEST_F(AidlTest, UnderstandsNativeParcelables) {
359   io_delegate_.SetFileContents(
360       "p/Bar.aidl",
361       "package p; parcelable Bar cpp_header \"baz/header\";");
362   import_paths_.push_back("");
363   const string input_path = "p/IFoo.aidl";
364   const string input = "package p; import p.Bar; interface IFoo { }";
365 
366   // C++ understands C++ specific stuff
367   auto cpp_parse_result = Parse(input_path, input, &cpp_types_);
368   EXPECT_NE(nullptr, cpp_parse_result);
369   auto cpp_type = cpp_types_.FindTypeByCanonicalName("p.Bar");
370   ASSERT_NE(nullptr, cpp_type);
371   EXPECT_EQ("::p::Bar", cpp_type->CppType());
372   set<string> headers;
373   cpp_type->GetHeaders(&headers);
374   EXPECT_EQ(1u, headers.size());
375   EXPECT_EQ(1u, headers.count("baz/header"));
376 
377   // Java ignores C++ specific stuff
378   auto java_parse_result = Parse(input_path, input, &java_types_);
379   EXPECT_NE(nullptr, java_parse_result);
380   auto java_type = java_types_.FindTypeByCanonicalName("p.Bar");
381   ASSERT_NE(nullptr, java_type);
382   EXPECT_EQ("p.Bar", java_type->InstantiableName());
383 }
384 
TEST_F(AidlTest,WritesCorrectDependencyFile)385 TEST_F(AidlTest, WritesCorrectDependencyFile) {
386   // While the in tree build system always gives us an output file name,
387   // other android tools take advantage of our ability to infer the intended
388   // file name.  This test makes sure we handle this correctly.
389   JavaOptions options;
390   options.input_file_name_ = "p/IFoo.aidl";
391   options.output_base_folder_ = "place/for/output";
392   options.dep_file_name_ = "dep/file/path";
393   io_delegate_.SetFileContents(options.input_file_name_,
394                                "package p; interface IFoo {}");
395   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
396   string actual_dep_file_contents;
397   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.dep_file_name_,
398                                               &actual_dep_file_contents));
399   EXPECT_EQ(actual_dep_file_contents, kExpectedDepFileContents);
400 }
401 
TEST_F(AidlTest,WritesCorrectDependencyFileNinja)402 TEST_F(AidlTest, WritesCorrectDependencyFileNinja) {
403   // While the in tree build system always gives us an output file name,
404   // other android tools take advantage of our ability to infer the intended
405   // file name.  This test makes sure we handle this correctly.
406   JavaOptions options;
407   options.input_file_name_ = "p/IFoo.aidl";
408   options.output_base_folder_ = "place/for/output";
409   options.dep_file_name_ = "dep/file/path";
410   options.dep_file_ninja_ = true;
411   io_delegate_.SetFileContents(options.input_file_name_,
412                                "package p; interface IFoo {}");
413   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
414   string actual_dep_file_contents;
415   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.dep_file_name_,
416                                               &actual_dep_file_contents));
417   EXPECT_EQ(actual_dep_file_contents, kExpectedNinjaDepFileContents);
418 }
419 
TEST_F(AidlTest,WritesTrivialDependencyFileForParcelable)420 TEST_F(AidlTest, WritesTrivialDependencyFileForParcelable) {
421   // The SDK uses aidl to decide whether a .aidl file is a parcelable.  It does
422   // this by calling aidl with every .aidl file it finds, then parsing the
423   // generated dependency files.  Those that reference .java output files are
424   // for interfaces and those that do not are parcelables.  However, for both
425   // parcelables and interfaces, we *must* generate a non-empty dependency file.
426   JavaOptions options;
427   options.input_file_name_ = "p/Foo.aidl";
428   options.output_base_folder_ = "place/for/output";
429   options.dep_file_name_ = "dep/file/path";
430   io_delegate_.SetFileContents(options.input_file_name_,
431                                "package p; parcelable Foo;");
432   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
433   string actual_dep_file_contents;
434   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.dep_file_name_,
435                                               &actual_dep_file_contents));
436   EXPECT_EQ(actual_dep_file_contents, kExpectedParcelableDepFileContents);
437 }
438 
439 }  // namespace aidl
440 }  // namespace android
441