blob: b13ade6f563f43ea1df592ac83e130d2a0ad8230 [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.conversiontests;
import com.android.tools.r8.TestRuntime.DexRuntime;
import com.android.tools.r8.ToolHelper.DexVm;
import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.StringUtils;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Iterator;
import java.util.function.Consumer;
import org.jetbrains.annotations.NotNull;
import org.junit.Test;
public class ConversionIntroduceInterfaceMethodTest extends DesugaredLibraryTestBase {
@Test
public void testNoInterfaceMethods() throws Exception {
Path customLib = testForD8().addProgramClasses(CustomLibClass.class).compile().writeToZip();
testForD8()
.setMinApi(AndroidApiLevel.B)
.addProgramClasses(
MyCollectionInterface.class,
MyCollectionInterfaceAbstract.class,
MyCollection.class,
Executor.class)
.addLibraryClasses(CustomLibClass.class)
.enableCoreLibraryDesugaring(AndroidApiLevel.B)
.compile()
.addDesugaredCoreLibraryRunClassPath(this::buildDesugaredLibrary, AndroidApiLevel.B)
.addRunClasspathFiles(customLib)
.run(new DexRuntime(DexVm.ART_9_0_0_HOST), Executor.class)
.assertSuccessWithOutput(
StringUtils.lines(
"action called from j$ consumer",
"forEach called",
"action called from java consumer",
"forEach called"));
}
static class CustomLibClass {
@SuppressWarnings({"unchecked", "WeakerAccess"})
public static void callForeach(Iterable iterable) {
iterable.forEach(x -> System.out.println("action called from java consumer"));
}
}
static class Executor {
@SuppressWarnings("RedundantOperationOnEmptyContainer")
public static void main(String[] args) {
MyCollection<String> strings = new MyCollection<>();
// Call foreach with j$ consumer.
strings.forEach(x -> System.out.println("action called from j$ consumer"));
// Call foreach with java consumer.
CustomLibClass.callForeach(strings);
}
}
interface MyCollectionInterface<E> extends Collection<E> {
// The following method override a method from Iterable and use a desugared type.
// API conversion is required.
@Override
default void forEach(Consumer<? super E> action) {
action.accept(null);
System.out.println("forEach called");
}
}
@SuppressWarnings("ConstantConditions")
static class MyCollection<E> implements MyCollectionInterface<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 removeAll(@NotNull Collection<?> c) {
return false;
}
@Override
public boolean retainAll(@NotNull Collection<?> c) {
return false;
}
@Override
public void clear() {}
}
interface MyCollectionInterfaceAbstract<E> extends Collection<E> {
// The following method override a method from Iterable and use a desugared type.
// API conversion is required.
@Override
void forEach(Consumer<? super E> action);
}
}