Desugared Lib Time Conversions

Bug: 134732760
Change-Id: I0a4e7601daa318f568ed36fe9ca05a21bf972c61
diff --git a/src/test/desugaredLibraryConversions/conversions/TimeConversions.java b/src/test/desugaredLibraryConversions/conversions/TimeConversions.java
new file mode 100644
index 0000000..660df49
--- /dev/null
+++ b/src/test/desugaredLibraryConversions/conversions/TimeConversions.java
@@ -0,0 +1,68 @@
+// 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.conversion;
+
+public class TimeConversions {
+
+  public static j$.time.ZonedDateTime from(java.time.ZonedDateTime dateTime) {
+    if (dateTime == null) {
+      return null;
+    }
+    return j$.time.ZonedDateTime.of(
+        dateTime.getYear(),
+        dateTime.getMonthValue(),
+        dateTime.getDayOfMonth(),
+        dateTime.getHour(),
+        dateTime.getMinute(),
+        dateTime.getSecond(),
+        dateTime.getNano(),
+        j$.time.ZoneId.of(dateTime.getZone().getId()));
+  }
+
+  public static java.time.ZonedDateTime to(j$.time.ZonedDateTime dateTime) {
+    if (dateTime == null) {
+      return null;
+    }
+    return java.time.ZonedDateTime.of(
+        dateTime.getYear(),
+        dateTime.getMonthValue(),
+        dateTime.getDayOfMonth(),
+        dateTime.getHour(),
+        dateTime.getMinute(),
+        dateTime.getSecond(),
+        dateTime.getNano(),
+        java.time.ZoneId.of(dateTime.getZone().getId()));
+  }
+
+  // Following conversions are hidden (Used by tests APIs only).
+
+  public static j$.time.LocalDate from(java.time.LocalDate date) {
+    if (date == null) {
+      return null;
+    }
+    return j$.time.LocalDate.of(date.getYear(), date.getMonthValue(), date.getDayOfMonth());
+  }
+
+  public static java.time.LocalDate to(j$.time.LocalDate date) {
+    if (date == null) {
+      return null;
+    }
+    return java.time.LocalDate.of(date.getYear(), date.getMonthValue(), date.getDayOfMonth());
+  }
+
+  public static j$.time.Duration from(java.time.Duration duration) {
+    if (duration == null) {
+      return null;
+    }
+    return j$.time.Duration.ofSeconds(duration.getSeconds(), duration.getNano());
+  }
+
+  public static java.time.Duration to(j$.time.Duration duration) {
+    if (duration == null) {
+      return null;
+    }
+    return java.time.Duration.ofSeconds(duration.getSeconds(), duration.getNano());
+  }
+}
diff --git a/src/test/desugaredLibraryConversions/stubs/Duration.java b/src/test/desugaredLibraryConversions/stubs/Duration.java
new file mode 100644
index 0000000..e559a8f
--- /dev/null
+++ b/src/test/desugaredLibraryConversions/stubs/Duration.java
@@ -0,0 +1,19 @@
+// 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 j$.time;
+
+public class Duration {
+  public static Duration ofSeconds(long seconds, long nanoAdjustment) {
+    return null;
+  }
+
+  public int getSeconds() {
+    return 0;
+  }
+
+  public int getNano() {
+    return 0;
+  }
+}
diff --git a/src/test/desugaredLibraryConversions/stubs/LocalDate.java b/src/test/desugaredLibraryConversions/stubs/LocalDate.java
new file mode 100644
index 0000000..ddbff3b
--- /dev/null
+++ b/src/test/desugaredLibraryConversions/stubs/LocalDate.java
@@ -0,0 +1,23 @@
+// 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 j$.time;
+
+public class LocalDate {
+  public static LocalDate of(int year, int month, int dayOfMonth) {
+    return null;
+  }
+
+  public int getYear() {
+    return 0;
+  }
+
+  public int getMonthValue() {
+    return 0;
+  }
+
+  public int getDayOfMonth() {
+    return 0;
+  }
+}
diff --git a/src/test/desugaredLibraryConversions/stubs/ZoneId.java b/src/test/desugaredLibraryConversions/stubs/ZoneId.java
new file mode 100644
index 0000000..27f7230
--- /dev/null
+++ b/src/test/desugaredLibraryConversions/stubs/ZoneId.java
@@ -0,0 +1,16 @@
+// 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 j$.time;
+
+public final class ZoneId {
+
+  public static ZoneId of(String id) {
+    return null;
+  }
+
+  public String getId() {
+    return null;
+  }
+}
diff --git a/src/test/desugaredLibraryConversions/stubs/ZonedDateTime.java b/src/test/desugaredLibraryConversions/stubs/ZonedDateTime.java
new file mode 100644
index 0000000..ff02570
--- /dev/null
+++ b/src/test/desugaredLibraryConversions/stubs/ZonedDateTime.java
@@ -0,0 +1,52 @@
+// 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 j$.time;
+
+public final class ZonedDateTime {
+
+  public static ZonedDateTime of(
+      int year,
+      int month,
+      int dayOfMonth,
+      int hour,
+      int minute,
+      int second,
+      int nanoOfSecond,
+      ZoneId zone) {
+    return null;
+  }
+
+  public int getYear() {
+    return 0;
+  }
+
+  public int getMonthValue() {
+    return 0;
+  }
+
+  public int getDayOfMonth() {
+    return 0;
+  }
+
+  public int getHour() {
+    return 0;
+  }
+
+  public int getMinute() {
+    return 0;
+  }
+
+  public int getSecond() {
+    return 0;
+  }
+
+  public int getNano() {
+    return 0;
+  }
+
+  public j$.time.ZoneId getZone() {
+    return null;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
index 7543fc5..8741c08 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/CoreLibDesugarTestBase.java
@@ -20,6 +20,8 @@
 import com.android.tools.r8.origin.Origin;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.google.common.collect.ImmutableList;
+import java.io.IOException;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.Arrays;
 import java.util.List;
@@ -103,6 +105,13 @@
     }
   }
 
+  protected static Path[] getAllFilesWithSuffixInDirectory(Path directory, String suffix)
+      throws IOException {
+    return Files.walk(directory)
+        .filter(path -> path.toString().endsWith(suffix))
+        .toArray(Path[]::new);
+  }
+
   protected KeepRuleConsumer createKeepRuleConsumer(TestParameters parameters) {
     if (requiresAnyCoreLibDesugaring(parameters)) {
       return new PresentKeepRuleConsumer();
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/APIConversionTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/APIConversionTest.java
similarity index 95%
rename from src/test/java/com/android/tools/r8/desugar/corelib/APIConversionTest.java
rename to src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/APIConversionTest.java
index 167ecf7..7a68a55 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/APIConversionTest.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/APIConversionTest.java
@@ -2,7 +2,7 @@
 // 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.corelib;
+package com.android.tools.r8.desugar.corelib.conversionTests;
 
 import static org.hamcrest.CoreMatchers.endsWith;
 import static org.hamcrest.core.StringContains.containsString;
@@ -10,6 +10,7 @@
 import com.android.tools.r8.TestParameters;
 import com.android.tools.r8.TestParametersCollection;
 import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.desugar.corelib.CoreLibDesugarTestBase;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.StringUtils;
 import java.util.Arrays;
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/APIConversionTestBase.java b/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/APIConversionTestBase.java
new file mode 100644
index 0000000..9d33872
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/APIConversionTestBase.java
@@ -0,0 +1,45 @@
+// 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.corelib.conversionTests;
+
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.desugar.corelib.CoreLibDesugarTestBase;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+
+public class APIConversionTestBase extends CoreLibDesugarTestBase {
+
+  private static final Path CONVERSION_FOLDER = Paths.get("src/test/desugaredLibraryConversions");
+
+  public Path[] getTimeConversionClasses() throws IOException {
+    File conversionFolder = temp.newFolder("conversions");
+    File stubsFolder = temp.newFolder("stubs");
+
+    // Compile the stubs to be able to compile the conversions.
+    ToolHelper.runJavac(
+        CfVm.JDK8,
+        null,
+        stubsFolder.toPath(),
+        getAllFilesWithSuffixInDirectory(CONVERSION_FOLDER.resolve("stubs/"), "java"));
+
+    // Compile the conversions using the stubs.
+    ArrayList<Path> classPath = new ArrayList<>();
+    classPath.add(stubsFolder.toPath());
+    ToolHelper.runJavac(
+        CfVm.JDK8,
+        classPath,
+        conversionFolder.toPath(),
+        getAllFilesWithSuffixInDirectory(CONVERSION_FOLDER.resolve("conversions"), "java"));
+
+    Path[] classes = getAllFilesWithSuffixInDirectory(conversionFolder.toPath(), "class");
+    assert classes.length > 0
+        : "Something went wrong during compilation, check the runJavac return value for debugging.";
+    return classes;
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/TimeConversionCompilationTest.java b/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/TimeConversionCompilationTest.java
new file mode 100644
index 0000000..db250a1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/conversionTests/TimeConversionCompilationTest.java
@@ -0,0 +1,44 @@
+// 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.corelib.conversionTests;
+
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
+import static junit.framework.TestCase.assertEquals;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.codeinspector.ClassSubject;
+import com.android.tools.r8.utils.codeinspector.CodeInspector;
+import java.nio.file.Path;
+import org.junit.Test;
+
+public class TimeConversionCompilationTest extends APIConversionTestBase {
+
+  @Test
+  public void testTime() throws Exception {
+    Path[] timeConversionClasses = getTimeConversionClasses();
+    testForD8()
+        .addProgramFiles(timeConversionClasses)
+        .setMinApi(AndroidApiLevel.O)
+        .compile()
+        .inspect(this::checkTimeConversionAPIs);
+  }
+
+  private void checkTimeConversionAPIs(CodeInspector inspector) {
+    ClassSubject clazz = inspector.clazz("com.android.tools.r8.conversion.TimeConversions");
+    assertThat(clazz, isPresent());
+    assertEquals(7, clazz.allMethods().size());
+    long countTo =
+        clazz.allMethods().stream()
+            .filter(m -> m.getMethod().method.name.toString().equals("to"))
+            .count();
+    assertEquals(3, countTo);
+    long countFrom =
+        clazz.allMethods().stream()
+            .filter(m -> m.getMethod().method.name.toString().equals("from"))
+            .count();
+    assertEquals(3, countFrom);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11CoreLibTestBase.java b/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11CoreLibTestBase.java
index c106bec..4be9077 100644
--- a/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11CoreLibTestBase.java
+++ b/src/test/java/com/android/tools/r8/desugar/corelib/corelibjdktests/Jdk11CoreLibTestBase.java
@@ -53,13 +53,6 @@
         .toArray(Path[]::new);
   }
 
-  protected static Path[] getAllFilesWithSuffixInDirectory(Path directory, String suffix)
-      throws IOException {
-    return Files.walk(directory)
-        .filter(path -> path.toString().endsWith(suffix))
-        .toArray(Path[]::new);
-  }
-
   protected static Path getSafeVarArgsFile() {
     return ANDROID_SAFE_VAR_ARGS_LOCATION;
   }