• 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 "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 
TEST(ManifestClassGeneratorTest,NameIsProperlyGeneratedFromSymbol)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