blob: edaf32137e156c00614d012e54c71fe03fa7a6cb [file] [log] [blame]
// Copyright (c) 2019, 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.desugar.desugaredlibrary;
import static junit.framework.TestCase.assertTrue;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import com.android.tools.r8.utils.codeinspector.MethodSubject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Spliterator;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class CustomCollectionForwardingTest extends DesugaredLibraryTestBase {
private final TestParameters parameters;
private final boolean shrinkDesugaredLibrary;
@Parameters(name = "{1}, shrinkDesugaredLibrary: {0}")
public static List<Object[]> data() {
return buildParameters(
BooleanUtils.values(), getTestParameters().withDexRuntimes().withAllApiLevels().build());
}
public CustomCollectionForwardingTest(boolean shrinkDesugaredLibrary, TestParameters parameters) {
this.shrinkDesugaredLibrary = shrinkDesugaredLibrary;
this.parameters = parameters;
}
@Test
public void testCustomCollectionD8() throws Exception {
KeepRuleConsumer keepRuleConsumer = createKeepRuleConsumer(parameters);
testForD8()
.addInnerClasses(CustomCollectionForwardingTest.class)
.setMinApi(parameters.getApiLevel())
.enableCoreLibraryDesugaring(parameters.getApiLevel(), keepRuleConsumer)
.compile()
.inspect(this::assertForwardingMethods)
.addDesugaredCoreLibraryRunClassPath(
this::buildDesugaredLibrary,
parameters.getApiLevel(),
keepRuleConsumer.get(),
shrinkDesugaredLibrary)
.run(parameters.getRuntime(), Executor.class)
.assertSuccessWithOutput(
StringUtils.lines("false", "false", "false", "false", "false", "false"));
}
private void assertForwardingMethods(CodeInspector inspector) {
if (parameters.getApiLevel().getLevel() >= AndroidApiLevel.N.getLevel()) {
return;
}
ClassSubject cal = inspector.clazz(CustomArrayList.class);
MethodSubject spliteratorCal = cal.method("j$.util.Spliterator", "spliterator");
assertTrue(spliteratorCal.isPresent());
assertTrue(
spliteratorCal
.streamInstructions()
.anyMatch(i -> i.isInvokeStatic() && i.toString().contains("List$-CC")));
MethodSubject streamCal = cal.method("j$.util.stream.Stream", "stream");
assertTrue(streamCal.isPresent());
assertTrue(
streamCal
.streamInstructions()
.anyMatch(i -> i.isInvokeStatic() && i.toString().contains("Collection$-CC")));
ClassSubject clhs = inspector.clazz(CustomLinkedHashSet.class);
MethodSubject spliteratorClhs = clhs.method("j$.util.Spliterator", "spliterator");
assertTrue(spliteratorClhs.isPresent());
assertTrue(
spliteratorClhs
.streamInstructions()
.anyMatch(i -> i.isInvokeStatic() && i.toString().contains("DesugarLinkedHashSet")));
MethodSubject streamClhs = clhs.method("j$.util.stream.Stream", "stream");
assertTrue(streamClhs.isPresent());
assertTrue(
streamClhs
.streamInstructions()
.anyMatch(i -> i.isInvokeStatic() && i.toString().contains("Collection$-CC")));
ClassSubject cl = inspector.clazz(CustomList.class);
MethodSubject spliteratorCl = cl.method("j$.util.Spliterator", "spliterator");
assertTrue(spliteratorCl.isPresent());
assertTrue(
spliteratorCl
.streamInstructions()
.anyMatch(i -> i.isInvokeStatic() && i.toString().contains("List$-CC")));
MethodSubject streamCl = cl.method("j$.util.stream.Stream", "stream");
assertTrue(streamCl.isPresent());
assertTrue(
streamCl
.streamInstructions()
.anyMatch(i -> i.isInvokeStatic() && i.toString().contains("Collection$-CC")));
}
static class Executor {
public static void main(String[] args) {
CustomArrayList<Object> objects = new CustomArrayList<>();
System.out.println(objects.spliterator().hasCharacteristics(Spliterator.CONCURRENT));
System.out.println(objects.stream().spliterator().hasCharacteristics(Spliterator.CONCURRENT));
CustomLinkedHashSet<Object> objects2 = new CustomLinkedHashSet<>();
System.out.println(objects2.spliterator().hasCharacteristics(Spliterator.CONCURRENT));
System.out.println(
objects2.stream().spliterator().hasCharacteristics(Spliterator.CONCURRENT));
CustomList<Object> objects3 = new CustomList<>();
System.out.println(objects3.spliterator().hasCharacteristics(Spliterator.CONCURRENT));
System.out.println(
objects3.stream().spliterator().hasCharacteristics(Spliterator.CONCURRENT));
}
}
static class CustomArrayList<E> extends ArrayList<E> implements Collection<E> {}
static class CustomLinkedHashSet<E> extends LinkedHashSet<E> implements Collection<E> {}
static class CustomList<E> implements Collection<E>, List<E> {
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object o) {
return false;
}
@NotNull
@Override
public Iterator<E> iterator() {
return null;
}
@NotNull
@Override
public Object[] toArray() {
return new Object[0];
}
@NotNull
@Override
public <T> T[] toArray(@NotNull T[] a) {
return null;
}
@Override
public boolean add(E e) {
return false;
}
@Override
public boolean remove(Object o) {
return false;
}
@Override
public boolean containsAll(@NotNull Collection<?> c) {
return false;
}
@Override
public boolean addAll(@NotNull Collection<? extends E> c) {
return false;
}
@Override
public boolean addAll(int index, @NotNull Collection<? extends E> c) {
return false;
}
@Override
public boolean removeAll(@NotNull Collection<?> c) {
return false;
}
@Override
public boolean retainAll(@NotNull Collection<?> c) {
return false;
}
@Override
public void clear() {}
@Override
public E get(int index) {
return null;
}
@Override
public E set(int index, E element) {
return null;
}
@Override
public void add(int index, E element) {}
@Override
public E remove(int index) {
return null;
}
@Override
public int indexOf(Object o) {
return 0;
}
@Override
public int lastIndexOf(Object o) {
return 0;
}
@NotNull
@Override
public ListIterator<E> listIterator() {
return null;
}
@NotNull
@Override
public ListIterator<E> listIterator(int index) {
return null;
}
@NotNull
@Override
public List<E> subList(int fromIndex, int toIndex) {
return null;
}
}
}