Home | History | Annotate | Download | only in java
      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 "java/ManifestClassGenerator.h"
     18 
     19 #include "io/StringStream.h"
     20 #include "test/Test.h"
     21 
     22 using ::aapt::io::StringOutputStream;
     23 using ::testing::HasSubstr;
     24 using ::testing::Not;
     25 
     26 namespace aapt {
     27 
     28 static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res,
     29                                                        std::string* out_str);
     30 
     31 TEST(ManifestClassGeneratorTest, NameIsProperlyGeneratedFromSymbol) {
     32   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
     33   std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
     34       <manifest xmlns:android="http://schemas.android.com/apk/res/android">
     35         <permission android:name="android.permission.ACCESS_INTERNET" />
     36         <permission android:name="android.DO_DANGEROUS_THINGS" />
     37         <permission android:name="com.test.sample.permission.HUH" />
     38         <permission-group android:name="foo.bar.PERMISSION" />
     39       </manifest>)");
     40 
     41   std::string actual;
     42   ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual));
     43 
     44   ASSERT_THAT(actual, HasSubstr("public static final class permission {"));
     45   ASSERT_THAT(actual, HasSubstr("public static final class permission_group {"));
     46 
     47   const size_t permission_start_pos = actual.find("public static final class permission {");
     48   const size_t permission_group_start_pos =
     49       actual.find("public static final class permission_group {");
     50 
     51   //
     52   // Make sure these permissions are in the permission class.
     53   //
     54   const std::string permission_class =
     55       actual.substr(permission_start_pos, permission_group_start_pos - permission_start_pos);
     56 
     57   EXPECT_THAT(
     58       permission_class,
     59       HasSubstr(
     60           "public static final String ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";"));
     61   EXPECT_THAT(
     62       permission_class,
     63       HasSubstr("public static final String DO_DANGEROUS_THINGS=\"android.DO_DANGEROUS_THINGS\";"));
     64   EXPECT_THAT(permission_class,
     65               HasSubstr("public static final String HUH=\"com.test.sample.permission.HUH\";"));
     66 
     67   //
     68   // Make sure these permissions are in the permission_group class
     69   //
     70   const std::string permission_group_class = actual.substr(permission_group_start_pos);
     71 
     72   EXPECT_THAT(permission_group_class,
     73               HasSubstr("public static final String PERMISSION=\"foo.bar.PERMISSION\";"));
     74 }
     75 
     76 TEST(ManifestClassGeneratorTest, CommentsAndAnnotationsArePresent) {
     77   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
     78   std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
     79       <manifest xmlns:android="http://schemas.android.com/apk/res/android">
     80         <!-- Required to access the internet.
     81              Added in API 1. -->
     82         <permission android:name="android.permission.ACCESS_INTERNET" />
     83         <!-- @deprecated This permission is for playing outside. -->
     84         <permission android:name="android.permission.PLAY_OUTSIDE" />
     85         <!-- This is a private permission for system only!
     86              @hide
     87              @SystemApi -->
     88         <permission android:name="android.permission.SECRET" />
     89         <!-- @TestApi This is a test only permission. -->
     90         <permission android:name="android.permission.TEST_ONLY" />
     91       </manifest>)");
     92 
     93   std::string actual;
     94   ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual));
     95 
     96   const char* expected_access_internet = R"(    /**
     97      * Required to access the internet.
     98      * Added in API 1.
     99      */
    100     public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)";
    101   EXPECT_THAT(actual, HasSubstr(expected_access_internet));
    102 
    103   const char* expected_play_outside = R"(    /**
    104      * @deprecated This permission is for playing outside.
    105      */
    106     @Deprecated
    107     public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)";
    108   EXPECT_THAT(actual, HasSubstr(expected_play_outside));
    109 
    110   const char* expected_secret = R"(    /**
    111      * This is a private permission for system only!
    112      * @hide
    113      */
    114     @android.annotation.SystemApi
    115     public static final String SECRET="android.permission.SECRET";)";
    116   EXPECT_THAT(actual, HasSubstr(expected_secret));
    117 
    118   const char* expected_test = R"(    /**
    119      * This is a test only permission.
    120      */
    121     @android.annotation.TestApi
    122     public static final String TEST_ONLY="android.permission.TEST_ONLY";)";
    123   EXPECT_THAT(actual, HasSubstr(expected_test));
    124 }
    125 
    126 // This is bad but part of public API behaviour so we need to preserve it.
    127 TEST(ManifestClassGeneratorTest, LastSeenPermissionWithSameLeafNameTakesPrecedence) {
    128   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
    129   std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
    130       <manifest xmlns:android="http://schemas.android.com/apk/res/android">
    131         <permission android:name="android.permission.ACCESS_INTERNET" />
    132         <permission android:name="com.android.sample.ACCESS_INTERNET" />
    133         <permission android:name="com.android.permission.UNRELATED_PERMISSION" />
    134         <permission android:name="com.android.aapt.test.ACCESS_INTERNET" /> -->
    135       </manifest>)");
    136 
    137   std::string actual;
    138   ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual));
    139   EXPECT_THAT(actual, HasSubstr("ACCESS_INTERNET=\"com.android.aapt.test.ACCESS_INTERNET\";"));
    140   EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";")));
    141   EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"com.android.sample.ACCESS_INTERNET\";")));
    142 }
    143 
    144 TEST(ManifestClassGeneratorTest, NormalizePermissionNames) {
    145   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
    146   std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"(
    147         <manifest xmlns:android="http://schemas.android.com/apk/res/android">
    148           <permission android:name="android.permission.access-internet" />
    149         </manifest>)");
    150 
    151   std::string actual;
    152   ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), &actual));
    153   EXPECT_THAT(actual, HasSubstr("access_internet=\"android.permission.access-internet\";"));
    154 }
    155 
    156 static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res,
    157                                                        std::string* out_str) {
    158   std::unique_ptr<ClassDefinition> manifest_class =
    159       GenerateManifestClass(context->GetDiagnostics(), res);
    160   if (!manifest_class) {
    161     return ::testing::AssertionFailure() << "manifest_class == nullptr";
    162   }
    163 
    164   StringOutputStream out(out_str);
    165   manifest_class->WriteJavaFile(manifest_class.get(), "android", true, &out);
    166   out.Flush();
    167   return ::testing::AssertionSuccess();
    168 }
    169 
    170 }  // namespace aapt
    171