| /* | |
| * Copyright (C) 2015 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include "java/ManifestClassGenerator.h" | |
| #include "io/StringStream.h" | |
| #include "test/Test.h" | |
| using ::aapt::io::StringOutputStream; | |
| using ::testing::HasSubstr; | |
| using ::testing::Not; | |
| namespace aapt { | |
| static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res, | |
| bool strip_api_annotations, | |
| std::string* out_str); | |
| TEST(ManifestClassGeneratorTest, NameIsProperlyGeneratedFromSymbol) { | |
| std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); | |
| std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"( | |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | |
| <permission android:name="android.permission.ACCESS_INTERNET" /> | |
| <permission android:name="android.DO_DANGEROUS_THINGS" /> | |
| <permission android:name="com.test.sample.permission.HUH" /> | |
| <permission-group android:name="foo.bar.PERMISSION" /> | |
| </manifest>)"); | |
| std::string actual; | |
| ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), | |
| false /* strip_api_annotations */, &actual)); | |
| ASSERT_THAT(actual, HasSubstr("public static final class permission {")); | |
| ASSERT_THAT(actual, HasSubstr("public static final class permission_group {")); | |
| const size_t permission_start_pos = actual.find("public static final class permission {"); | |
| const size_t permission_group_start_pos = | |
| actual.find("public static final class permission_group {"); | |
| // | |
| // Make sure these permissions are in the permission class. | |
| // | |
| const std::string permission_class = | |
| actual.substr(permission_start_pos, permission_group_start_pos - permission_start_pos); | |
| EXPECT_THAT( | |
| permission_class, | |
| HasSubstr( | |
| "public static final String ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";")); | |
| EXPECT_THAT( | |
| permission_class, | |
| HasSubstr("public static final String DO_DANGEROUS_THINGS=\"android.DO_DANGEROUS_THINGS\";")); | |
| EXPECT_THAT(permission_class, | |
| HasSubstr("public static final String HUH=\"com.test.sample.permission.HUH\";")); | |
| // | |
| // Make sure these permissions are in the permission_group class | |
| // | |
| const std::string permission_group_class = actual.substr(permission_group_start_pos); | |
| EXPECT_THAT(permission_group_class, | |
| HasSubstr("public static final String PERMISSION=\"foo.bar.PERMISSION\";")); | |
| } | |
| TEST(ManifestClassGeneratorTest, CommentsAndAnnotationsArePresent) { | |
| std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); | |
| std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"( | |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | |
| <!-- Required to access the internet. | |
| Added in API 1. --> | |
| <permission android:name="android.permission.ACCESS_INTERNET" /> | |
| <!-- @deprecated This permission is for playing outside. --> | |
| <permission android:name="android.permission.PLAY_OUTSIDE" /> | |
| <!-- This is a private permission for system only! | |
| @hide | |
| @SystemApi --> | |
| <permission android:name="android.permission.SECRET" /> | |
| <!-- @TestApi This is a test only permission. --> | |
| <permission android:name="android.permission.TEST_ONLY" /> | |
| </manifest>)"); | |
| std::string actual; | |
| ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), | |
| false /* strip_api_annotations */, &actual)); | |
| const char* expected_access_internet = R"( /** | |
| * Required to access the internet. | |
| * Added in API 1. | |
| */ | |
| public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)"; | |
| EXPECT_THAT(actual, HasSubstr(expected_access_internet)); | |
| const char* expected_play_outside = R"( /** | |
| * @deprecated This permission is for playing outside. | |
| */ | |
| @Deprecated | |
| public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)"; | |
| EXPECT_THAT(actual, HasSubstr(expected_play_outside)); | |
| const char* expected_secret = R"( /** | |
| * This is a private permission for system only! | |
| * @hide | |
| */ | |
| @android.annotation.SystemApi | |
| public static final String SECRET="android.permission.SECRET";)"; | |
| EXPECT_THAT(actual, HasSubstr(expected_secret)); | |
| const char* expected_test = R"( /** | |
| * This is a test only permission. | |
| */ | |
| @android.annotation.TestApi | |
| public static final String TEST_ONLY="android.permission.TEST_ONLY";)"; | |
| EXPECT_THAT(actual, HasSubstr(expected_test)); | |
| } | |
| TEST(ManifestClassGeneratorTest, CommentsAndAnnotationsArePresentButNoApiAnnotations) { | |
| std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); | |
| std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"( | |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | |
| <!-- Required to access the internet. | |
| Added in API 1. --> | |
| <permission android:name="android.permission.ACCESS_INTERNET" /> | |
| <!-- @deprecated This permission is for playing outside. --> | |
| <permission android:name="android.permission.PLAY_OUTSIDE" /> | |
| <!-- This is a private permission for system only! | |
| @hide | |
| @SystemApi --> | |
| <permission android:name="android.permission.SECRET" /> | |
| <!-- @TestApi This is a test only permission. --> | |
| <permission android:name="android.permission.TEST_ONLY" /> | |
| </manifest>)"); | |
| std::string actual; | |
| ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), | |
| true /* strip_api_annotations */, &actual)); | |
| const char* expected_access_internet = R"( /** | |
| * Required to access the internet. | |
| * Added in API 1. | |
| */ | |
| public static final String ACCESS_INTERNET="android.permission.ACCESS_INTERNET";)"; | |
| EXPECT_THAT(actual, HasSubstr(expected_access_internet)); | |
| const char* expected_play_outside = R"( /** | |
| * @deprecated This permission is for playing outside. | |
| */ | |
| @Deprecated | |
| public static final String PLAY_OUTSIDE="android.permission.PLAY_OUTSIDE";)"; | |
| EXPECT_THAT(actual, HasSubstr(expected_play_outside)); | |
| const char* expected_secret = R"( /** | |
| * This is a private permission for system only! | |
| * @hide | |
| */ | |
| public static final String SECRET="android.permission.SECRET";)"; | |
| EXPECT_THAT(actual, HasSubstr(expected_secret)); | |
| const char* expected_test = R"( /** | |
| * This is a test only permission. | |
| */ | |
| public static final String TEST_ONLY="android.permission.TEST_ONLY";)"; | |
| EXPECT_THAT(actual, HasSubstr(expected_test)); | |
| } | |
| // This is bad but part of public API behaviour so we need to preserve it. | |
| TEST(ManifestClassGeneratorTest, LastSeenPermissionWithSameLeafNameTakesPrecedence) { | |
| std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); | |
| std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"( | |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | |
| <permission android:name="android.permission.ACCESS_INTERNET" /> | |
| <permission android:name="com.android.sample.ACCESS_INTERNET" /> | |
| <permission android:name="com.android.permission.UNRELATED_PERMISSION" /> | |
| <permission android:name="com.android.aapt.test.ACCESS_INTERNET" /> --> | |
| </manifest>)"); | |
| std::string actual; | |
| ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), | |
| false /* strip_api_annotations */, &actual)); | |
| EXPECT_THAT(actual, HasSubstr("ACCESS_INTERNET=\"com.android.aapt.test.ACCESS_INTERNET\";")); | |
| EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"android.permission.ACCESS_INTERNET\";"))); | |
| EXPECT_THAT(actual, Not(HasSubstr("ACCESS_INTERNET=\"com.android.sample.ACCESS_INTERNET\";"))); | |
| } | |
| TEST(ManifestClassGeneratorTest, NormalizePermissionNames) { | |
| std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); | |
| std::unique_ptr<xml::XmlResource> manifest = test::BuildXmlDom(R"( | |
| <manifest xmlns:android="http://schemas.android.com/apk/res/android"> | |
| <permission android:name="android.permission.access-internet" /> | |
| </manifest>)"); | |
| std::string actual; | |
| ASSERT_TRUE(GetManifestClassText(context.get(), manifest.get(), | |
| false /* strip_api_annotations */, &actual)); | |
| EXPECT_THAT(actual, HasSubstr("access_internet=\"android.permission.access-internet\";")); | |
| } | |
| static ::testing::AssertionResult GetManifestClassText(IAaptContext* context, xml::XmlResource* res, | |
| bool strip_api_annotations, | |
| std::string* out_str) { | |
| std::unique_ptr<ClassDefinition> manifest_class = | |
| GenerateManifestClass(context->GetDiagnostics(), res); | |
| if (!manifest_class) { | |
| return ::testing::AssertionFailure() << "manifest_class == nullptr"; | |
| } | |
| StringOutputStream out(out_str); | |
| manifest_class->WriteJavaFile(manifest_class.get(), "android", true, strip_api_annotations, &out); | |
| out.Flush(); | |
| return ::testing::AssertionSuccess(); | |
| } | |
| } // namespace aapt |