| // Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| package com.android.tools.r8.utils.structural; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotEquals; |
| import static org.junit.Assert.assertTrue; |
| |
| import com.android.tools.r8.TestBase; |
| import com.android.tools.r8.TestParameters; |
| import com.android.tools.r8.TestParametersCollection; |
| import com.google.common.collect.ImmutableList; |
| import com.google.common.collect.ImmutableSet; |
| import java.util.HashSet; |
| import java.util.Set; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.junit.runners.Parameterized; |
| |
| @RunWith(Parameterized.class) |
| public class StructuralItemsCustomOrderTest extends TestBase { |
| |
| @Parameterized.Parameters(name = "{0}") |
| public static TestParametersCollection data() { |
| return getTestParameters().withNoneRuntime().build(); |
| } |
| |
| public StructuralItemsCustomOrderTest(TestParameters parameters) { |
| parameters.assertNoneRuntime(); |
| } |
| |
| final B b1 = new B(1); |
| final B b2 = new B(2); |
| final B b2_copy = new B(2); |
| |
| final A a1b1 = new A(1, b1); |
| final A a2b1 = new A(2, b1); |
| final A a1b2 = new A(1, b2); |
| final A a2b2 = new A(2, b2); |
| final A a1b2_copy = new A(1, b2_copy); |
| final A a2b2_copy = new A(2, b2_copy); |
| |
| @Test |
| public void testOrder() { |
| assertFalse(b1.isLessThan(b2)); |
| assertTrue(b2.isEqualTo(b2_copy)); |
| assertTrue(b2.isLessThan(b1)); |
| |
| assertFalse(a1b1.isLessThan(a1b2)); |
| assertTrue(a1b2.isLessThan(a2b1)); |
| assertFalse(a2b1.isLessThan(a1b2_copy)); |
| } |
| |
| @Test |
| public void testOrderWithIdentityEquivalence() { |
| // These mirror the above exactly but using the compare result. |
| RepresentativeMap map = t -> t; |
| |
| assertFalse(b1.compareWithTypeEquivalenceTo(b2, map) < 0); |
| assertTrue(b2.compareWithTypeEquivalenceTo(b2_copy, map) == 0); |
| assertTrue(b2.compareWithTypeEquivalenceTo(b1, map) < 0); |
| |
| assertFalse(a1b1.compareWithTypeEquivalenceTo(a1b2, map) < 0); |
| assertTrue(a1b2.compareWithTypeEquivalenceTo(a2b1, map) < 0); |
| assertFalse(a2b1.compareWithTypeEquivalenceTo(a1b2_copy, map) < 0); |
| } |
| |
| @Test |
| public void testEquals() { |
| assertFalse(b1.isEqualTo(b2)); |
| assertTrue(b2.isEqualTo(b2_copy)); |
| assertEquals(b2, b2_copy); |
| |
| assertFalse(a2b2.isEqualTo(a2b1)); |
| assertTrue(a1b2.isEqualTo(a1b2_copy)); |
| assertEquals(a2b2, a2b2_copy); |
| |
| // Type incompatible check should still work. |
| assertNotEquals(b1, a1b1); |
| } |
| |
| @Test |
| public void testHashCode() { |
| Set<B> bs = new HashSet<>(ImmutableList.of(b1, b2, b2_copy)); |
| assertEquals(ImmutableSet.of(b1, b2), bs); |
| |
| Set<A> as = new HashSet<>(ImmutableList.of(a1b1, a1b2, a2b1, a2b2, a1b2_copy, a2b2_copy)); |
| assertEquals(ImmutableSet.of(a1b1, a1b2, a2b1, a2b2), as); |
| |
| // If these collide it is a poor hashing algorithm... |
| assertNotEquals(b1.hashCode(), b2.hashCode()); |
| } |
| |
| private static class A implements StructuralItem<A> { |
| |
| private final int x; |
| private final B b; |
| |
| private static void specify(StructuralSpecification<A, ?> spec) { |
| spec.withInt(a -> a.x).withItem(a -> a.b); |
| } |
| |
| public A(int x, B b) { |
| this.x = x; |
| this.b = b; |
| } |
| |
| @Override |
| public StructuralMapping<A> getStructuralMapping() { |
| return A::specify; |
| } |
| |
| @Override |
| public A self() { |
| return this; |
| } |
| |
| @Override |
| public final boolean equals(Object other) { |
| return Equatable.equalsImpl(this, other); |
| } |
| |
| @Override |
| public final int hashCode() { |
| return HashCodeVisitor.run(this, A::specify); |
| } |
| } |
| |
| private static class B implements StructuralItem<B> { |
| |
| private final int y; |
| |
| private static void specify(StructuralSpecification<B, ?> spec) { |
| spec.withInt(b -> b.y); |
| } |
| |
| public B(int y) { |
| this.y = y; |
| } |
| |
| @Override |
| public StructuralMapping<B> getStructuralMapping() { |
| return B::specify; |
| } |
| |
| @Override |
| public B self() { |
| return this; |
| } |
| |
| @Override |
| public final boolean equals(Object other) { |
| return Equatable.equalsImpl(this, other); |
| } |
| |
| @Override |
| public final int hashCode() { |
| return HashCodeVisitor.run(this, B::specify); |
| } |
| |
| // Override allowing a change to the order of any type of compare-to visitation, e.g., with |
| // and without a type equivalence map. |
| @Override |
| public int acceptCompareTo(B other, CompareToVisitor visitor) { |
| return visitor.visit(other, this, B::specify); |
| } |
| } |
| } |