Desugared library: test create methods in Files

- Document differences to fix
- Fix Conversion of FileAttribute<Set<PosixPermission>>

Change-Id: I157ee87f459e32bea04ea2d420f751c47f8c0e3c
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
index 089a293..b02dc00 100644
--- a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriteDescription.java
@@ -28,24 +28,23 @@
           "j$/nio/file/spi/FileTypeDetector",
           "j$/nio/file/Path",
           "j$/nio/file/WatchEvent",
-          "j$/nio/file/OpenOption");
+          "j$/nio/file/OpenOption",
+          "j$/nio/file/attribute/FileAttribute");
 
-  static Map<String, String> getJavaWrapConvertOwnerMap() {
-    return computeConvertOwnerMap("$Wrapper");
-  }
-
-  static Map<String, String> getJ$WrapConvertOwnerMap() {
-    return computeConvertOwnerMap("$VivifiedWrapper");
-  }
-
-  private static HashMap<String, String> computeConvertOwnerMap(String suffix) {
+  static Map<String, String> getWrapConvertOwnerMap() {
     HashMap<String, String> map = new HashMap<>();
     for (String theEnum : ENUM_WRAP_CONVERT_OWNER) {
       map.put(theEnum, theEnum + "$EnumConversion");
+      map.put(withJavaPrefix(theEnum), theEnum + "$EnumConversion");
     }
     for (String owner : WRAP_CONVERT_OWNER) {
-      map.put(owner, owner + suffix);
+      map.put(withJavaPrefix(owner), owner + "$Wrapper");
+      map.put(owner, owner + "$VivifiedWrapper");
     }
     return map;
   }
+
+  private static String withJavaPrefix(String descriptor) {
+    return "java" + descriptor.substring(2);
+  }
 }
diff --git a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java
index 0848c09..95a5ecc 100644
--- a/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java
+++ b/buildSrc/src/main/java/desugaredlibrary/CustomConversionAsmRewriter.java
@@ -39,10 +39,8 @@
   }
 
   private final CustomConversionVersion legacy;
-  private final Map<String, String> javaWrapConvertOwnerMap =
-      CustomConversionAsmRewriteDescription.getJavaWrapConvertOwnerMap();
-  private final Map<String, String> j$WrapConvertOwnerMap =
-      CustomConversionAsmRewriteDescription.getJ$WrapConvertOwnerMap();
+  private final Map<String, String> wrapConvertOwnerMap =
+      CustomConversionAsmRewriteDescription.getWrapConvertOwnerMap();
 
   public static void generateJars(Path jar, Path outputDirectory) throws IOException {
     for (CustomConversionVersion version : CustomConversionVersion.values()) {
@@ -148,30 +146,14 @@
 
     private void convertInvoke(int opcode, String owner, String descriptor, boolean isInterface) {
       String firstArg = extractFirstArg(descriptor);
-      assert sameBaseName(firstArg, owner);
-      if (!javaWrapConvertOwnerMap.containsKey(owner)
-          || !j$WrapConvertOwnerMap.containsKey(owner)
+      if (!wrapConvertOwnerMap.containsKey(firstArg)
           || !(firstArg.startsWith("java") || firstArg.startsWith("j$"))) {
         throw new RuntimeException(
             "Cannot transform wrap_convert method for " + firstArg + " (owner: " + owner + ")");
       }
-      if (firstArg.startsWith("java")) {
-        String newOwner = javaWrapConvertOwnerMap.get(owner);
-        super.visitMethodInsn(opcode, newOwner, CONVERT, descriptor, isInterface);
-        return;
-      }
-      assert firstArg.startsWith("j$");
-      String newOwner = j$WrapConvertOwnerMap.get(owner);
+      String newOwner = wrapConvertOwnerMap.get(firstArg);
       super.visitMethodInsn(opcode, newOwner, CONVERT, descriptor, isInterface);
     }
 
-    private boolean sameBaseName(String firstArg, String owner) {
-      assert owner.startsWith("j$");
-      if (firstArg.equals(owner)) {
-        return true;
-      }
-      String javaName = owner.replace("j$", "java");
-      return firstArg.equals(javaName);
-    }
   }
 }
diff --git a/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributeView.java
index 774cf2c..7d2612f 100644
--- a/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributeView.java
+++ b/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributeView.java
@@ -5,13 +5,4 @@
 package j$.nio.file.attribute;
 
 public class BasicFileAttributeView extends FileAttributeView {
-  public static java.nio.file.attribute.BasicFileAttributeView wrap_convert(
-      j$.nio.file.attribute.BasicFileAttributeView fileAttributeView) {
-    return null;
-  }
-
-  public static j$.nio.file.attribute.BasicFileAttributeView wrap_convert(
-      java.nio.file.attribute.BasicFileAttributeView fileAttributeView) {
-    return null;
-  }
 }
diff --git a/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributes.java b/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributes.java
index dd91a95..69b0ca6 100644
--- a/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributes.java
+++ b/src/library_desugar/java/j$/nio/file/attribute/BasicFileAttributes.java
@@ -5,13 +5,4 @@
 package j$.nio.file.attribute;
 
 public class BasicFileAttributes {
-  public static java.nio.file.attribute.BasicFileAttributes wrap_convert(
-      j$.nio.file.attribute.BasicFileAttributes fileAttributes) {
-    return null;
-  }
-
-  public static j$.nio.file.attribute.BasicFileAttributes wrap_convert(
-      java.nio.file.attribute.BasicFileAttributes fileAttributes) {
-    return null;
-  }
 }
diff --git a/src/library_desugar/java/j$/nio/file/attribute/FileAttribute.java b/src/library_desugar/java/j$/nio/file/attribute/FileAttribute.java
new file mode 100644
index 0000000..b971b05
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/FileAttribute.java
@@ -0,0 +1,12 @@
+// Copyright (c) 2022, 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$.nio.file.attribute;
+
+public interface FileAttribute<T> {
+
+  String name();
+
+  T value();
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/FileAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/FileAttributeView.java
index 34046eb3..df33474 100644
--- a/src/library_desugar/java/j$/nio/file/attribute/FileAttributeView.java
+++ b/src/library_desugar/java/j$/nio/file/attribute/FileAttributeView.java
@@ -5,13 +5,4 @@
 package j$.nio.file.attribute;
 
 public class FileAttributeView {
-  public static java.nio.file.attribute.FileAttributeView wrap_convert(
-      j$.nio.file.attribute.FileAttributeView fileAttributeView) {
-    return null;
-  }
-
-  public static j$.nio.file.attribute.FileAttributeView wrap_convert(
-      java.nio.file.attribute.FileAttributeView fileAttributeView) {
-    return null;
-  }
 }
diff --git a/src/library_desugar/java/j$/nio/file/attribute/FileAttributeWrapperMethods.java b/src/library_desugar/java/j$/nio/file/attribute/FileAttributeWrapperMethods.java
new file mode 100644
index 0000000..dfff944
--- /dev/null
+++ b/src/library_desugar/java/j$/nio/file/attribute/FileAttributeWrapperMethods.java
@@ -0,0 +1,18 @@
+// Copyright (c) 2022, 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$.nio.file.attribute;
+
+public class FileAttributeWrapperMethods {
+
+  public static java.nio.file.attribute.FileAttribute wrap_convert(
+      j$.nio.file.attribute.FileAttribute fileAttribute) {
+    return null;
+  }
+
+  public static j$.nio.file.attribute.FileAttribute wrap_convert(
+      java.nio.file.attribute.FileAttribute fileAttribute) {
+    return null;
+  }
+}
diff --git a/src/library_desugar/java/j$/nio/file/attribute/FileOwnerAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/FileOwnerAttributeView.java
index 34a637d..cbce1b4 100644
--- a/src/library_desugar/java/j$/nio/file/attribute/FileOwnerAttributeView.java
+++ b/src/library_desugar/java/j$/nio/file/attribute/FileOwnerAttributeView.java
@@ -5,13 +5,4 @@
 package j$.nio.file.attribute;
 
 public class FileOwnerAttributeView extends FileAttributeView {
-  public static java.nio.file.attribute.FileOwnerAttributeView wrap_convert(
-      j$.nio.file.attribute.FileOwnerAttributeView fileAttributeView) {
-    return null;
-  }
-
-  public static j$.nio.file.attribute.FileOwnerAttributeView wrap_convert(
-      java.nio.file.attribute.FileOwnerAttributeView fileAttributeView) {
-    return null;
-  }
 }
diff --git a/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributeView.java b/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributeView.java
index bb24cb7..04f4f04 100644
--- a/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributeView.java
+++ b/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributeView.java
@@ -5,13 +5,4 @@
 package j$.nio.file.attribute;
 
 public class PosixFileAttributeView extends FileAttributeView {
-  public static java.nio.file.attribute.PosixFileAttributeView wrap_convert(
-      j$.nio.file.attribute.PosixFileAttributeView fileAttributeView) {
-    return null;
-  }
-
-  public static j$.nio.file.attribute.PosixFileAttributeView wrap_convert(
-      java.nio.file.attribute.PosixFileAttributeView fileAttributeView) {
-    return null;
-  }
 }
diff --git a/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributes.java b/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributes.java
index 5e61814..d6e9796 100644
--- a/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributes.java
+++ b/src/library_desugar/java/j$/nio/file/attribute/PosixFileAttributes.java
@@ -5,13 +5,4 @@
 package j$.nio.file.attribute;
 
 public class PosixFileAttributes extends BasicFileAttributes {
-  public static java.nio.file.attribute.PosixFileAttributes wrap_convert(
-      j$.nio.file.attribute.PosixFileAttributes fileAttributes) {
-    return null;
-  }
-
-  public static j$.nio.file.attribute.PosixFileAttributes wrap_convert(
-      java.nio.file.attribute.PosixFileAttributes fileAttributes) {
-    return null;
-  }
 }
diff --git a/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java b/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
index c895d52..18c575f 100644
--- a/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
+++ b/src/library_desugar/java/java/nio/file/attribute/FileAttributeConversions.java
@@ -4,6 +4,10 @@
 
 package java.nio.file.attribute;
 
+import java.nio.file.FileApiFlips;
+import java.util.Collections;
+import java.util.Set;
+
 public class FileAttributeConversions {
 
   public static java.nio.file.attribute.FileTime convert(j$.nio.file.attribute.FileTime fileTime) {
@@ -20,4 +24,58 @@
     return j$.nio.file.attribute.FileTime.fromMillis(fileTime.toMillis());
   }
 
+  /** A FileAttribute usually holds an immutable set of non-null posix permissions. */
+  public static java.nio.file.attribute.FileAttribute<?> convert(
+      j$.nio.file.attribute.FileAttribute<?> attribute) {
+    if (attribute == null) {
+      return null;
+    }
+    if (isPosixPermissionAttributes(attribute.value())) {
+      return new java.nio.file.attribute.FileAttribute<Object>() {
+        public String name() {
+          return "posix:permissions";
+        }
+
+        public Object value() {
+          return Collections.unmodifiableSet(
+              FileApiFlips.flipPosixPermissionSet((Set<?>) attribute.value()));
+        }
+      };
+    }
+    return j$.nio.file.attribute.FileAttributeWrapperMethods.wrap_convert(attribute);
+  }
+
+  public static j$.nio.file.attribute.FileAttribute<?> convert(
+      java.nio.file.attribute.FileAttribute<?> attribute) {
+    if (attribute == null) {
+      return null;
+    }
+    if (isPosixPermissionAttributes(attribute.value())) {
+      return new j$.nio.file.attribute.FileAttribute<Object>() {
+        public String name() {
+          return "posix:permissions";
+        }
+
+        public Object value() {
+          return Collections.unmodifiableSet(
+              FileApiFlips.flipPosixPermissionSet((Set<?>) attribute.value()));
+        }
+      };
+    }
+    return j$.nio.file.attribute.FileAttributeWrapperMethods.wrap_convert(attribute);
+  }
+
+  private static boolean isPosixPermissionAttributes(Object value) {
+    if (value instanceof java.util.Set) {
+      Set<?> set = (java.util.Set<?>) value;
+      if (!set.isEmpty()) {
+        Object guineaPig = set.iterator().next();
+        if (guineaPig instanceof java.nio.file.attribute.PosixFilePermission
+            || guineaPig instanceof j$.nio.file.attribute.PosixFilePermission) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
 }
diff --git a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
index c102e5e..dff0eac 100644
--- a/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
+++ b/src/library_desugar/jdk11/desugar_jdk_libs_nio.json
@@ -257,7 +257,6 @@
         "java.nio.file.CopyOption",
         "java.nio.file.StandardCopyOption",
         "java.nio.file.attribute.GroupPrincipal",
-        "java.nio.file.attribute.FileAttribute",
         "java.nio.file.attribute.UserPrincipal",
         "java.nio.file.FileStore",
         "java.nio.file.attribute.FileStoreAttributeView",
@@ -265,6 +264,7 @@
         "java.nio.file.attribute.BasicFileAttributes",
         "java.nio.file.attribute.DosFileAttributes",
         "java.nio.file.attribute.PosixFileAttributes",
+        "java.nio.file.attribute.FileAttribute",
         "java.nio.file.attribute.FileAttributeView",
         "java.nio.file.attribute.FileOwnerAttributeView",
         "java.nio.file.attribute.DosFileAttributeView",
@@ -279,7 +279,8 @@
         ]
       },
       "custom_conversion": {
-        "java.nio.file.attribute.FileTime": "java.nio.file.attribute.FileAttributeConversions"
+        "java.nio.file.attribute.FileTime": "java.nio.file.attribute.FileAttributeConversions",
+        "java.nio.file.attribute.FileAttribute": "java.nio.file.attribute.FileAttributeConversions"
       }
     },
     {
diff --git a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
index 314d657..cae75f2 100644
--- a/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
+++ b/src/main/java/com/android/tools/r8/ir/desugar/desugaredlibrary/humanspecification/HumanRewritingFlags.java
@@ -15,13 +15,11 @@
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
-import com.google.common.collect.Sets.SetView;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Set;
-import java.util.stream.Collectors;
 
 public class HumanRewritingFlags {
 
@@ -510,7 +508,6 @@
     }
 
     public HumanRewritingFlags build() {
-      validate();
       return new HumanRewritingFlags(
           ImmutableMap.copyOf(rewritePrefix),
           ImmutableSet.copyOf(dontRewritePrefix),
@@ -533,19 +530,5 @@
           ImmutableMap.copyOf(amendLibraryMethod),
           ImmutableMap.copyOf(amendLibraryField));
     }
-
-    private void validate() {
-      SetView<DexType> dups =
-          Sets.intersection(customConversions.keySet(), wrapperConversions.keySet());
-      if (!dups.isEmpty()) {
-        throw reporter.fatalError(
-            new StringDiagnostic(
-                "Invalid desugared library configuration. "
-                    + "Duplicate types in custom conversions and wrapper conversions: "
-                    + String.join(
-                        ", ", dups.stream().map(DexType::toString).collect(Collectors.toSet())),
-                origin));
-      }
-    }
   }
 }
diff --git a/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FilesCreateTest.java b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FilesCreateTest.java
new file mode 100644
index 0000000..39d85b1
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/desugar/desugaredlibrary/jdk11/FilesCreateTest.java
@@ -0,0 +1,203 @@
+// Copyright (c) 2022, 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.desugaredlibrary.jdk11;
+
+import static com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification.DEFAULT_SPECIFICATIONS;
+import static com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification.JDK11_PATH;
+
+import com.android.tools.r8.TestParameters;
+import com.android.tools.r8.TestRuntime.CfVm;
+import com.android.tools.r8.ToolHelper.DexVm.Version;
+import com.android.tools.r8.desugar.desugaredlibrary.DesugaredLibraryTestBase;
+import com.android.tools.r8.desugar.desugaredlibrary.test.CompilationSpecification;
+import com.android.tools.r8.desugar.desugaredlibrary.test.LibraryDesugaringSpecification;
+import com.android.tools.r8.utils.StringUtils;
+import com.google.common.collect.ImmutableList;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.LinkOption;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileAttribute;
+import java.nio.file.attribute.PosixFilePermission;
+import java.nio.file.attribute.PosixFilePermissions;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class FilesCreateTest extends DesugaredLibraryTestBase {
+
+  private static final String EXPECTED_RESULT =
+      StringUtils.lines(
+          "ind3f class java.nio.file.NoSuchFileException",
+          "ind4f class java.nio.file.NoSuchFileException",
+          "ind5f class java.nio.file.NoSuchFileException",
+          "ind6f class java.nio.file.NoSuchFileException",
+          "true",
+          "true",
+          "notExisting1class java.nio.file.NoSuchFileException",
+          "false",
+          "false");
+  private static final String EXPECTED_RESULT_DESUGARING =
+      StringUtils.lines(
+          "ind5f class java.io.FileNotFoundException",
+          "ind6f class java.io.FileNotFoundException",
+          "true",
+          "true",
+          "notExisting1class java.io.IOException",
+          "false",
+          "true",
+          "ind4f/dir",
+          "ind4f",
+          "ind3f/dir",
+          "ind3f");
+  private static final String EXPECTED_FILES =
+      StringUtils.lines(
+          "ind2s/dir", "ind2s", "ind1s/dir", "ind1s", "f4.txt", "f3.txt", "dir2s", "dir1s");
+
+  private final TestParameters parameters;
+  private final LibraryDesugaringSpecification libraryDesugaringSpecification;
+  private final CompilationSpecification compilationSpecification;
+
+  @Parameters(name = "{0}, spec: {1}, {2}")
+  public static List<Object[]> data() {
+    return buildParameters(
+        // Skip Android 4.4.4 due to missing libjavacrypto.
+        getTestParameters()
+            .withCfRuntime(CfVm.JDK11)
+            .withDexRuntime(Version.V4_0_4)
+            .withDexRuntimesStartingFromIncluding(Version.V5_1_1)
+            .withAllApiLevels()
+            .build(),
+        ImmutableList.of(JDK11_PATH),
+        DEFAULT_SPECIFICATIONS);
+  }
+
+  public FilesCreateTest(
+      TestParameters parameters,
+      LibraryDesugaringSpecification libraryDesugaringSpecification,
+      CompilationSpecification compilationSpecification) {
+    this.parameters = parameters;
+    this.libraryDesugaringSpecification = libraryDesugaringSpecification;
+    this.compilationSpecification = compilationSpecification;
+  }
+
+  @Test
+  public void test() throws Throwable {
+    if (parameters.isCfRuntime()) {
+      // Reference runtime, we use Jdk 11 since this is Jdk 11 desugared library, not that Jdk 8
+      // behaves differently on this test.
+      Assume.assumeTrue(parameters.isCfRuntime(CfVm.JDK11));
+      testForJvm()
+          .addInnerClasses(getClass())
+          .run(parameters.getRuntime(), TestClass.class)
+          .assertSuccessWithOutput(getExpectedResult());
+      return;
+    }
+    Assume.assumeFalse(
+        "The command mkdir fails on Android 7.0, we need to investigate if this is an emulator"
+            + "issue or a real issue.",
+        parameters.getDexRuntimeVersion().equals(Version.V7_0_0));
+    testForDesugaredLibrary(parameters, libraryDesugaringSpecification, compilationSpecification)
+        .addInnerClasses(getClass())
+        .addKeepMainRule(TestClass.class)
+        .compile()
+        .withArt6Plus64BitsLib()
+        .run(parameters.getRuntime(), TestClass.class)
+        .assertSuccessWithOutput(getExpectedResult());
+  }
+
+  private String getExpectedResult() {
+    if (parameters.isCfRuntime()) {
+      return EXPECTED_RESULT + EXPECTED_FILES;
+    }
+    return (libraryDesugaringSpecification.usesPlatformFileSystem(parameters)
+            ? EXPECTED_RESULT
+            : EXPECTED_RESULT_DESUGARING)
+        // We cannot print on such devices due to conversions errors.
+        + ((libraryDesugaringSpecification.usesPlatformFileSystem(parameters)
+                && libraryDesugaringSpecification.hasNioFileDesugaring(parameters))
+            ? ""
+            : EXPECTED_FILES);
+  }
+
+  public static class TestClass {
+
+    public static void main(String[] args) throws Throwable {
+      Path root = Files.createTempDirectory("tmp_test");
+      Files.createDirectories(root.resolve("ind1s/dir"));
+      Files.createDirectories(root.resolve("ind2s/dir"), getFileAttribute());
+      try {
+        Files.createDirectory(root.resolve("ind3f/dir"));
+      } catch (Throwable t) {
+        System.out.println("ind3f " + t.getClass());
+      }
+      try {
+        Files.createDirectory(root.resolve("ind4f/dir"), getFileAttribute());
+      } catch (Throwable t) {
+        System.out.println("ind4f " + t.getClass());
+      }
+      Files.createDirectory(root.resolve("dir1s"));
+      Files.createDirectory(root.resolve("dir2s"), getFileAttribute());
+      try {
+        Files.createFile(root.resolve("ind5f/f.txt"));
+      } catch (Throwable t) {
+        System.out.println("ind5f " + t.getClass());
+      }
+      try {
+        Files.createFile(root.resolve("ind6f/f.txt"), getFileAttribute());
+      } catch (Throwable t) {
+        System.out.println("ind6f " + t.getClass());
+      }
+      Files.createFile(root.resolve("f1.txt"));
+      Files.createFile(root.resolve("f2.txt"), getFileAttribute());
+
+      System.out.println(Files.exists(root.resolve("f1.txt")));
+      System.out.println(Files.exists(root.resolve("f1.txt"), LinkOption.NOFOLLOW_LINKS));
+
+      Files.delete(root.resolve("f1.txt"));
+      try {
+        Files.delete(root.resolve("notExisting1.txt"));
+      } catch (Throwable t) {
+        System.out.println("notExisting1" + t.getClass());
+      }
+      Files.deleteIfExists(root.resolve("f2.txt"));
+      Files.deleteIfExists(root.resolve("notExisting2.txt"));
+
+      System.out.println(Files.exists(root.resolve("f1.txt")));
+      System.out.println(Files.exists(root.resolve("f1.txt"), LinkOption.NOFOLLOW_LINKS));
+
+      // Recreate for the final print.
+      Files.createFile(root.resolve("f3.txt"));
+      Files.createFile(root.resolve("f4.txt"), getFileAttribute());
+
+      // Clear the temp directory.
+      // We need to fix Files#walk on high Api levels.
+      try {
+        Files.walk(root)
+            .sorted(Comparator.reverseOrder())
+            .map(
+                f -> {
+                  if (f != root) {
+                    System.out.println(f.subpath(2, f.getNameCount()));
+                  }
+                  return f.toFile();
+                })
+            .forEach(File::delete);
+      } catch (Throwable t) {
+
+      }
+    }
+
+    public static FileAttribute<Set<PosixFilePermission>> getFileAttribute() {
+      return PosixFilePermissions.asFileAttribute(PosixFilePermissions.fromString("rwxr-xr-x"));
+    }
+  }
+}