blob: 679200c2c760a133e6dc4b12056e88837479ff5a [file] [log] [blame]
// 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);
}
}
}