aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-11-28 05:54:07 -0800
committerGravatar Copybara-Service <copybara-piper@google.com>2017-11-28 05:56:02 -0800
commitaf10f2a83bdda8406a8c0a012db6d38e19d022b0 (patch)
treed384623998a0096577b5c747d3bc9a97e135efcc /src/test/java/com/google
parent683bdc7a069a8328676740798d2fb6abc2119a2f (diff)
Let to push lambda arguments not only with *LOAD instructions but with SIPUSH and *CONST_*.
RELNOTES: None PiperOrigin-RevId: 177149410
Diffstat (limited to 'src/test/java/com/google')
-rw-r--r--src/test/java/com/google/devtools/build/android/desugar/BUILD66
-rw-r--r--src/test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java318
-rw-r--r--src/test/java/com/google/devtools/build/android/desugar/DesugarLambdaTest.java38
3 files changed, 417 insertions, 5 deletions
diff --git a/src/test/java/com/google/devtools/build/android/desugar/BUILD b/src/test/java/com/google/devtools/build/android/desugar/BUILD
index a079ef80c5..1e33dd6996 100644
--- a/src/test/java/com/google/devtools/build/android/desugar/BUILD
+++ b/src/test/java/com/google/devtools/build/android/desugar/BUILD
@@ -61,14 +61,28 @@ java_test(
],
)
+# Test for b/62060793. Verifies constant lambda arguments that were pushed using *CONST_0
+# instructions.
+java_test(
+ name = "DesugarFunctionalTestForConstantArgumentsInLambdas",
+ size = "small",
+ srcs = ["DesugarLambdaTest.java"],
+ tags = ["no_windows"],
+ test_class = "com.google.devtools.build.android.desugar.DesugarLambdaTest",
+ deps = [
+ ":desugar_lambda_with_constant_arguments_lib",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)
+
# Test for b/62456849. If a synthetic method is named "lambda$XXX", but not used in invokedynamic,
# then Desugar should keep it in the class, rather than renaming it.
java_test(
name = "DesugarFunctionalTestForSyntheticMethodsWithLambdaNames",
size = "small",
- srcs = [
- "DesugarFunctionalTest.java",
- ],
+ srcs = ["DesugarFunctionalTest.java"],
tags = ["no_windows"],
test_class = "com.google.devtools.build.android.desugar.DesugarFunctionalTest",
deps = [
@@ -792,6 +806,39 @@ genrule(
tools = ["//src/tools/android/java/com/google/devtools/build/android/desugar:Desugar"],
)
+# Generates special lambda invocation so we can test for b/62060793.
+genrule(
+ name = "generate_lambda_with_constant_arguments_in_test_data",
+ outs = ["testdata_generate_lambda_with_constant_arguments.jar"],
+ cmd = "$(location :generate_lambda_with_constant_arguments) $@",
+ tags = ["no_windows"],
+ tools = [":generate_lambda_with_constant_arguments"],
+)
+
+# Desugar the test data for b/62456849
+genrule(
+ name = "desugar_lambda_with_constant_arguments",
+ srcs = [
+ ":generate_lambda_with_constant_arguments_in_test_data",
+ # Depend on Jacoco runtime in case testdata was built with coverage instrumentation
+ "//third_party/java/jacoco:blaze-agent",
+ "//tools/defaults:android_jar",
+ ],
+ outs = ["testdata_desugar_generate_lambda_with_constant_arguments.jar"],
+ cmd = "$(location //src/tools/android/java/com/google/devtools/build/android/desugar:Desugar) " +
+ "-i $(location :generate_lambda_with_constant_arguments_in_test_data) -o $@ " +
+ "--classpath_entry $(location //third_party/java/jacoco:blaze-agent) " +
+ "--bootclasspath_entry $(location //tools/defaults:android_jar)",
+ tags = ["no_windows"],
+ tools = ["//src/tools/android/java/com/google/devtools/build/android/desugar:Desugar"],
+)
+
+java_import(
+ name = "desugar_lambda_with_constant_arguments_lib",
+ jars = [":desugar_lambda_with_constant_arguments"],
+ tags = ["no_windows"],
+)
+
# Convert human-written methods whose names start with "lambda$XXX" to synthetic methods, so we can
# test for b/62456849.
genrule(
@@ -812,8 +859,7 @@ genrule(
"//third_party:guava-jars",
":separate",
":generate_synthetic_methods_with_lambda_names_in_test_data",
- # Depend on Jacoco runtime in case testdata was built with coverage
- # instrumentation
+ # Depend on Jacoco runtime in case testdata was built with coverage instrumentation
"//third_party/java/jacoco:blaze-agent",
"//tools/defaults:android_jar",
],
@@ -1864,6 +1910,16 @@ genrule(
)
java_binary(
+ name = "generate_lambda_with_constant_arguments",
+ srcs = ["Bug62060793TestDataGenerator.java"],
+ main_class = "com.google.devtools.build.android.desugar.Bug62060793TestDataGenerator",
+ deps = [
+ "//third_party:asm",
+ "//third_party:guava",
+ ],
+)
+
+java_binary(
name = "generate_synthetic_method_with_lambda_name_convention",
srcs = ["Bug62456849TestDataGenerator.java"],
main_class = "com.google.devtools.build.android.desugar.Bug62456849TestDataGenerator",
diff --git a/src/test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java b/src/test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java
new file mode 100644
index 0000000000..f6c3c99a30
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/android/desugar/Bug62060793TestDataGenerator.java
@@ -0,0 +1,318 @@
+// Copyright 2017 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.base.Preconditions.checkArgument;
+import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
+import static org.objectweb.asm.Opcodes.ACC_FINAL;
+import static org.objectweb.asm.Opcodes.ACC_INTERFACE;
+import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ACC_SUPER;
+import static org.objectweb.asm.Opcodes.ACONST_NULL;
+import static org.objectweb.asm.Opcodes.ALOAD;
+import static org.objectweb.asm.Opcodes.ARETURN;
+import static org.objectweb.asm.Opcodes.ASTORE;
+import static org.objectweb.asm.Opcodes.BIPUSH;
+import static org.objectweb.asm.Opcodes.DCONST_0;
+import static org.objectweb.asm.Opcodes.DLOAD;
+import static org.objectweb.asm.Opcodes.DUP_X1;
+import static org.objectweb.asm.Opcodes.FCONST_0;
+import static org.objectweb.asm.Opcodes.FLOAD;
+import static org.objectweb.asm.Opcodes.GOTO;
+import static org.objectweb.asm.Opcodes.IADD;
+import static org.objectweb.asm.Opcodes.ICONST_0;
+import static org.objectweb.asm.Opcodes.ICONST_1;
+import static org.objectweb.asm.Opcodes.ICONST_2;
+import static org.objectweb.asm.Opcodes.ICONST_4;
+import static org.objectweb.asm.Opcodes.IFNONNULL;
+import static org.objectweb.asm.Opcodes.ILOAD;
+import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
+import static org.objectweb.asm.Opcodes.INVOKESTATIC;
+import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
+import static org.objectweb.asm.Opcodes.ISTORE;
+import static org.objectweb.asm.Opcodes.LCONST_0;
+import static org.objectweb.asm.Opcodes.LLOAD;
+import static org.objectweb.asm.Opcodes.NEW;
+import static org.objectweb.asm.Opcodes.RETURN;
+import static org.objectweb.asm.Opcodes.SIPUSH;
+import static org.objectweb.asm.Opcodes.SWAP;
+import static org.objectweb.asm.Opcodes.V1_8;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Handle;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+
+/**
+ * Test data generator for b/62060793. This class creates a special labmda invocation that
+ * contains *CONST_0 values on stack, which are passed as lambda arguments.
+ */
+public class Bug62060793TestDataGenerator {
+
+ private static final String CLASS_NAME =
+ "com/google/devtools/build/android/desugar/testdata/ConstantArgumentsInLambda";
+
+ private static final String INTERFACE_TYPE_NAME = CLASS_NAME + "$Interface";
+
+ public static void main(String[] args) throws IOException {
+ checkArgument(
+ args.length == 1,
+ "Usage: %s <output-jar>",
+ Bug62060793TestDataGenerator.class.getName());
+ Path outputJar = Paths.get(args[0]);
+
+ try (ZipOutputStream outZip =
+ new ZipOutputStream(new BufferedOutputStream(Files.newOutputStream(outputJar)))) {
+ String className = CLASS_NAME + ".class";
+ writeToZipFile(outZip, className, createClass());
+ String interfaceName = INTERFACE_TYPE_NAME + ".class";
+ writeToZipFile(outZip, interfaceName, createInterface());
+ }
+ }
+
+ private static void writeToZipFile(ZipOutputStream outZip, String entryName, byte[] content)
+ throws IOException {
+ ZipEntry result = new ZipEntry(entryName);
+ result.setTime(0L);
+ outZip.putNextEntry(result);
+ outZip.write(content);
+ outZip.closeEntry();
+ }
+
+ private static byte[] createClass() {
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ MethodVisitor mv;
+ cw.visit(
+ V1_8, ACC_PUBLIC | ACC_SUPER,
+ CLASS_NAME,
+ null, "java/lang/Object", null);
+
+ cw.visitInnerClass(
+ INTERFACE_TYPE_NAME,
+ CLASS_NAME,
+ "Interface",
+ ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
+
+ cw.visitInnerClass(
+ "java/lang/invoke/MethodHandles$Lookup",
+ "java/lang/invoke/MethodHandles",
+ "Lookup",
+ ACC_PUBLIC | ACC_FINAL | ACC_STATIC);
+
+ {
+ mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
+ mv.visitInsn(RETURN);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(
+ ACC_PRIVATE | ACC_STATIC,
+ "method",
+ "(Ljava/lang/String;)Ljava/lang/String;",
+ null,
+ null);
+ mv.visitParameter("str", 0);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 0);
+ mv.visitInsn(ARETURN);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(
+ ACC_PRIVATE | ACC_STATIC,
+ "method",
+ "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/String;",
+ null,
+ null);
+ mv.visitParameter("bool", 0);
+ mv.visitParameter("c", 0);
+ mv.visitParameter("b", 0);
+ mv.visitParameter("f", 0);
+ mv.visitParameter("d", 0);
+ mv.visitParameter("l", 0);
+ mv.visitParameter("i", 0);
+ mv.visitParameter("s", 0);
+ mv.visitParameter("o", 0);
+ mv.visitParameter("array", 0);
+ mv.visitParameter("str", 0);
+ mv.visitCode();
+ mv.visitVarInsn(ALOAD, 10);
+ mv.visitMethodInsn(
+ INVOKESTATIC,
+ "java/lang/String",
+ "valueOf",
+ "(Ljava/lang/Object;)Ljava/lang/String;", false);
+ mv.visitVarInsn(ASTORE, 13);
+ mv.visitVarInsn(ALOAD, 11);
+ Label l0 = new Label();
+ mv.visitJumpInsn(IFNONNULL, l0);
+ mv.visitInsn(ICONST_1);
+ Label l1 = new Label();
+ mv.visitJumpInsn(GOTO, l1);
+ mv.visitLabel(l0);
+ mv.visitFrame(Opcodes.F_APPEND, 1, new Object[] {"java/lang/String"}, 0, null);
+ mv.visitInsn(ICONST_0);
+ mv.visitLabel(l1);
+ mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {Opcodes.INTEGER});
+ mv.visitVarInsn(ISTORE, 14);
+ mv.visitIntInsn(BIPUSH, 91);
+ mv.visitVarInsn(ALOAD, 12);
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/String",
+ "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;", false);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String",
+ "length", "()I", false);
+ mv.visitInsn(IADD);
+ mv.visitVarInsn(ALOAD, 13);
+ mv.visitMethodInsn(INVOKESTATIC, "java/lang/String",
+ "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;", false);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String",
+ "length", "()I", false);
+ mv.visitInsn(IADD);
+ mv.visitTypeInsn(NEW, "java/lang/StringBuilder");
+ mv.visitInsn(DUP_X1);
+ mv.visitInsn(SWAP);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuilder",
+ "<init>", "(I)V", false);
+ mv.visitVarInsn(ALOAD, 12);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 0);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(Z)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 1);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(C)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 2);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(I)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(FLOAD, 3);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(F)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(DLOAD, 4);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(D)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(LLOAD, 6);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(J)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 8);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(I)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 9);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(I)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ALOAD, 13);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(Ljava/lang/String;)Ljava/lang/StringBuilder;", false);
+ mv.visitVarInsn(ILOAD, 14);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "append", "(Z)Ljava/lang/StringBuilder;", false);
+ mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuilder",
+ "toString", "()Ljava/lang/String;", false);
+ mv.visitInsn(ARETURN);
+ mv.visitEnd();
+ }
+ {
+ mv = cw.visitMethod(
+ ACC_PUBLIC | ACC_STATIC,
+ "lambdaWithConstantArguments",
+ "()L" + INTERFACE_TYPE_NAME + ";",
+ null, null);
+ mv.visitCode();
+ mv.visitInsn(ICONST_0);
+ mv.visitInsn(ICONST_1);
+ mv.visitInsn(ICONST_2);
+ mv.visitInsn(FCONST_0);
+ mv.visitInsn(DCONST_0);
+ mv.visitInsn(LCONST_0);
+ mv.visitInsn(ICONST_4);
+ mv.visitIntInsn(SIPUSH, 9);
+ mv.visitInsn(ACONST_NULL);
+ mv.visitInsn(ACONST_NULL);
+ mv.visitInvokeDynamicInsn(
+ "call",
+ "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;)L" + INTERFACE_TYPE_NAME + ";",
+ new Handle(
+ Opcodes.H_INVOKESTATIC,
+ "java/lang/invoke/LambdaMetafactory",
+ "metafactory",
+ "(Ljava/lang/invoke/MethodHandles$Lookup;"
+ + "Ljava/lang/String;Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodType;"
+ + "Ljava/lang/invoke/MethodHandle;"
+ + "Ljava/lang/invoke/MethodType;"
+ + ")Ljava/lang/invoke/CallSite;",
+ false),
+ new Object[] {
+ Type.getType("(Ljava/lang/String;)Ljava/lang/String;"),
+ new Handle(
+ Opcodes.H_INVOKESTATIC,
+ CLASS_NAME,
+ "method",
+ "(ZCBFDJISLjava/lang/Object;[Ljava/lang/Object;Ljava/lang/String;"
+ + ")Ljava/lang/String;",
+ false),
+ Type.getType("(Ljava/lang/String;)Ljava/lang/String;")});
+ mv.visitInsn(ARETURN);
+ mv.visitEnd();
+ }
+
+ cw.visitEnd();
+
+ return cw.toByteArray();
+ }
+
+ private static byte[] createInterface() {
+ ClassWriter cw = new ClassWriter(0);
+ MethodVisitor mv;
+
+ cw.visit(V1_8, ACC_PUBLIC | ACC_ABSTRACT | ACC_INTERFACE,
+ INTERFACE_TYPE_NAME,
+ null, "java/lang/Object", null);
+
+ cw.visitInnerClass(
+ INTERFACE_TYPE_NAME,
+ CLASS_NAME,
+ "Interface",
+ ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE);
+
+ {
+ mv = cw.visitMethod(
+ ACC_PUBLIC | ACC_ABSTRACT,
+ "call",
+ "(Ljava/lang/String;)Ljava/lang/String;",
+ null,
+ null);
+ mv.visitParameter("input", 0);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+
+ return cw.toByteArray();
+
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/android/desugar/DesugarLambdaTest.java b/src/test/java/com/google/devtools/build/android/desugar/DesugarLambdaTest.java
new file mode 100644
index 0000000000..7c3d7eeeb3
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/android/desugar/DesugarLambdaTest.java
@@ -0,0 +1,38 @@
+// Copyright 2016 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.devtools.build.android.desugar.testdata.ConstantArgumentsInLambda;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Tests uncommon lambda scenarious.
+ */
+@RunWith(JUnit4.class)
+public class DesugarLambdaTest {
+
+ /**
+ * Test for b/62060793. Verifies constant lambda arguments that were pushed using *CONST_0
+ * instructions.
+ */
+ @Test
+ public void testCallLambdaWithConstants() throws Exception {
+ assertThat(ConstantArgumentsInLambda.lambdaWithConstantArguments().call("test"))
+ .isEqualTo("testfalse\00120.00.0049nulltrue");
+ }
+}