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