Home | History | Annotate | Download | only in aidl
      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 kExpectedParcelableDepFileContents[] =
     52 R"( : \
     53   p/Foo.aidl
     54 
     55 p/Foo.aidl :
     56 )";
     57 
     58 }  // namespace
     59 
     60 class AidlTest : public ::testing::Test {
     61  protected:
     62   void SetUp() override {
     63     java_types_.Init();
     64     cpp_types_.Init();
     65   }
     66 
     67   unique_ptr<AidlInterface> Parse(const string& path,
     68                                   const string& contents,
     69                                   TypeNamespace* types) {
     70     io_delegate_.SetFileContents(path, contents);
     71     unique_ptr<AidlInterface> ret;
     72     std::vector<std::unique_ptr<AidlImport>> imports;
     73     ::android::aidl::internals::load_and_validate_aidl(
     74         preprocessed_files_,
     75         import_paths_,
     76         path,
     77         io_delegate_,
     78         types,
     79         &ret,
     80         &imports);
     81     return ret;
     82   }
     83 
     84   FakeIoDelegate io_delegate_;
     85   vector<string> preprocessed_files_;
     86   vector<string> import_paths_;
     87   java::JavaTypeNamespace java_types_;
     88   cpp::TypeNamespace cpp_types_;
     89 };
     90 
     91 TEST_F(AidlTest, JavaAcceptsMissingPackage) {
     92   EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { }", &java_types_));
     93 }
     94 
     95 TEST_F(AidlTest, RejectsArraysOfBinders) {
     96   import_paths_.push_back("");
     97   io_delegate_.SetFileContents("bar/IBar.aidl",
     98                                "package bar; interface IBar {}");
     99   string path = "foo/IFoo.aidl";
    100   string contents = "package foo;\n"
    101                     "import bar.IBar;\n"
    102                     "interface IFoo { void f(in IBar[] input); }";
    103   EXPECT_EQ(nullptr, Parse(path, contents, &java_types_));
    104   EXPECT_EQ(nullptr, Parse(path, contents, &cpp_types_));
    105 }
    106 
    107 TEST_F(AidlTest, CppRejectsMissingPackage) {
    108   EXPECT_EQ(nullptr, Parse("IFoo.aidl", "interface IFoo { }", &cpp_types_));
    109   EXPECT_NE(nullptr,
    110             Parse("a/IFoo.aidl", "package a; interface IFoo { }", &cpp_types_));
    111 }
    112 
    113 TEST_F(AidlTest, RejectsOnewayOutParameters) {
    114   string oneway_interface =
    115       "package a; oneway interface IFoo { void f(out int bar); }";
    116   string oneway_method =
    117       "package a; interface IBar { oneway void f(out int bar); }";
    118   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_interface, &cpp_types_));
    119   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_interface, &java_types_));
    120   EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, &cpp_types_));
    121   EXPECT_EQ(nullptr, Parse("a/IBar.aidl", oneway_method, &java_types_));
    122 }
    123 
    124 TEST_F(AidlTest, RejectsOnewayNonVoidReturn) {
    125   string oneway_method = "package a; interface IFoo { oneway int f(); }";
    126   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_));
    127   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_));
    128 }
    129 
    130 TEST_F(AidlTest, RejectsNullablePrimitive) {
    131   string oneway_method = "package a; interface IFoo { @nullable int f(); }";
    132   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_));
    133   EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_));
    134 }
    135 
    136 TEST_F(AidlTest, ParsesNullableAnnotation) {
    137   for (auto is_nullable: {true, false}) {
    138     auto parse_result = Parse(
    139         "a/IFoo.aidl",
    140         StringPrintf( "package a; interface IFoo {%s String f(); }",
    141                      (is_nullable) ? "@nullable" : ""),
    142         &cpp_types_);
    143     ASSERT_NE(nullptr, parse_result);
    144     ASSERT_FALSE(parse_result->GetMethods().empty());
    145     EXPECT_EQ(parse_result->GetMethods()[0]->GetType().IsNullable(),
    146               is_nullable);
    147   }
    148 }
    149 
    150 TEST_F(AidlTest, ParsesUtf8Annotations) {
    151   for (auto is_utf8: {true, false}) {
    152     auto parse_result = Parse(
    153         "a/IFoo.aidl",
    154         StringPrintf( "package a; interface IFoo {%s String f(); }",
    155                      (is_utf8) ? "@utf8InCpp" : ""),
    156         &cpp_types_);
    157     ASSERT_NE(nullptr, parse_result);
    158     ASSERT_FALSE(parse_result->GetMethods().empty());
    159     EXPECT_EQ(parse_result->GetMethods()[0]->GetType().IsUtf8InCpp(),
    160               is_utf8);
    161   }
    162 }
    163 
    164 TEST_F(AidlTest, AcceptsOneway) {
    165   string oneway_method = "package a; interface IFoo { oneway void f(int a); }";
    166   string oneway_interface =
    167       "package a; oneway interface IBar { void f(int a); }";
    168   EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, &cpp_types_));
    169   EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, &java_types_));
    170   EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, &cpp_types_));
    171   EXPECT_NE(nullptr, Parse("a/IBar.aidl", oneway_interface, &java_types_));
    172 }
    173 
    174 TEST_F(AidlTest, ParsesPreprocessedFile) {
    175   string simple_content = "parcelable a.Foo;\ninterface b.IBar;";
    176   io_delegate_.SetFileContents("path", simple_content);
    177   EXPECT_FALSE(java_types_.HasTypeByCanonicalName("a.Foo"));
    178   EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &java_types_));
    179   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("a.Foo"));
    180   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("b.IBar"));
    181 }
    182 
    183 TEST_F(AidlTest, ParsesPreprocessedFileWithWhitespace) {
    184   string simple_content = "parcelable    a.Foo;\n  interface b.IBar  ;\t";
    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 
    192 TEST_F(AidlTest, PreferImportToPreprocessed) {
    193   io_delegate_.SetFileContents("preprocessed", "interface another.IBar;");
    194   io_delegate_.SetFileContents("one/IBar.aidl", "package one; "
    195                                                 "interface IBar {}");
    196   preprocessed_files_.push_back("preprocessed");
    197   import_paths_.push_back("");
    198   auto parse_result = Parse(
    199       "p/IFoo.aidl", "package p; import one.IBar; interface IFoo {}",
    200       &java_types_);
    201   EXPECT_NE(nullptr, parse_result);
    202   // We expect to know about both kinds of IBar
    203   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("one.IBar"));
    204   EXPECT_TRUE(java_types_.HasTypeByCanonicalName("another.IBar"));
    205   // But if we request just "IBar" we should get our imported one.
    206   AidlType ambiguous_type("IBar", 0, "", false /* not an array */);
    207   const java::Type* type = java_types_.Find(ambiguous_type);
    208   ASSERT_TRUE(type);
    209   EXPECT_EQ("one.IBar", type->CanonicalName());
    210 }
    211 
    212 TEST_F(AidlTest, WritePreprocessedFile) {
    213   io_delegate_.SetFileContents("p/Outer.aidl",
    214                                "package p; parcelable Outer.Inner;");
    215   io_delegate_.SetFileContents("one/IBar.aidl", "package one; import p.Outer;"
    216                                                 "interface IBar {}");
    217 
    218   JavaOptions options;
    219   options.output_file_name_ = "preprocessed";
    220   options.files_to_preprocess_.resize(2);
    221   options.files_to_preprocess_[0] = "p/Outer.aidl";
    222   options.files_to_preprocess_[1] = "one/IBar.aidl";
    223   EXPECT_TRUE(::android::aidl::preprocess_aidl(options, io_delegate_));
    224 
    225   string output;
    226   EXPECT_TRUE(io_delegate_.GetWrittenContents("preprocessed", &output));
    227   EXPECT_EQ("parcelable p.Outer.Inner;\ninterface one.IBar;\n", output);
    228 }
    229 
    230 TEST_F(AidlTest, RequireOuterClass) {
    231   io_delegate_.SetFileContents("p/Outer.aidl",
    232                                "package p; parcelable Outer.Inner;");
    233   import_paths_.push_back("");
    234   auto parse_result = Parse(
    235       "p/IFoo.aidl",
    236       "package p; import p.Outer; interface IFoo { void f(in Inner c); }",
    237       &java_types_);
    238   EXPECT_EQ(nullptr, parse_result);
    239 }
    240 
    241 TEST_F(AidlTest, ParseCompoundParcelableFromPreprocess) {
    242   io_delegate_.SetFileContents("preprocessed",
    243                                "parcelable p.Outer.Inner;");
    244   preprocessed_files_.push_back("preprocessed");
    245   auto parse_result = Parse(
    246       "p/IFoo.aidl",
    247       "package p; interface IFoo { void f(in Inner c); }",
    248       &java_types_);
    249   // TODO(wiley): This should actually return nullptr because we require
    250   //              the outer class name.  However, for legacy reasons,
    251   //              this behavior must be maintained.  b/17415692
    252   EXPECT_NE(nullptr, parse_result);
    253 }
    254 
    255 TEST_F(AidlTest, FailOnParcelable) {
    256   JavaOptions options;
    257   options.input_file_name_ = "p/IFoo.aidl";
    258   io_delegate_.SetFileContents(options.input_file_name_,
    259                                "package p; parcelable IFoo;");
    260   // By default, we shouldn't fail on parcelable.
    261   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
    262   options.fail_on_parcelable_ = true;
    263   EXPECT_NE(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
    264 }
    265 
    266 TEST_F(AidlTest, UnderstandsNativeParcelables) {
    267   io_delegate_.SetFileContents(
    268       "p/Bar.aidl",
    269       "package p; parcelable Bar cpp_header \"baz/header\";");
    270   import_paths_.push_back("");
    271   const string input_path = "p/IFoo.aidl";
    272   const string input = "package p; import p.Bar; interface IFoo { }";
    273 
    274   // C++ understands C++ specific stuff
    275   auto cpp_parse_result = Parse(input_path, input, &cpp_types_);
    276   EXPECT_NE(nullptr, cpp_parse_result);
    277   auto cpp_type = cpp_types_.FindTypeByCanonicalName("p.Bar");
    278   ASSERT_NE(nullptr, cpp_type);
    279   EXPECT_EQ("::p::Bar", cpp_type->CppType());
    280   set<string> headers;
    281   cpp_type->GetHeaders(&headers);
    282   EXPECT_EQ(1u, headers.size());
    283   EXPECT_EQ(1u, headers.count("baz/header"));
    284 
    285   // Java ignores C++ specific stuff
    286   auto java_parse_result = Parse(input_path, input, &java_types_);
    287   EXPECT_NE(nullptr, java_parse_result);
    288   auto java_type = java_types_.FindTypeByCanonicalName("p.Bar");
    289   ASSERT_NE(nullptr, java_type);
    290   EXPECT_EQ("p.Bar", java_type->InstantiableName());
    291 }
    292 
    293 TEST_F(AidlTest, WritesCorrectDependencyFile) {
    294   // While the in tree build system always gives us an output file name,
    295   // other android tools take advantage of our ability to infer the intended
    296   // file name.  This test makes sure we handle this correctly.
    297   JavaOptions options;
    298   options.input_file_name_ = "p/IFoo.aidl";
    299   options.output_base_folder_ = "place/for/output";
    300   options.dep_file_name_ = "dep/file/path";
    301   io_delegate_.SetFileContents(options.input_file_name_,
    302                                "package p; interface IFoo {}");
    303   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
    304   string actual_dep_file_contents;
    305   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.dep_file_name_,
    306                                               &actual_dep_file_contents));
    307   EXPECT_EQ(actual_dep_file_contents, kExpectedDepFileContents);
    308 }
    309 
    310 TEST_F(AidlTest, WritesTrivialDependencyFileForParcelable) {
    311   // The SDK uses aidl to decide whether a .aidl file is a parcelable.  It does
    312   // this by calling aidl with every .aidl file it finds, then parsing the
    313   // generated dependency files.  Those that reference .java output files are
    314   // for interfaces and those that do not are parcelables.  However, for both
    315   // parcelables and interfaces, we *must* generate a non-empty dependency file.
    316   JavaOptions options;
    317   options.input_file_name_ = "p/Foo.aidl";
    318   options.output_base_folder_ = "place/for/output";
    319   options.dep_file_name_ = "dep/file/path";
    320   io_delegate_.SetFileContents(options.input_file_name_,
    321                                "package p; parcelable Foo;");
    322   EXPECT_EQ(0, ::android::aidl::compile_aidl_to_java(options, io_delegate_));
    323   string actual_dep_file_contents;
    324   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.dep_file_name_,
    325                                               &actual_dep_file_contents));
    326   EXPECT_EQ(actual_dep_file_contents, kExpectedParcelableDepFileContents);
    327 }
    328 
    329 }  // namespace aidl
    330 }  // namespace android
    331