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