blob: b0b0b0e88fd9b7f321d9c30c39a8298f6103356e [file] [log] [blame]
Clément Béra83fa01e2024-08-02 09:49:58 +02001// Copyright (c) 2024, the R8 project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5package records;
6
7import static org.junit.Assume.assumeTrue;
8
9import com.android.tools.r8.JdkClassFileProvider;
10import com.android.tools.r8.NeverInline;
11import com.android.tools.r8.R8FullTestBuilder;
12import com.android.tools.r8.TestBase;
13import com.android.tools.r8.TestParameters;
14import com.android.tools.r8.TestParametersCollection;
15import com.android.tools.r8.TestRuntime.CfVm;
16import com.android.tools.r8.utils.AndroidApiLevel;
17import com.android.tools.r8.utils.StringUtils;
18import org.junit.Test;
19import org.junit.runner.RunWith;
20import org.junit.runners.Parameterized;
21import org.junit.runners.Parameterized.Parameter;
22import org.junit.runners.Parameterized.Parameters;
23
24@RunWith(Parameterized.class)
25public class RecordHashCodeTest extends TestBase {
26
27 private static final String EXPECTED_RESULT =
28 StringUtils.lines(
29 "true", "true", "true", "true", "false", "false", "true", "true", "false", "false");
30
31 @Parameter public TestParameters parameters;
32
33 @Parameters(name = "{0}")
34 public static TestParametersCollection data() {
35 return getTestParameters().withAllRuntimes().withAllApiLevelsAlsoForCf().build();
36 }
37
38 private boolean isCfRuntimeWithNativeRecordSupport() {
39 return parameters.isCfRuntime()
40 && parameters.asCfRuntime().isNewerThanOrEqual(CfVm.JDK14)
41 && parameters.getApiLevel().equals(AndroidApiLevel.B);
42 }
43
44 @Test
45 public void testReference() throws Exception {
46 assumeTrue(isCfRuntimeWithNativeRecordSupport());
47 testForJvm(parameters)
48 .addInnerClassesAndStrippedOuter(getClass())
49 .run(parameters.getRuntime(), TestClass.class)
50 .assertSuccessWithOutput(EXPECTED_RESULT);
51 }
52
53 @Test
54 public void testD8() throws Exception {
55 testForD8(parameters.getBackend())
56 .addInnerClassesAndStrippedOuter(getClass())
57 .setMinApi(parameters)
58 .run(parameters.getRuntime(), TestClass.class)
59 .applyIf(
Clément Bérad8769c22024-08-15 08:43:58 +020060 isRecordsFullyDesugaredForD8(parameters)
Clément Béra83fa01e2024-08-02 09:49:58 +020061 || runtimeWithRecordsSupport(parameters.getRuntime()),
62 r -> r.assertSuccessWithOutput(EXPECTED_RESULT),
63 r -> r.assertFailureWithErrorThatThrows(NoClassDefFoundError.class));
64 }
65
66 @Test
67 public void testR8() throws Exception {
68 parameters.assumeR8TestParameters();
69 assumeTrue(parameters.isDexRuntime() || isCfRuntimeWithNativeRecordSupport());
70 R8FullTestBuilder builder =
71 testForR8(parameters.getBackend())
72 .addInnerClassesAndStrippedOuter(getClass())
73 .setMinApi(parameters)
74 .addInliningAnnotations()
75 .addKeepMainRule(TestClass.class);
76 if (parameters.isCfRuntime()) {
77 builder
78 .addLibraryProvider(JdkClassFileProvider.fromSystemJdk())
79 .run(parameters.getRuntime(), TestClass.class)
80 .assertSuccessWithOutput(EXPECTED_RESULT);
81 return;
82 }
83 builder.run(parameters.getRuntime(), TestClass.class).assertSuccessWithOutput(EXPECTED_RESULT);
84 }
85
Clément Bérac36e1542024-08-21 11:16:32 +020086 @Test
87 public void testR8DontShrinkDontObfuscate() throws Exception {
88 parameters.assumeR8TestParameters();
89 assumeTrue(parameters.isDexRuntime() || isCfRuntimeWithNativeRecordSupport());
90 R8FullTestBuilder builder =
91 testForR8(parameters.getBackend())
92 .addInnerClassesAndStrippedOuter(getClass())
93 .setMinApi(parameters)
94 .addDontShrink()
95 .addDontObfuscate()
96 .addInliningAnnotations()
97 .addKeepMainRule(TestClass.class);
98 if (parameters.isCfRuntime()) {
99 builder
100 .addLibraryProvider(JdkClassFileProvider.fromSystemJdk())
101 .run(parameters.getRuntime(), TestClass.class)
102 .assertSuccessWithOutput(EXPECTED_RESULT);
103 return;
104 }
105 builder.run(parameters.getRuntime(), TestClass.class).assertSuccessWithOutput(EXPECTED_RESULT);
106 }
107
Clément Béra83fa01e2024-08-02 09:49:58 +0200108 public static class TestClass {
109
110 record Person(String name, int age) {}
111
112 record Food(String name, int sweetness, int saltyness) {}
113
114 public static void main(String[] args) {
115 Person janeDoe = new Person("Jane Doe", 42);
116 System.out.println(equals(janeDoe.hashCode(), janeDoe.hashCode()));
117 System.out.println(equalsHash(janeDoe, janeDoe));
118 Person otherJaneDoe = new Person("Jane Doe", 42);
119 System.out.println(equals(janeDoe.hashCode(), otherJaneDoe.hashCode()));
120 System.out.println(equalsHash(janeDoe, otherJaneDoe));
121 Person johnDoe = new Person("John Doe", 45);
122 System.out.println(equals(janeDoe.hashCode(), johnDoe.hashCode()));
123 System.out.println(equalsHash(janeDoe, johnDoe));
124
125 Food bread = new Food("bread", 1, 100);
126 System.out.println(equals(bread.hashCode(), bread.hashCode()));
127 System.out.println(equalsHash(bread, bread));
128 Food biscuit = new Food("biscuit", 50, 20);
129 System.out.println(equals(bread.hashCode(), biscuit.hashCode()));
130 System.out.println(equalsHash(bread, biscuit));
131 }
132
133 @NeverInline
134 public static boolean equals(int i1, int i2) {
135 return System.currentTimeMillis() > 0 ? i1 == i2 : false;
136 }
137
138 @NeverInline
139 public static boolean equalsHash(Record r1, Record r2) {
140 return System.currentTimeMillis() > 0 ? equals(r1.hashCode(), r2.hashCode()) : false;
141 }
142 }
143}