Reproduce issue with not filtering out META-INF/version classes

Bug: b/281774632
Change-Id: I4ed8047a399831a057253a36a57657766baf62ea
diff --git a/src/main/java/com/android/tools/r8/utils/FileUtils.java b/src/main/java/com/android/tools/r8/utils/FileUtils.java
index b8b8286..13c9f3a 100644
--- a/src/main/java/com/android/tools/r8/utils/FileUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/FileUtils.java
@@ -100,12 +100,14 @@
     return Files.readAllLines(file);
   }
 
-  public static void writeTextFile(Path file, List<String> lines) throws IOException {
+  public static Path writeTextFile(Path file, List<String> lines) throws IOException {
     Files.write(file, lines);
+    return file;
   }
 
-  public static void writeTextFile(Path file, String... lines) throws IOException {
+  public static Path writeTextFile(Path file, String... lines) throws IOException {
     Files.write(file, Arrays.asList(lines));
+    return file;
   }
 
   public static Path validateOutputFile(Path path, Reporter reporter) {
diff --git a/src/main/java/com/android/tools/r8/utils/ZipUtils.java b/src/main/java/com/android/tools/r8/utils/ZipUtils.java
index 43b1b02..3e066a4 100644
--- a/src/main/java/com/android/tools/r8/utils/ZipUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/ZipUtils.java
@@ -257,6 +257,14 @@
       return stream;
     }
 
+    public ZipBuilder addFile(String name, Path file) throws IOException {
+      ZipEntry zipEntry = new ZipEntry(name);
+      stream.putNextEntry(zipEntry);
+      Files.copy(file, stream);
+      stream.closeEntry();
+      return this;
+    }
+
     public ZipBuilder addFilesRelative(Path basePath, Collection<Path> filesToAdd)
         throws IOException {
       for (Path path : filesToAdd) {
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index 5c73e63..334b2bf 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -1583,7 +1583,7 @@
   public static ProcessResult forkR8WithJavaOptions(
       Path dir, List<String> javaOptions, String... args) throws IOException {
     String r8Jar = R8_JAR.toAbsolutePath().toString();
-    return forkJavaWithJarAndJavaOptions(dir, r8Jar, Arrays.asList(args), javaOptions);
+    return forkJavaWithJarAndJavaOptions(dir, javaOptions, r8Jar, Arrays.asList(args));
   }
 
   public static ProcessResult forkR8Jar(Path dir, String... args)
@@ -1612,11 +1612,11 @@
 
   private static ProcessResult forkJavaWithJar(Path dir, String jarPath, List<String> args)
       throws IOException {
-    return forkJavaWithJarAndJavaOptions(dir, jarPath, args, ImmutableList.of());
+    return forkJavaWithJarAndJavaOptions(dir, ImmutableList.of(), jarPath, args);
   }
 
   private static ProcessResult forkJavaWithJarAndJavaOptions(
-      Path dir, String jarPath, List<String> args, List<String> javaOptions) throws IOException {
+      Path dir, List<String> javaOptions, String jarPath, List<String> args) throws IOException {
     List<String> command =
         new ImmutableList.Builder<String>()
             .add(getJavaExecutable())
@@ -1628,6 +1628,19 @@
     return runProcess(new ProcessBuilder(command).directory(dir.toFile()));
   }
 
+  public static ProcessResult forkJavaWithJavaOptions(
+      Path dir, List<String> javaOptions, Class clazz, List<String> args) throws IOException {
+    List<String> command =
+        new ImmutableList.Builder<String>()
+            .add(getJavaExecutable())
+            .addAll(javaOptions)
+            .add("-cp")
+            .add(System.getProperty("java.class.path"))
+            .add(clazz.getCanonicalName())
+            .addAll(args)
+            .build();
+    return runProcess(new ProcessBuilder(command).directory(dir.toFile()));
+  }
 
   private static ProcessResult forkJava(Path dir, Class clazz, List<String> args)
       throws IOException {
diff --git a/src/test/java/com/android/tools/r8/locale/TurkishLocaleMultiReleaseJarTest.java b/src/test/java/com/android/tools/r8/locale/TurkishLocaleMultiReleaseJarTest.java
new file mode 100644
index 0000000..9dd0da6
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/locale/TurkishLocaleMultiReleaseJarTest.java
@@ -0,0 +1,109 @@
+// Copyright (c) 2023, 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.locale;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.D8;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class TurkishLocaleMultiReleaseJarTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testD8() throws Exception {
+    parameters.assumeDexRuntime();
+    Path workingDir = temp.getRoot().toPath();
+    ProcessResult result =
+        ToolHelper.forkJavaWithJavaOptions(
+            workingDir,
+            ImmutableList.of("-Duser.language=tr"),
+            D8.class,
+            ImmutableList.of(
+                "--min-api",
+                Integer.toString(parameters.getApiLevel().getLevel()),
+                "--lib",
+                ToolHelper.getAndroidJar(AndroidApiLevel.U).toAbsolutePath().toString(),
+                buildMultiReleaseJarWithUpperCaseMetaInf(workingDir).toString()));
+    checkResult(result);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    Path workingDir = temp.getRoot().toPath();
+    ImmutableList.Builder<String> builder = ImmutableList.builder();
+    builder.add(
+        "--lib",
+        ToolHelper.getAndroidJar(AndroidApiLevel.U).toAbsolutePath().toString(),
+        "--pg-conf",
+        FileUtils.writeTextFile(temp.newFile("test.pro").toPath(), "-keep class * { *; }")
+            .toString(),
+        buildMultiReleaseJarWithUpperCaseMetaInf(workingDir).toString());
+    if (parameters.isCfRuntime()) {
+      builder.add("--classfile");
+    } else {
+      builder.add("--min-api", Integer.toString(parameters.getApiLevel().getLevel()));
+    }
+
+    ProcessResult result =
+        ToolHelper.forkJavaWithJavaOptions(
+            workingDir, ImmutableList.of("-Duser.language=tr"), R8.class, builder.build());
+    checkResult(result);
+  }
+
+  private Path buildMultiReleaseJarWithUpperCaseMetaInf(Path dir) throws Exception {
+    // Compiler will to check String.toLowerCase() of zip entries.
+    Path jar = dir.resolve("test.jar");
+    ZipBuilder.builder(jar)
+        .addFilesRelative(
+            ToolHelper.getClassPathForTests(), ToolHelper.getClassFileForTestClass(TestClass.class))
+        .addFile(
+            Paths.get("META-INF/versions/9")
+                .resolve(
+                    ToolHelper.getClassPathForTests()
+                        .relativize(ToolHelper.getClassFileForTestClass(TestClass.class)))
+                .toString(),
+            ToolHelper.getClassFileForTestClass(TestClass.class))
+        .build();
+    return jar;
+  }
+
+  private void checkResult(ProcessResult result) {
+    assertEquals(1, result.exitCode);
+    assertThat(
+        result.stderr,
+        containsString("Type " + TestClass.class.getTypeName() + " is defined multiple times"));
+  }
+
+  static class TestClass {
+    public static void main(String[] args) {
+      System.out.println("Hello, world!");
+    }
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/locale/TurkishLocaleZipFileInputTest.java b/src/test/java/com/android/tools/r8/locale/TurkishLocaleZipFileInputTest.java
new file mode 100644
index 0000000..14a330e
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/locale/TurkishLocaleZipFileInputTest.java
@@ -0,0 +1,104 @@
+// Copyright (c) 2023, 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.locale;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import com.android.tools.r8.D8;
+import com.android.tools.r8.R8;
+import com.android.tools.r8.TestBase;
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestParametersCollection;
+import com.android.tools.r8.ToolHelper;
+import com.android.tools.r8.ToolHelper.ProcessResult;
+import com.android.tools.r8.utils.AndroidApiLevel;
+import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.ZipUtils.ZipBuilder;
+import com.google.common.collect.ImmutableList;
+import java.nio.file.Path;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class TurkishLocaleZipFileInputTest extends TestBase {
+
+  @Parameter() public TestParameters parameters;
+
+  @Parameters(name = "{0}")
+  public static TestParametersCollection data() {
+    return getTestParameters().withAllRuntimesAndApiLevels().build();
+  }
+
+  @Test
+  public void testD8() throws Exception {
+    parameters.assumeDexRuntime();
+    Path workingDir = temp.getRoot().toPath();
+    ProcessResult result =
+        ToolHelper.forkJavaWithJavaOptions(
+            workingDir,
+            // See b/281774632 for context.
+            ImmutableList.of("-Duser.language=tr"),
+            D8.class,
+            ImmutableList.of(
+                "--min-api",
+                Integer.toString(parameters.getApiLevel().getLevel()),
+                "--lib",
+                ToolHelper.getAndroidJar(AndroidApiLevel.U).toAbsolutePath().toString(),
+                buildZipWithUpperCaseExtension(workingDir).toString()));
+    checkResult(result);
+  }
+
+  @Test
+  public void testR8() throws Exception {
+    Path workingDir = temp.getRoot().toPath();
+    ImmutableList.Builder<String> builder = ImmutableList.builder();
+    builder.add(
+        "--lib",
+        ToolHelper.getAndroidJar(AndroidApiLevel.U).toAbsolutePath().toString(),
+        "--pg-conf",
+        FileUtils.writeTextFile(temp.newFile("test.pro").toPath(), "-keep class * { *; }")
+            .toString(),
+        buildZipWithUpperCaseExtension(workingDir).toString());
+    if (parameters.isCfRuntime()) {
+      builder.add("--classfile");
+    } else {
+      builder.add("--min-api", Integer.toString(parameters.getApiLevel().getLevel()));
+    }
+
+    ProcessResult result =
+        ToolHelper.forkJavaWithJavaOptions(
+            workingDir,
+            // See b/281774632 for context.
+            ImmutableList.of("-Duser.language=tr"),
+            R8.class,
+            builder.build());
+    checkResult(result);
+  }
+
+  private Path buildZipWithUpperCaseExtension(Path dir) throws Exception {
+    // Compiler will to check String.toLowerCase() of file extensions.
+    Path jar = dir.resolve("test.ZIP");
+    ZipBuilder.builder(jar)
+        .addFilesRelative(
+            ToolHelper.getClassPathForTests(), ToolHelper.getClassFileForTestClass(TestClass.class))
+        .build();
+    return jar;
+  }
+
+  private void checkResult(ProcessResult result) {
+    assertEquals(1, result.exitCode);
+    assertThat(result.stderr, containsString("Unsupported source file type"));
+  }
+
+  static class TestClass {
+    public static void main(String[] args) {
+      System.out.println("Hello, world!");
+    }
+  }
+}