|
12 | 12 | # See the License for the specific language governing permissions and |
13 | 13 | # limitations under the License. |
14 | 14 |
|
15 | | -"""Tests that R8 properly applies core library desugaring. |
16 | | -
|
17 | | -Verifies that methods added after API 26 (like Duration.toSeconds() from |
18 | | -API 31) are retargeted to their backported implementations when R8 processes |
19 | | -an android_binary with core library desugaring enabled. |
20 | | -""" |
21 | | - |
22 | 15 | import os |
23 | 16 | import subprocess |
24 | 17 | import sys |
|
27 | 20 |
|
28 | 21 |
|
29 | 22 | class R8DesugaringTest(unittest.TestCase): |
30 | | - """Tests R8 core library desugaring integration.""" |
| 23 | + """Tests R8 core library desugaring integration.""" |
31 | 24 |
|
32 | | - def _get_dexdump_output(self, apk_name): |
33 | | - tmp = os.environ["TEST_TMPDIR"] |
34 | | - apk_directory = "test/rules/android_binary/r8_integration/java/com/desugaring" |
35 | | - apk_path = os.path.join(apk_directory, apk_name) |
36 | | - apk_tmp = os.path.join(tmp, apk_name) |
| 25 | + def _get_dexdump_output(self, apk_name): |
| 26 | + tmp = os.environ["TEST_TMPDIR"] |
| 27 | + apk_directory = "test/rules/android_binary/r8_integration/java/com/desugaring" |
| 28 | + apk_path = os.path.join(apk_directory, apk_name) |
| 29 | + apk_tmp = os.path.join(tmp, apk_name) |
37 | 30 |
|
38 | | - all_output = [] |
39 | | - with zipfile.ZipFile(apk_path) as zf: |
40 | | - for name in zf.namelist(): |
41 | | - if name.endswith(".dex"): |
42 | | - zf.extract(name, apk_tmp) |
43 | | - dex_path = os.path.join(apk_tmp, name) |
44 | | - proc = subprocess.run( |
45 | | - [dexdump, "-d", dex_path], |
46 | | - stdout=subprocess.PIPE, |
47 | | - stderr=subprocess.PIPE, |
48 | | - check=True, |
49 | | - ) |
50 | | - all_output.append(proc.stdout.decode(errors="replace")) |
| 31 | + with zipfile.ZipFile(apk_path) as zf: |
| 32 | + zf.extract("classes.dex", apk_tmp) |
51 | 33 |
|
52 | | - return "\n".join(all_output) |
| 34 | + dexdump_proc = subprocess.run( |
| 35 | + [dexdump, "-d", os.path.join(apk_tmp, "classes.dex")], |
| 36 | + stdout=subprocess.PIPE, |
| 37 | + stderr=subprocess.PIPE, |
| 38 | + check=True, |
| 39 | + ) |
| 40 | + return str(dexdump_proc.stdout) |
53 | 41 |
|
54 | | - def test_duration_to_seconds_is_desugared(self): |
55 | | - """Duration.toSeconds() (API 31) must not appear as a raw call in the DEX.""" |
56 | | - output = self._get_dexdump_output("desugaring_app_r8.apk") |
| 42 | + def test_duration_to_seconds_is_desugared(self): |
| 43 | + output = self._get_dexdump_output("desugaring_app_r8.apk") |
57 | 44 |
|
58 | | - self.assertNotIn( |
59 | | - "Ljava/time/Duration;.toSeconds:()J", |
60 | | - output, |
61 | | - "Duration.toSeconds() was NOT desugared. This method requires API 31 " |
62 | | - "and will cause NoSuchMethodError on API 28-30 devices. " |
63 | | - "R8 must be passed --desugared-lib to retarget this call.", |
64 | | - ) |
| 45 | + # Duration.toSeconds() (API 31) must not appear as a raw call in the DEX. |
| 46 | + # If present, R8 was not passed --desugared-lib and the call will cause |
| 47 | + # NoSuchMethodError on API 28-30 devices. |
| 48 | + self.assertNotIn( |
| 49 | + "Ljava/time/Duration;.toSeconds:()J", |
| 50 | + output, |
| 51 | + ) |
65 | 52 |
|
66 | | - def test_desugared_duration_class_present(self): |
67 | | - """The desugared library runtime must be included in the APK.""" |
68 | | - output = self._get_dexdump_output("desugaring_app_r8.apk") |
| 53 | + def test_desugared_duration_class_present(self): |
| 54 | + output = self._get_dexdump_output("desugaring_app_r8.apk") |
69 | 55 |
|
70 | | - # The DurationUser class should still be in the DEX (kept by proguard rules) |
71 | | - self.assertIn( |
72 | | - "Class descriptor : 'Lcom/desugaring/DurationUser;'", |
73 | | - output, |
74 | | - "DurationUser class not found in DEX output", |
75 | | - ) |
| 56 | + # The DurationUser class should still be in the DEX (kept by proguard rules) |
| 57 | + self.assertIn( |
| 58 | + "Class descriptor : 'Lcom/desugaring/DurationUser;'", |
| 59 | + output, |
| 60 | + ) |
76 | 61 |
|
77 | 62 |
|
78 | 63 | if __name__ == "__main__": |
79 | | - dexdump = sys.argv.pop() |
80 | | - unittest.main(argv=None) |
| 64 | + dexdump = sys.argv.pop() |
| 65 | + unittest.main(argv=None) |
0 commit comments