8224617: (fs) java/nio/file/FileStore/Basic.java found filesystem twice
authorbpb
Thu, 06 Jun 2019 14:13:59 -0700
changeset 55271 5c7c3662c386
parent 55270 759acbfb9fde
child 55272 1b17d09e3e05
8224617: (fs) java/nio/file/FileStore/Basic.java found filesystem twice Reviewed-by: alanb
test/jdk/java/nio/file/FileStore/Basic.java
test/lib/jdk/test/lib/util/FileUtils.java
--- a/test/jdk/java/nio/file/FileStore/Basic.java	Thu Jun 06 13:42:41 2019 -0700
+++ b/test/jdk/java/nio/file/FileStore/Basic.java	Thu Jun 06 14:13:59 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -115,7 +115,7 @@
         /**
          * Test: Enumerate all FileStores
          */
-        if (FileUtils.areFileSystemsAccessible()) {
+        if (FileUtils.areAllMountPointsAccessible()) {
             FileStore prev = null;
             for (FileStore store: FileSystems.getDefault().getFileStores()) {
                 System.out.format("%s (name=%s type=%s)\n", store, store.name(),
--- a/test/lib/jdk/test/lib/util/FileUtils.java	Thu Jun 06 13:42:41 2019 -0700
+++ b/test/lib/jdk/test/lib/util/FileUtils.java	Thu Jun 06 14:13:59 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 import jdk.test.lib.Platform;
 
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.io.UncheckedIOException;
@@ -45,6 +47,8 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -238,6 +242,93 @@
     }
 
     /**
+     * Checks whether all file systems are accessible. This is performed
+     * by checking free disk space on all mounted file systems via a
+     * separate, spawned process. File systems are considered to be
+     * accessible if this process completes successfully before a given
+     * fixed duration has elapsed.
+     *
+     * @implNote On Unix this executes the {@code df} command in a separate
+     * process and on Windows always returns {@code true}.
+     *
+     * @return whether file systems appear to be accessible
+     *
+     * @throws RuntimeException if there are duplicate mount points or some
+     * other execution problem occurs
+     */
+    public static boolean areAllMountPointsAccessible() {
+        final AtomicBoolean areMountPointsOK = new AtomicBoolean(true);
+        if (!IS_WINDOWS) {
+            Thread thr = new Thread(() -> {
+                try {
+                    Process proc = new ProcessBuilder("df").start();
+                    BufferedReader reader = new BufferedReader
+                        (new InputStreamReader(proc.getInputStream()));
+                    // Skip the first line as it is the "df" output header.
+                    if (reader.readLine() != null ) {
+                        String prevMountPoint = null, mountPoint = null;
+                        while ((mountPoint = reader.readLine()) != null) {
+                            if (prevMountPoint != null &&
+                                mountPoint.equals(prevMountPoint)) {
+                                throw new RuntimeException
+                                    ("System configuration error: " +
+                                    "duplicate mount point " + mountPoint +
+                                    " detected");
+                            }
+                            prevMountPoint = mountPoint;
+                        }
+                    }
+
+                    try {
+                        proc.waitFor(90, TimeUnit.SECONDS);
+                    } catch (InterruptedException ignored) {
+                    }
+                    try {
+                        int exitValue = proc.exitValue();
+                        if (exitValue != 0) {
+                            System.err.printf("df process exited with %d != 0%n",
+                                exitValue);
+                            areMountPointsOK.set(false);
+                        }
+                    } catch (IllegalThreadStateException ignored) {
+                        System.err.println("df command apparently hung");
+                        areMountPointsOK.set(false);
+                    }
+                } catch (IOException ioe) {
+                    throw new RuntimeException(ioe);
+                };
+            });
+
+            final AtomicReference throwableReference =
+                new AtomicReference<Throwable>();
+            thr.setUncaughtExceptionHandler(
+                new Thread.UncaughtExceptionHandler() {
+                    public void uncaughtException(Thread t, Throwable e) {
+                        throwableReference.set(e);
+                    }
+                });
+
+            thr.start();
+            try {
+                thr.join(120*1000L);
+            } catch (InterruptedException ie) {
+                throw new RuntimeException(ie);
+            }
+
+            Throwable uncaughtException = (Throwable)throwableReference.get();
+            if (uncaughtException != null) {
+                throw new RuntimeException(uncaughtException);
+            }
+
+            if (thr.isAlive()) {
+                throw new RuntimeException("df thread did not join in time");
+            }
+        }
+
+        return areMountPointsOK.get();
+    }
+
+    /**
      * List the open file descriptors (if supported by the 'lsof' command).
      * @param ps a printStream to send the output to
      * @throws UncheckedIOException if an error occurs