blob: 9b43207d6009f810c18bb9c86844c74b733ec3c3 [file] [log] [blame]
// Copyright 2018 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.android.desugar;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.ImmutableList;
import com.google.devtools.build.android.desugar.io.CoreLibraryRewriter;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.objectweb.asm.Opcodes;
@RunWith(JUnit4.class)
public class CoreLibrarySupportTest {
@Test
public void testIsRenamedCoreLibrary() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
null,
ImmutableList.of("java/time/"),
ImmutableList.of(),
ImmutableList.of(),
ImmutableList.of());
assertThat(support.isRenamedCoreLibrary("java/time/X")).isTrue();
assertThat(support.isRenamedCoreLibrary("java/time/y/X")).isTrue();
assertThat(support.isRenamedCoreLibrary("java/io/X")).isFalse();
assertThat(support.isRenamedCoreLibrary("java/io/X$$CC")).isTrue();
assertThat(support.isRenamedCoreLibrary("java/io/X$$Lambda$17")).isTrue();
assertThat(support.isRenamedCoreLibrary("com/google/X")).isFalse();
}
@Test
public void testIsRenamedCoreLibrary_prefixedLoader() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter("__/"),
null,
ImmutableList.of("java/time/"),
ImmutableList.of(),
ImmutableList.of(),
ImmutableList.of());
assertThat(support.isRenamedCoreLibrary("__/java/time/X")).isTrue();
assertThat(support.isRenamedCoreLibrary("__/java/time/y/X")).isTrue();
assertThat(support.isRenamedCoreLibrary("__/java/io/X")).isFalse();
assertThat(support.isRenamedCoreLibrary("__/java/io/X$$CC")).isTrue();
assertThat(support.isRenamedCoreLibrary("__/java/io/X$$Lambda$17")).isTrue();
assertThat(support.isRenamedCoreLibrary("com/google/X")).isFalse();
}
@Test
public void testRenameCoreLibrary() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
null,
ImmutableList.of(),
ImmutableList.of(),
ImmutableList.of(),
ImmutableList.of());
assertThat(support.renameCoreLibrary("java/time/X")).isEqualTo("j$/time/X");
assertThat(support.renameCoreLibrary("com/google/X")).isEqualTo("com/google/X");
}
@Test
public void testRenameCoreLibrary_prefixedLoader() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter("__/"),
null,
ImmutableList.of(),
ImmutableList.of(),
ImmutableList.of(),
ImmutableList.of());
assertThat(support.renameCoreLibrary("__/java/time/X")).isEqualTo("j$/time/X");
assertThat(support.renameCoreLibrary("com/google/X")).isEqualTo("com/google/X");
}
@Test
public void testMoveTarget() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter("__/"),
null,
ImmutableList.of("java/util/Helper"),
ImmutableList.of(),
ImmutableList.of("java/util/Existing#match -> java/util/Helper"),
ImmutableList.of());
assertThat(support.getMoveTarget("__/java/util/Existing", "match")).isEqualTo("j$/util/Helper");
assertThat(support.getMoveTarget("java/util/Existing", "match")).isEqualTo("j$/util/Helper");
assertThat(support.getMoveTarget("__/java/util/Existing", "matchesnot")).isNull();
assertThat(support.getMoveTarget("__/java/util/ExistingOther", "match")).isNull();
}
@Test
public void testIsEmulatedCoreClassOrInterface() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of("java/util/concurrent/"),
ImmutableList.of("java/util/Map"),
ImmutableList.of(),
ImmutableList.of());
assertThat(support.isEmulatedCoreClassOrInterface("java/util/Map")).isTrue();
assertThat(support.isEmulatedCoreClassOrInterface("java/util/Map$$Lambda$17")).isFalse();
assertThat(support.isEmulatedCoreClassOrInterface("java/util/Map$$CC")).isFalse();
assertThat(support.isEmulatedCoreClassOrInterface("java/util/HashMap")).isTrue();
assertThat(support.isEmulatedCoreClassOrInterface("java/util/concurrent/ConcurrentMap"))
.isFalse(); // false for renamed prefixes
assertThat(support.isEmulatedCoreClassOrInterface("com/google/Map")).isFalse();
}
@Test
public void testGetCoreInterfaceRewritingTarget_emulatedDefaultMethod() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
ImmutableList.of("java/util/Collection"),
ImmutableList.of(),
ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/Collection",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
true))
.isEqualTo(Collection.class);
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEVIRTUAL,
"java/util/ArrayList",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
false))
.isEqualTo(Collection.class);
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"com/google/HypotheticalListInterface",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
true))
.isNull();
}
@Test
public void testGetCoreInterfaceRewritingTarget_emulatedImplementationMoved() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of("java/util/Moved"),
ImmutableList.of("java/util/Map"),
ImmutableList.of("java/util/LinkedHashMap#forEach->java/util/Moved"),
ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/Map",
"forEach",
"(Ljava/util/function/BiConsumer;)V",
true))
.isEqualTo(Map.class);
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKESPECIAL,
"java/util/Map",
"forEach",
"(Ljava/util/function/BiConsumer;)V",
true))
.isEqualTo(Map.class);
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEVIRTUAL,
"java/util/LinkedHashMap",
"forEach",
"(Ljava/util/function/BiConsumer;)V",
false))
.isEqualTo(Map.class);
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKESPECIAL,
"java/util/LinkedHashMap",
"forEach",
"(Ljava/util/function/BiConsumer;)V",
false))
.isEqualTo(LinkedHashMap.class);
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKESPECIAL,
"java/util/HashMap",
"forEach",
"(Ljava/util/function/BiConsumer;)V",
false))
.isEqualTo(Map.class);
}
@Test
public void testGetCoreInterfaceRewritingTarget_abstractMethod() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
ImmutableList.of("java/util/Collection"),
ImmutableList.of(),
ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/Collection",
"size",
"()I",
true))
.isNull();
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEVIRTUAL,
"java/util/ArrayList",
"size",
"()I",
false))
.isNull();
}
@Test
public void testGetCoreInterfaceRewritingTarget_emulatedDefaultOverride() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
ImmutableList.of("java/util/Map"),
ImmutableList.of(),
ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/Map",
"putIfAbsent",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
true))
.isEqualTo(Map.class);
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/concurrent/ConcurrentMap",
"putIfAbsent",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
true))
.isNull(); // putIfAbsent is default in Map but abstract in ConcurrentMap
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/concurrent/ConcurrentMap",
"getOrDefault",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
true))
.isEqualTo(ConcurrentMap.class); // conversely, getOrDefault is overridden as default method
}
@Test
public void testGetCoreInterfaceRewritingTarget_staticInterfaceMethod() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
ImmutableList.of("java/util/Comparator"),
ImmutableList.of(),
ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKESTATIC,
"java/util/Comparator",
"reverseOrder",
"()Ljava/util/Comparator;",
true))
.isEqualTo(Comparator.class);
}
/**
* Tests that call sites of renamed core libraries are treated like call sites in regular
* {@link InterfaceDesugaring}.
*/
@Test
public void testGetCoreInterfaceRewritingTarget_renamed() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of("java/util/"),
ImmutableList.of(),
ImmutableList.of(),
ImmutableList.of());
// regular invocations of default methods: ignored
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/Collection",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
true))
.isNull();
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEVIRTUAL,
"java/util/ArrayList",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
false))
.isNull();
// abstract methods: ignored
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/Collection",
"size",
"()I",
true))
.isNull();
// static interface method
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKESTATIC,
"java/util/Comparator",
"reverseOrder",
"()Ljava/util/Comparator;",
true))
.isEqualTo(Comparator.class);
// invokespecial for default methods: find nearest definition
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKESPECIAL,
"java/util/List",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
true))
.isEqualTo(Collection.class);
// invokespecial on a class: ignore (even if there's an inherited default method)
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKESPECIAL,
"java/util/ArrayList",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
false))
.isNull();
}
@Test
public void testGetCoreInterfaceRewritingTarget_ignoreRenamedInvokeInterface() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of("java/util/concurrent/"), // should return null for these
ImmutableList.of("java/util/Map"),
ImmutableList.of(),
ImmutableList.of());
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/Map",
"getOrDefault",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
true))
.isEqualTo(Map.class);
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/concurrent/ConcurrentMap",
"getOrDefault",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
true))
.isNull();
}
@Test
public void testGetCoreInterfaceRewritingTarget_excludedMethodIgnored() throws Exception {
CoreLibrarySupport support =
new CoreLibrarySupport(
new CoreLibraryRewriter(""),
Thread.currentThread().getContextClassLoader(),
ImmutableList.of(),
ImmutableList.of("java/util/Collection"),
ImmutableList.of(),
ImmutableList.of("java/util/Collection#removeIf"));
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEINTERFACE,
"java/util/List",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
true))
.isNull();
assertThat(
support.getCoreInterfaceRewritingTarget(
Opcodes.INVOKEVIRTUAL,
"java/util/ArrayList",
"removeIf",
"(Ljava/util/function/Predicate;)Z",
false))
.isNull();
}
@Test
public void testEmulatedMethod_nullExceptions() throws Exception {
CoreLibrarySupport.EmulatedMethod m =
CoreLibrarySupport.EmulatedMethod.create(1, Number.class, "a", "()V", null);
assertThat(m.access()).isEqualTo(1);
assertThat(m.owner()).isEqualTo(Number.class);
assertThat(m.name()).isEqualTo("a");
assertThat(m.descriptor()).isEqualTo("()V");
assertThat(m.exceptions()).isEmpty();
}
@Test
public void testEmulatedMethod_givenExceptions() throws Exception {
CoreLibrarySupport.EmulatedMethod m =
CoreLibrarySupport.EmulatedMethod.create(
1, Number.class, "a", "()V", new String[] {"b", "c"});
assertThat(m.access()).isEqualTo(1);
assertThat(m.owner()).isEqualTo(Number.class);
assertThat(m.name()).isEqualTo("a");
assertThat(m.descriptor()).isEqualTo("()V");
assertThat(m.exceptions()).containsExactly("b", "c").inOrder();
}
}