diff options
Diffstat (limited to 'tools/aapt2/cmd/Link_test.cpp')
-rw-r--r-- | tools/aapt2/cmd/Link_test.cpp | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/tools/aapt2/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp index 27cbe88fde38..dfdac6b9d93e 100644 --- a/tools/aapt2/cmd/Link_test.cpp +++ b/tools/aapt2/cmd/Link_test.cpp @@ -25,6 +25,7 @@ using testing::Eq; using testing::HasSubstr; using testing::Ne; +using testing::NotNull; namespace aapt { @@ -400,4 +401,127 @@ TEST_F(LinkTest, SharedLibraryAttributeRJava) { EXPECT_THAT(client_r_contents, HasSubstr(" com.example.lib.R.attr.foo, 0x7f010000")); } +TEST_F(LinkTest, StagedAndroidApi) { + StdErrDiagnostics diag; + const std::string android_values = + R"(<resources> + <public type="attr" name="finalized_res" id="0x01010001"/> + + <!-- S staged attributes (support staged resources in the same type id) --> + <staging-public-group type="attr" first-id="0x01010050"> + <public name="staged_s_res" /> + </staging-public-group> + + <!-- SV2 staged attributes (support staged resources in a separate type id) --> + <staging-public-group type="attr" first-id="0x01ff0049"> + <public name="staged_s2_res" /> + </staging-public-group> + + <!-- T staged attributes (support staged resources in multiple separate type ids) --> + <staging-public-group type="attr" first-id="0x01fe0063"> + <public name="staged_t_res" /> + </staging-public-group> + + <staging-public-group type="string" first-id="0x01fd0072"> + <public name="staged_t_string" /> + </staging-public-group> + + <attr name="finalized_res" /> + <attr name="staged_s_res" /> + <attr name="staged_s2_res" /> + <attr name="staged_t_res" /> + <string name="staged_t_string">Hello</string> + </resources>)"; + + const std::string app_values = + R"(<resources xmlns:android="http://schemas.android.com/apk/res/android"> + <attr name="bar" /> + <declare-styleable name="ClientStyleable"> + <attr name="android:finalized_res" /> + <attr name="android:staged_s_res" /> + <attr name="bar" /> + </declare-styleable> + </resources>)"; + + const std::string android_res = GetTestPath("android-res"); + ASSERT_TRUE( + CompileFile(GetTestPath("res/values/values.xml"), android_values, android_res, &diag)); + + const std::string android_apk = GetTestPath("android.apk"); + const std::string android_java = GetTestPath("android_java"); + // clang-format off + auto android_manifest = ManifestBuilder(this) + .SetPackageName("android") + .Build(); + + auto android_link_args = LinkCommandBuilder(this) + .SetManifestFile(android_manifest) + .AddParameter("--private-symbols", "com.android.internal") + .AddParameter("--java", android_java) + .AddCompiledResDir(android_res, &diag) + .Build(android_apk); + // clang-format on + ASSERT_TRUE(Link(android_link_args, &diag)); + + const std::string android_r_java = android_java + "/android/R.java"; + std::string android_r_contents; + ASSERT_TRUE(android::base::ReadFileToString(android_r_java, &android_r_contents)); + EXPECT_THAT(android_r_contents, HasSubstr(" public static final int finalized_res=0x01010001;")); + EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_s_res=0x01010050;")); + EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_s2_res=0x01ff0049;")); + EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_t_res=0x01fe0063;")); + EXPECT_THAT(android_r_contents, HasSubstr(" public static int staged_t_string=0x01fd0072;")); + + // Build an app that uses the framework attribute in a declare-styleable + const std::string client_res = GetTestPath("app-res"); + ASSERT_TRUE(CompileFile(GetTestPath("res/values/values.xml"), app_values, client_res, &diag)); + + const std::string app_apk = GetTestPath("app.apk"); + const std::string app_java = GetTestPath("app_java"); + // clang-format off + auto app_manifest = ManifestBuilder(this) + .SetPackageName("com.example.app") + .Build(); + + auto app_link_args = LinkCommandBuilder(this) + .SetManifestFile(app_manifest) + .AddParameter("--java", app_java) + .AddParameter("-I", android_apk) + .AddCompiledResDir(client_res, &diag) + .Build(app_apk); + // clang-format on + ASSERT_TRUE(Link(app_link_args, &diag)); + + const std::string client_r_java = app_java + "/com/example/app/R.java"; + std::string client_r_contents; + ASSERT_TRUE(android::base::ReadFileToString(client_r_java, &client_r_contents)); + EXPECT_THAT(client_r_contents, HasSubstr(" 0x01010001, android.R.attr.staged_s_res, 0x7f010000")); + + // Test that the resource ids of staged and non-staged resource can be retrieved + android::AssetManager2 am; + auto android_asset = android::ApkAssets::Load(android_apk); + ASSERT_THAT(android_asset, NotNull()); + ASSERT_TRUE(am.SetApkAssets({android_asset.get()})); + + auto result = am.GetResourceId("android:attr/finalized_res"); + ASSERT_TRUE(result.has_value()); + EXPECT_THAT(*result, Eq(0x01010001)); + + result = am.GetResourceId("android:attr/staged_s_res"); + ASSERT_TRUE(result.has_value()); + EXPECT_THAT(*result, Eq(0x01010050)); + + result = am.GetResourceId("android:attr/staged_s2_res"); + ASSERT_TRUE(result.has_value()); + EXPECT_THAT(*result, Eq(0x01ff0049)); + + result = am.GetResourceId("android:attr/staged_t_res"); + ASSERT_TRUE(result.has_value()); + EXPECT_THAT(*result, Eq(0x01fe0063)); + + result = am.GetResourceId("android:string/staged_t_string"); + ASSERT_TRUE(result.has_value()); + EXPECT_THAT(*result, Eq(0x01fd0072)); +} + } // namespace aapt |