Backport Java 9 Byte/Short compareUnsigned methods

Change-Id: Iffc29a824b37a5710cce370e43580a5091a4447c
diff --git a/src/test/examplesJava9/backport/ByteBackportJava9Main.java b/src/test/examplesJava9/backport/ByteBackportJava9Main.java
new file mode 100644
index 0000000..2487a81
--- /dev/null
+++ b/src/test/examplesJava9/backport/ByteBackportJava9Main.java
@@ -0,0 +1,38 @@
+package backport;
+
+public final class ByteBackportJava9Main {
+  private static final byte MIN_UNSIGNED_VALUE = (byte) 0;
+  private static final byte MAX_UNSIGNED_VALUE = (byte) -1;
+
+  public static void main(String[] args) {
+    testCompareUnsigned();
+  }
+
+  private static void testCompareUnsigned() {
+    assertTrue(Byte.compareUnsigned(MIN_UNSIGNED_VALUE, MIN_UNSIGNED_VALUE) == 0);
+    assertTrue(Byte.compareUnsigned(MIN_UNSIGNED_VALUE, Byte.MAX_VALUE) < 0);
+    assertTrue(Byte.compareUnsigned(MIN_UNSIGNED_VALUE, Byte.MIN_VALUE) < 0);
+    assertTrue(Byte.compareUnsigned(MIN_UNSIGNED_VALUE, MAX_UNSIGNED_VALUE) < 0);
+
+    assertTrue(Byte.compareUnsigned(Byte.MAX_VALUE, MIN_UNSIGNED_VALUE) > 0);
+    assertTrue(Byte.compareUnsigned(Byte.MAX_VALUE, Byte.MAX_VALUE) == 0);
+    assertTrue(Byte.compareUnsigned(Byte.MAX_VALUE, Byte.MIN_VALUE) < 0);
+    assertTrue(Byte.compareUnsigned(Byte.MAX_VALUE, MAX_UNSIGNED_VALUE) < 0);
+
+    assertTrue(Byte.compareUnsigned(Byte.MIN_VALUE, MIN_UNSIGNED_VALUE) > 0);
+    assertTrue(Byte.compareUnsigned(Byte.MIN_VALUE, Byte.MAX_VALUE) > 0);
+    assertTrue(Byte.compareUnsigned(Byte.MIN_VALUE, Byte.MIN_VALUE) == 0);
+    assertTrue(Byte.compareUnsigned(Byte.MIN_VALUE, MAX_UNSIGNED_VALUE) < 0);
+
+    assertTrue(Byte.compareUnsigned(MAX_UNSIGNED_VALUE, MIN_UNSIGNED_VALUE) > 0);
+    assertTrue(Byte.compareUnsigned(MAX_UNSIGNED_VALUE, Byte.MAX_VALUE) > 0);
+    assertTrue(Byte.compareUnsigned(MAX_UNSIGNED_VALUE, Byte.MIN_VALUE) > 0);
+    assertTrue(Byte.compareUnsigned(MAX_UNSIGNED_VALUE, MAX_UNSIGNED_VALUE) == 0);
+  }
+
+  private static void assertTrue(boolean value) {
+    if (!value) {
+      throw new AssertionError("Expected <true> but was <false>");
+    }
+  }
+}
diff --git a/src/test/examplesJava9/backport/ShortBackportJava9Main.java b/src/test/examplesJava9/backport/ShortBackportJava9Main.java
new file mode 100644
index 0000000..63764dd
--- /dev/null
+++ b/src/test/examplesJava9/backport/ShortBackportJava9Main.java
@@ -0,0 +1,38 @@
+package backport;
+
+public final class ShortBackportJava9Main {
+  private static final byte MIN_UNSIGNED_VALUE = (short) 0;
+  private static final byte MAX_UNSIGNED_VALUE = (short) -1;
+
+  public static void main(String[] args) {
+    testCompareUnsigned();
+  }
+
+  private static void testCompareUnsigned() {
+    assertTrue(Short.compareUnsigned(MIN_UNSIGNED_VALUE, MIN_UNSIGNED_VALUE) == 0);
+    assertTrue(Short.compareUnsigned(MIN_UNSIGNED_VALUE, Short.MAX_VALUE) < 0);
+    assertTrue(Short.compareUnsigned(MIN_UNSIGNED_VALUE, Short.MIN_VALUE) < 0);
+    assertTrue(Short.compareUnsigned(MIN_UNSIGNED_VALUE, MAX_UNSIGNED_VALUE) < 0);
+
+    assertTrue(Short.compareUnsigned(Short.MAX_VALUE, MIN_UNSIGNED_VALUE) > 0);
+    assertTrue(Short.compareUnsigned(Short.MAX_VALUE, Short.MAX_VALUE) == 0);
+    assertTrue(Short.compareUnsigned(Short.MAX_VALUE, Short.MIN_VALUE) < 0);
+    assertTrue(Short.compareUnsigned(Short.MAX_VALUE, MAX_UNSIGNED_VALUE) < 0);
+
+    assertTrue(Short.compareUnsigned(Short.MIN_VALUE, MIN_UNSIGNED_VALUE) > 0);
+    assertTrue(Short.compareUnsigned(Short.MIN_VALUE, Short.MAX_VALUE) > 0);
+    assertTrue(Short.compareUnsigned(Short.MIN_VALUE, Short.MIN_VALUE) == 0);
+    assertTrue(Short.compareUnsigned(Short.MIN_VALUE, MAX_UNSIGNED_VALUE) < 0);
+
+    assertTrue(Short.compareUnsigned(MAX_UNSIGNED_VALUE, MIN_UNSIGNED_VALUE) > 0);
+    assertTrue(Short.compareUnsigned(MAX_UNSIGNED_VALUE, Short.MAX_VALUE) > 0);
+    assertTrue(Short.compareUnsigned(MAX_UNSIGNED_VALUE, Short.MIN_VALUE) > 0);
+    assertTrue(Short.compareUnsigned(MAX_UNSIGNED_VALUE, MAX_UNSIGNED_VALUE) == 0);
+  }
+
+  private static void assertTrue(boolean value) {
+    if (!value) {
+      throw new AssertionError("Expected <true> but was <false>");
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
index 218d462..c7a0a58 100644
--- a/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/backports/AbstractBackportTest.java
@@ -9,6 +9,9 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.Assert.assertEquals;
 
+import com.android.tools.r8.D8TestBuilder;
+import com.android.tools.r8.D8TestCompileResult;
+import com.android.tools.r8.D8TestRunResult;
 import com.android.tools.r8.TestBase;
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.utils.AndroidApiLevel;
@@ -16,6 +19,7 @@
 import com.android.tools.r8.utils.codeinspector.CodeInspector;
 import com.android.tools.r8.utils.codeinspector.InstructionSubject;
 import com.android.tools.r8.utils.codeinspector.MethodSubject;
+import java.nio.file.Path;
 import java.util.List;
 import java.util.NavigableMap;
 import java.util.TreeMap;
@@ -26,13 +30,29 @@
   private final TestParameters parameters;
   private final Class<?> targetClass;
   private final Class<?> testClass;
+  private final Path testJar;
+  private final String testClassName;
   private final NavigableMap<AndroidApiLevel, Integer> invokeStaticCounts = new TreeMap<>();
 
   AbstractBackportTest(TestParameters parameters, Class<?> targetClass,
       Class<?> testClass) {
+    this(parameters, targetClass, testClass, null, null);
+  }
+
+  AbstractBackportTest(TestParameters parameters, Class<?> targetClass,
+      Path testJar, String testClassName) {
+    this(parameters, targetClass, null, testJar, testClassName);
+  }
+
+  private AbstractBackportTest(TestParameters parameters, Class<?> targetClass,
+      Class<?> testClass, Path testJar, String testClassName) {
     this.parameters = parameters;
     this.targetClass = targetClass;
     this.testClass = testClass;
+    this.testJar = testJar;
+    this.testClassName = testClassName;
+    assert testClass != null ^ testJar != null; // No test class requires a test path.
+    assert testJar == null || testClassName != null; // Test jar path requires a main class.
 
     // Assume all method calls will be rewritten on the lowest API level.
     invokeStaticCounts.put(AndroidApiLevel.B, 0);
@@ -44,18 +64,32 @@
 
   @Test
   public void desugaring() throws Exception {
-    testForD8()
-        .addProgramClasses(MiniAssert.class, IgnoreInvokes.class)
-        .addProgramClassesAndInnerClasses(testClass)
+    D8TestBuilder builder = testForD8()
         .setMinApi(parameters.getRuntime().asDex().getMinApiLevel())
-        .compile()
-        .run(parameters.getRuntime(), testClass)
-        .assertSuccess()
-        .inspect(this::assertDesugaring);
+        .addProgramClasses(MiniAssert.class, IgnoreInvokes.class);
+    if (testClass != null) {
+      builder.addProgramClassesAndInnerClasses(testClass);
+    } else {
+      builder.addProgramFiles(testJar);
+    }
+    D8TestCompileResult compileResult = builder.compile();
+
+    D8TestRunResult runResult;
+    if (testClass != null) {
+      runResult = compileResult.run(parameters.getRuntime(), testClass);
+    } else {
+      runResult = compileResult.run(parameters.getRuntime(), testClassName);
+    }
+    runResult.assertSuccess().inspect(this::assertDesugaring);
   }
 
   private void assertDesugaring(CodeInspector inspector) {
-    ClassSubject testSubject = inspector.clazz(testClass);
+    ClassSubject testSubject;
+    if (testClass != null) {
+      testSubject = inspector.clazz(testClass);
+    } else {
+      testSubject = inspector.clazz(testClassName);
+    }
     assertThat(testSubject, isPresent());
 
     List<InstructionSubject> javaInvokeStatics = testSubject.allMethods()
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ByteBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ByteBackportJava9Test.java
new file mode 100644
index 0000000..a9dd5f2
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ByteBackportJava9Test.java
@@ -0,0 +1,33 @@
+// 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.backports;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+@RunWith(Parameterized.class)
+public final class ByteBackportJava9Test extends AbstractBackportTest {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return getTestParameters().withDexRuntimes().build();
+  }
+
+  private static final Path TEST_JAR =
+      Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+
+  public ByteBackportJava9Test(TestParameters parameters) {
+    super(parameters, Byte.class, TEST_JAR, "backport.ByteBackportJava9Main");
+    // TODO Once shipped in an actual API level, migrate to ByteBackportTest
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/backports/ShortBackportJava9Test.java b/src/test/java/com/android/tools/r8/desugar/backports/ShortBackportJava9Test.java
new file mode 100644
index 0000000..0afa926
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/backports/ShortBackportJava9Test.java
@@ -0,0 +1,31 @@
+// 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.backports;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.ToolHelper;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import static com.android.tools.r8.utils.FileUtils.JAR_EXTENSION;
+
+@RunWith(Parameterized.class)
+public final class ShortBackportJava9Test extends AbstractBackportTest {
+  @Parameters(name = "{0}")
+  public static Iterable<?> data() {
+    return getTestParameters().withDexRuntimes().build();
+  }
+
+  private static final Path TEST_JAR =
+      Paths.get(ToolHelper.EXAMPLES_JAVA9_BUILD_DIR).resolve("backport" + JAR_EXTENSION);
+
+  public ShortBackportJava9Test(TestParameters parameters) {
+    super(parameters, Short.class, TEST_JAR, "backport.ShortBackportJava9Main");
+    // TODO Once shipped in an actual API level, migrate to ShortBackportTest
+  }
+}