aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorAlex Humesky <ahumesky@google.com>2023-08-22 12:49:29 -0700
committerCopybara-Service <copybara-worker@google.com>2023-08-22 12:49:59 -0700
commitb79878d71688baff303a9a2ee4218d5505ccf4e2 (patch)
tree32105c0dd0e10037435ccb2b05f23b6378f4853e /test
parent7b2db559b0974ac8e27ad3e1ad1d9ac09654e01f (diff)
downloadbazelbuild-rules_android-b79878d71688baff303a9a2ee4218d5505ccf4e2.tar.gz
Add R8 integration to the Starlark Bazel Android rules.
https://github.com/bazelbuild/bazel/issues/18239 https://github.com/bazelbuild/rules_android/issues/31 https://github.com/bazelbuild/rules_android/issues/105 PiperOrigin-RevId: 559196543 Change-Id: Id2a6aea5079a14f305ca48d79d292b166677befa
Diffstat (limited to 'test')
-rw-r--r--test/rules/android_binary_internal/r8_integration/BUILD12
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest.xml22
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest_lib.xml9
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/BUILD56
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/BasicActivity.java49
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/Lib2WithSpecsActivity.java29
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/LibWithSpecsActivity.java29
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/UnusedActivity.java30
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib2_proguard.cfg1
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib_proguard.cfg0
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/proguard.cfg2
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/layout/basic_activity.xml23
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/values/strings.xml8
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/layout/unused_activity.xml12
-rw-r--r--test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/values/strings.xml8
-rwxr-xr-xtest/rules/android_binary_internal/r8_integration/r8_integration_test.py91
16 files changed, 381 insertions, 0 deletions
diff --git a/test/rules/android_binary_internal/r8_integration/BUILD b/test/rules/android_binary_internal/r8_integration/BUILD
new file mode 100644
index 0000000..fcefaeb
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/BUILD
@@ -0,0 +1,12 @@
+load("@rules_python//python:py_test.bzl", "py_test")
+
+py_test(
+ name = "r8_integration_test",
+ srcs = ["r8_integration_test.py"],
+ data = [
+ "//test/rules/android_binary_internal/r8_integration/java/com/basicapp:basic_app_R8_no_shrink",
+ "//test/rules/android_binary_internal/r8_integration/java/com/basicapp:basic_app_R8_shrink",
+ "//test/rules/android_binary_internal/r8_integration/java/com/basicapp:basic_app_no_R8",
+ "@androidsdk-supplemental//:dexdump",
+ ],
+)
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest.xml
new file mode 100644
index 0000000..8d9cc4a
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.basicapp" >
+
+ <uses-sdk
+ android:minSdkVersion="27"
+ android:targetSdkVersion="30" />
+
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:taskAffinity="" >
+ <activity
+ android:name="com.basicapp.BasicActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest_lib.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest_lib.xml
new file mode 100644
index 0000000..f661d59
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/AndroidManifest_lib.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.basicapp" >
+
+ <uses-sdk
+ android:minSdkVersion="27"
+ android:targetSdkVersion="30" />
+
+</manifest>
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BUILD b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BUILD
new file mode 100644
index 0000000..4727887
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BUILD
@@ -0,0 +1,56 @@
+load("//rules:rules.bzl", "android_binary", "android_library")
+
+[
+ android_binary(
+ name = name,
+ srcs = ["BasicActivity.java"],
+ manifest = "AndroidManifest.xml",
+ min_sdk_version = 27,
+ proguard_specs = specs,
+ resource_files = glob(["res/**"]),
+ shrink_resources = shrink,
+ visibility = ["//test/rules/android_binary_internal/r8_integration:__pkg__"],
+ deps = [
+ ":basic_lib",
+ ":lib_with_specs",
+ ],
+ # Work around --java_runtime_version=17 and --java_language_version=11
+ # set in the presubmit tests.
+ javacopts = ["-target", "8", "-source", "8"],
+ )
+ for name, specs, shrink in [
+ (
+ "basic_app_R8_shrink",
+ ["proguard.cfg"],
+ True,
+ ),
+ (
+ "basic_app_R8_no_shrink",
+ ["proguard.cfg"],
+ False,
+ ),
+ ("basic_app_no_R8", [], False),
+ ]
+]
+
+android_library(
+ name = "basic_lib",
+ srcs = ["UnusedActivity.java"],
+ manifest = "AndroidManifest_lib.xml",
+ resource_files = glob(["res_lib/**"]),
+)
+
+android_library(
+ name = "lib_with_specs",
+ srcs = ["LibWithSpecsActivity.java"],
+ manifest = "AndroidManifest_lib.xml",
+ proguard_specs = ["lib_proguard.cfg"],
+ deps = [":lib2_with_specs"],
+)
+
+android_library(
+ name = "lib2_with_specs",
+ srcs = ["Lib2WithSpecsActivity.java"],
+ manifest = "AndroidManifest_lib.xml",
+ proguard_specs = ["lib2_proguard.cfg"],
+)
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BasicActivity.java b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BasicActivity.java
new file mode 100644
index 0000000..4aee8d1
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/BasicActivity.java
@@ -0,0 +1,49 @@
+// Copyright 2023 The Bazel Authors. All rights reserved.
+//
+// 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.
+
+package com.basicapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+/** The main activity of the Basic Sample App. */
+public class BasicActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.basic_activity);
+
+ final Button buttons[] = {
+ findViewById(R.id.button_id_fizz), findViewById(R.id.button_id_buzz),
+ };
+
+ for (Button b : buttons) {
+ b.setOnClickListener(
+ new View.OnClickListener() {
+ public void onClick(View v) {
+ TextView tv = findViewById(R.id.text_hello);
+ if (v.getId() == R.id.button_id_fizz) {
+ tv.setText("fizz");
+ } else if (v.getId() == R.id.button_id_buzz) {
+ tv.setText("buzz");
+ }
+ }
+ });
+ }
+ }
+}
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/Lib2WithSpecsActivity.java b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/Lib2WithSpecsActivity.java
new file mode 100644
index 0000000..57d613f
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/Lib2WithSpecsActivity.java
@@ -0,0 +1,29 @@
+// Copyright 2023 The Bazel Authors. All rights reserved.
+//
+// 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.
+
+package com.basicapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+/** The main activity of the Basic Sample App. */
+public class Lib2WithSpecsActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i("TAG", "onCreate");
+ }
+}
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/LibWithSpecsActivity.java b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/LibWithSpecsActivity.java
new file mode 100644
index 0000000..b40be64
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/LibWithSpecsActivity.java
@@ -0,0 +1,29 @@
+// Copyright 2023 The Bazel Authors. All rights reserved.
+//
+// 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.
+
+package com.basicapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+/** The main activity of the Basic Sample App. */
+public class LibWithSpecsActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ Log.i("TAG", "onCreate");
+ }
+}
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/UnusedActivity.java b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/UnusedActivity.java
new file mode 100644
index 0000000..e188f87
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/UnusedActivity.java
@@ -0,0 +1,30 @@
+// Copyright 2023 The Bazel Authors. All rights reserved.
+//
+// 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.
+
+package com.basicapp;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+
+/** The main activity of the Basic Sample App. */
+public class UnusedActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.unused_activity);
+ Log.i("TAG", "onCreate");
+ }
+}
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib2_proguard.cfg b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib2_proguard.cfg
new file mode 100644
index 0000000..3fddc01
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib2_proguard.cfg
@@ -0,0 +1 @@
+-keep class com.basicapp.Lib2WithSpecsActivity \ No newline at end of file
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib_proguard.cfg b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib_proguard.cfg
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/lib_proguard.cfg
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/proguard.cfg b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/proguard.cfg
new file mode 100644
index 0000000..e0ef7ce
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/proguard.cfg
@@ -0,0 +1,2 @@
+# proguard specs
+-dontobfuscate
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/layout/basic_activity.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/layout/basic_activity.xml
new file mode 100644
index 0000000..f84199c
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/layout/basic_activity.xml
@@ -0,0 +1,23 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/text_hello"
+ android:text="@string/hello_world"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <Button
+ android:id="@+id/button_id_fizz"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="fizz" />
+ <Button
+ android:id="@+id/button_id_buzz"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="buzz" />
+
+</LinearLayout>
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/values/strings.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/values/strings.xml
new file mode 100644
index 0000000..565c987
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res/values/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name" translatable="false">basicapp</string>
+ <string name="hello_world" translatable="false">Hello world!</string>
+ <string name="action_settings" translatable="false">Settings</string>
+
+</resources>
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/layout/unused_activity.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/layout/unused_activity.xml
new file mode 100644
index 0000000..61fb73e
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/layout/unused_activity.xml
@@ -0,0 +1,12 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/text_hello"
+ android:text="@string/hello_world"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+</LinearLayout>
diff --git a/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/values/strings.xml b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/values/strings.xml
new file mode 100644
index 0000000..79934a2
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/java/com/basicapp/res_lib/values/strings.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name" translatable="false">basicapp</string>
+ <string name="hello_world" translatable="false">Hello world! unused</string>
+ <string name="action_settings" translatable="false">Settings</string>
+
+</resources>
diff --git a/test/rules/android_binary_internal/r8_integration/r8_integration_test.py b/test/rules/android_binary_internal/r8_integration/r8_integration_test.py
new file mode 100755
index 0000000..b9ba7e2
--- /dev/null
+++ b/test/rules/android_binary_internal/r8_integration/r8_integration_test.py
@@ -0,0 +1,91 @@
+# Copyright 2023 The Bazel Authors. All rights reserved.
+#
+# 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.
+
+import os
+import subprocess
+import unittest
+import zipfile
+
+
+class R8IntegrationTest(unittest.TestCase):
+ """Tests Bazel's R8 integration."""
+
+ def _r8_integration_check(
+ self, apk, expect_unused_activity_resource, expect_unused_activity_class
+ ):
+ tmp = os.environ["TEST_TMPDIR"]
+ apk_directory = (
+ "test/rules/android_binary_internal/r8_integration/java/com/basicapp"
+ )
+ apk_tmp = os.path.join(tmp, apk)
+ classes_dex = os.path.join(apk_tmp, "classes.dex")
+ with zipfile.ZipFile(os.path.join(apk_directory, apk)) as zf:
+ apk_files = zf.namelist()
+ zf.extract("classes.dex", apk_tmp)
+
+ self.assertEqual(
+ expect_unused_activity_resource,
+ "res/layout/unused_activity.xml" in apk_files,
+ )
+
+ build_tools_dir = "external/androidsdk-supplemental/build-tools"
+ build_tools_version = os.listdir(build_tools_dir)[0]
+ dexdump = os.path.join(build_tools_dir, build_tools_version, "dexdump")
+
+ dexdump_proc = subprocess.run(
+ [dexdump, classes_dex],
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ check=True,
+ )
+ dexdump_stdout = str(dexdump_proc.stdout)
+ self.assertEqual(
+ expect_unused_activity_class,
+ "Class descriptor : 'Lcom/basicapp/UnusedActivity;'" in dexdump_stdout,
+ )
+
+ # In all cases, the Lib2WithSpecsActivity class should be in the app,
+ # since lib2_proguard.cfg (an indirect dependency) specifies to keep it.
+ self.assertIn(
+ "Class descriptor : 'Lcom/basicapp/Lib2WithSpecsActivity;'",
+ dexdump_stdout,
+ )
+
+ def test_r8_integration(self):
+ # No R8, so unused resources and unused classes should be in the app
+ self._r8_integration_check(
+ "basic_app_no_R8.apk",
+ expect_unused_activity_resource=True,
+ expect_unused_activity_class=True,
+ )
+
+ # Run R8, don't shrink, so unused class should not be in the app but unused
+ # resource should remain.
+ self._r8_integration_check(
+ "basic_app_R8_no_shrink.apk",
+ expect_unused_activity_resource=True,
+ expect_unused_activity_class=False,
+ )
+
+ # Run R8 and shrinkings, so unused classes and resources should not be in
+ # the app.
+ self._r8_integration_check(
+ "basic_app_R8_shrink.apk",
+ expect_unused_activity_resource=False,
+ expect_unused_activity_class=False,
+ )
+
+
+if __name__ == "__main__":
+ unittest.main()