Desugar: Extract common help methods to DesugarTestHelpers

#java11 #desugar #cleanup

- Change: Allows a user to match instructions by regular expression.

PiperOrigin-RevId: 300667525
diff --git a/src/test/java/com/google/devtools/build/android/desugar/nest/BUILD b/src/test/java/com/google/devtools/build/android/desugar/nest/BUILD
index 442fae3..ea3920d 100644
--- a/src/test/java/com/google/devtools/build/android/desugar/nest/BUILD
+++ b/src/test/java/com/google/devtools/build/android/desugar/nest/BUILD
@@ -177,6 +177,7 @@
     ],
     test_class = "com.google.devtools.build.android.desugar.nest.NestDesugaringMethodAccessTest",
     deps = [
+        "//src/tools/android/java/com/google/devtools/build/android/desugar/langmodel",
         "//src/tools/android/java/com/google/devtools/build/android/desugar/testing/junit:desugar_rule",
         "//third_party:asm",
         "//third_party:asm-tree",
diff --git a/src/test/java/com/google/devtools/build/android/desugar/nest/NestDesugaringCoreLibTest.java b/src/test/java/com/google/devtools/build/android/desugar/nest/NestDesugaringCoreLibTest.java
index fbd3b5e..d101978 100644
--- a/src/test/java/com/google/devtools/build/android/desugar/nest/NestDesugaringCoreLibTest.java
+++ b/src/test/java/com/google/devtools/build/android/desugar/nest/NestDesugaringCoreLibTest.java
@@ -17,8 +17,8 @@
 package com.google.devtools.build.android.desugar.nest;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.android.desugar.testing.junit.DesugarTestHelpers.getRuntimePathsFromJvmFlag;
 
-import com.google.common.base.Splitter;
 import com.google.devtools.build.android.desugar.testing.junit.AsmNode;
 import com.google.devtools.build.android.desugar.testing.junit.DesugarRule;
 import com.google.devtools.build.android.desugar.testing.junit.DesugarRunner;
@@ -28,8 +28,6 @@
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodHandles.Lookup;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -45,7 +43,7 @@
   @Rule
   public final DesugarRule desugarRule =
       DesugarRule.builder(this, lookup)
-          .addSourceInputs(getInputSourceFilesFromJvmOption("input_srcs"))
+          .addSourceInputs(getRuntimePathsFromJvmFlag("input_srcs"))
           .addJavacOptions("-source 11", "-target 11")
           .addCommandOptions("desugar_nest_based_private_access", "true")
           .addCommandOptions("allow_empty_bootclasspath", "true")
@@ -54,12 +52,6 @@
           .addCommandOptions("rewrite_core_library_prefix", "javadesugar/testing/")
           .build();
 
-  private static Path[] getInputSourceFilesFromJvmOption(String jvmOptionKey) {
-    return Splitter.on(" ").trimResults().splitToList(System.getProperty(jvmOptionKey)).stream()
-        .map(Paths::get)
-        .toArray(Path[]::new);
-  }
-
   @Test
   public void inputClassFileMajorVersions(
       @AsmNode(className = "javadesugar.testing.TestCoreType$MateA", round = 0) ClassNode before,
diff --git a/src/test/java/com/google/devtools/build/android/desugar/nest/NestDesugaringMethodAccessTest.java b/src/test/java/com/google/devtools/build/android/desugar/nest/NestDesugaringMethodAccessTest.java
index d178414..929a9a9 100644
--- a/src/test/java/com/google/devtools/build/android/desugar/nest/NestDesugaringMethodAccessTest.java
+++ b/src/test/java/com/google/devtools/build/android/desugar/nest/NestDesugaringMethodAccessTest.java
@@ -16,14 +16,15 @@
 
 package com.google.devtools.build.android.desugar.nest;
 
-import static com.google.common.collect.ImmutableList.toImmutableList;
 import static com.google.common.truth.Truth.assertThat;
 
-import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
+import com.google.devtools.build.android.desugar.langmodel.MemberUseKind;
+import com.google.devtools.build.android.desugar.langmodel.MethodInvocationSite;
 import com.google.devtools.build.android.desugar.testing.junit.AsmNode;
 import com.google.devtools.build.android.desugar.testing.junit.DesugarRule;
 import com.google.devtools.build.android.desugar.testing.junit.DesugarRunner;
+import com.google.devtools.build.android.desugar.testing.junit.DesugarTestHelpers;
 import com.google.devtools.build.android.desugar.testing.junit.DynamicClassLiteral;
 import com.google.devtools.build.android.desugar.testing.junit.JdkSuppress;
 import com.google.devtools.build.android.desugar.testing.junit.JdkVersion;
@@ -40,10 +41,7 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.AbstractInsnNode;
 import org.objectweb.asm.tree.ClassNode;
-import org.objectweb.asm.tree.MethodInsnNode;
 import org.objectweb.asm.tree.MethodNode;
 
 /** Tests for accessing private methods from another class within a nest. */
@@ -214,18 +212,20 @@
   public void invokeVirtualOnPrivateMethod_beforeDesugaring(
       @AsmNode(className = "NonNest", memberName = "invokeTwoSum", round = 0)
           MethodNode invokeTwoSum) {
-    MethodInsnNode twoSumInvocation =
-        Iterables.getOnlyElement(findMethodInvocations(invokeTwoSum, "twoSum"));
-    assertThat(twoSumInvocation.getOpcode()).isEqualTo(Opcodes.INVOKEVIRTUAL);
+    MethodInvocationSite twoSumInvocation =
+        Iterables.getOnlyElement(
+            DesugarTestHelpers.findMethodInvocationSites(invokeTwoSum, "NonNest", "twoSum", ".*"));
+    assertThat(twoSumInvocation.invocationKind()).isEqualTo(MemberUseKind.INVOKEVIRTUAL);
   }
 
   @Test
   public void invokeSpecialOnPrivateMethod_afterDesugaring(
       @AsmNode(className = "NonNest", memberName = "invokeTwoSum", round = 1)
           MethodNode invokeTwoSum) {
-    MethodInsnNode twoSumInvocation =
-        Iterables.getOnlyElement(findMethodInvocations(invokeTwoSum, "twoSum"));
-    assertThat(twoSumInvocation.getOpcode()).isEqualTo(Opcodes.INVOKESPECIAL);
+    MethodInvocationSite twoSumInvocation =
+        Iterables.getOnlyElement(
+            DesugarTestHelpers.findMethodInvocationSites(invokeTwoSum, "NonNest", "twoSum", ".*"));
+    assertThat(twoSumInvocation.invocationKind()).isEqualTo(MemberUseKind.INVOKESPECIAL);
   }
 
   @Test
@@ -237,13 +237,4 @@
     assertThat(result).isEqualTo(1005L);
   }
 
-  private static ImmutableList<MethodInsnNode> findMethodInvocations(
-      MethodNode enclosingMethod, String invokedMethodName) {
-    AbstractInsnNode[] instructions = enclosingMethod.instructions.toArray();
-    return Arrays.stream(instructions)
-        .filter(node -> node.getType() == AbstractInsnNode.METHOD_INSN)
-        .map(node -> (MethodInsnNode) node)
-        .filter(node -> invokedMethodName.equals(node.name))
-        .collect(toImmutableList());
-  }
 }
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/testing/junit/DesugarRuleBuilder.java b/src/tools/android/java/com/google/devtools/build/android/desugar/testing/junit/DesugarRuleBuilder.java
index f4abb75..ace60d5 100644
--- a/src/tools/android/java/com/google/devtools/build/android/desugar/testing/junit/DesugarRuleBuilder.java
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/testing/junit/DesugarRuleBuilder.java
@@ -16,7 +16,6 @@
 
 package com.google.devtools.build.android.desugar.testing.junit;
 
-import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableListMultimap;
@@ -159,7 +158,7 @@
    *  .addSourceInputsFromJvmFlag("input_srcs").</code> in your test class.
    */
   public DesugarRuleBuilder addSourceInputsFromJvmFlag(String jvmFlagKey) {
-    return addSourceInputs(getRuntimePathsFromJvmFlag(jvmFlagKey));
+    return addSourceInputs(DesugarTestHelpers.getRuntimePathsFromJvmFlag(jvmFlagKey));
   }
 
   /**
@@ -169,17 +168,7 @@
    *  .addSourceInputsFromJvmFlag("input_srcs").</code> in your test class.
    */
   public DesugarRuleBuilder addJarInputsFromJvmFlag(String jvmFlagKey) {
-    return addInputs(getRuntimePathsFromJvmFlag(jvmFlagKey));
-  }
-
-  /**
-   * A helper method that reads file paths into an array from the JVM flag value associated with
-   * {@param jvmFlagKey}.
-   */
-  public static Path[] getRuntimePathsFromJvmFlag(String jvmFlagKey) {
-    return Splitter.on(" ").trimResults().splitToList(System.getProperty(jvmFlagKey)).stream()
-        .map(Paths::get)
-        .toArray(Path[]::new);
+    return addInputs(DesugarTestHelpers.getRuntimePathsFromJvmFlag(jvmFlagKey));
   }
 
   /**
diff --git a/src/tools/android/java/com/google/devtools/build/android/desugar/testing/junit/DesugarTestHelpers.java b/src/tools/android/java/com/google/devtools/build/android/desugar/testing/junit/DesugarTestHelpers.java
new file mode 100644
index 0000000..2292776
--- /dev/null
+++ b/src/tools/android/java/com/google/devtools/build/android/desugar/testing/junit/DesugarTestHelpers.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2020 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.testing.junit;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.ImmutableList.toImmutableList;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.android.desugar.langmodel.ClassName;
+import com.google.devtools.build.android.desugar.langmodel.MemberUseKind;
+import com.google.devtools.build.android.desugar.langmodel.MethodInvocationSite;
+import com.google.devtools.build.android.desugar.langmodel.MethodKey;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+import org.objectweb.asm.tree.AbstractInsnNode;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.MethodNode;
+
+/** Static utilities that facilities desugar testing. */
+public class DesugarTestHelpers {
+
+  /**
+   * A helper method that reads file paths into an array from the JVM flag value associated with
+   * {@param jvmFlagKey}.
+   */
+  public static Path[] getRuntimePathsFromJvmFlag(String jvmFlagKey) {
+    String jvmPropertyValue =
+        checkNotNull(
+            System.getProperty(jvmFlagKey),
+            "Expected JVM Option to be specified: -D<%s>=<YourValue>",
+            jvmFlagKey);
+    return Splitter.on(" ").trimResults().splitToList(jvmPropertyValue).stream()
+        .map(Paths::get)
+        .toArray(Path[]::new);
+  }
+
+  /** Find all matched method invocation instructions in the given method. */
+  public static ImmutableList<MethodInvocationSite> findMethodInvocationSites(
+      MethodNode enclosingMethod,
+      String methodOwnerRegex,
+      String methodNameRegex,
+      String methodDescRegex) {
+    Predicate<String> methodOwnerPredicate = Pattern.compile(methodOwnerRegex).asPredicate();
+    Predicate<String> methodNamePredicate = Pattern.compile(methodNameRegex).asPredicate();
+    Predicate<String> methodDescPredicate = Pattern.compile(methodDescRegex).asPredicate();
+    AbstractInsnNode[] instructions = enclosingMethod.instructions.toArray();
+    return Arrays.stream(instructions)
+        .filter(node -> node.getType() == AbstractInsnNode.METHOD_INSN)
+        .map(node -> (MethodInsnNode) node)
+        .filter(node -> methodOwnerPredicate.test(node.owner))
+        .filter(node -> methodNamePredicate.test(node.name))
+        .filter(node -> methodDescPredicate.test(node.desc))
+        .map(
+            node ->
+                MethodInvocationSite.builder()
+                    .setInvocationKind(MemberUseKind.fromValue(node.getOpcode()))
+                    .setMethod(MethodKey.create(ClassName.create(node.owner), node.name, node.desc))
+                    .setIsInterface(node.itf)
+                    .build())
+        .collect(toImmutableList());
+  }
+
+  private DesugarTestHelpers() {}
+}