jdk/test/java/nio/file/Files/walkFileTree/FindTest.java
changeset 45471 91b94351a742
parent 9035 1255eb81cc2f
equal deleted inserted replaced
45470:fad095de1919 45471:91b94351a742
       
     1 /*
       
     2  * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 4313887 6907737
       
    27  * @summary Tests that walkFileTree is consistent with the native find program
       
    28  * @requires (os.family != "windows")
       
    29  * @library /test/lib
       
    30  * @build jdk.test.lib.Utils
       
    31  *        jdk.test.lib.Asserts
       
    32  *        jdk.test.lib.JDKToolFinder
       
    33  *        jdk.test.lib.JDKToolLauncher
       
    34  *        jdk.test.lib.Platform
       
    35  *        jdk.test.lib.process.*
       
    36  *        CreateFileTree
       
    37  * @run testng/othervm -Djava.io.tmpdir=. FindTest
       
    38  */
       
    39 
       
    40 import java.io.IOException;
       
    41 import java.nio.file.FileSystemLoopException;
       
    42 import java.nio.file.FileVisitOption;
       
    43 import java.nio.file.FileVisitResult;
       
    44 import java.nio.file.FileVisitor;
       
    45 import java.nio.file.Files;
       
    46 import java.nio.file.Path;
       
    47 import java.nio.file.attribute.BasicFileAttributes;
       
    48 import java.util.ArrayList;
       
    49 import java.util.Arrays;
       
    50 import java.util.HashSet;
       
    51 import java.util.List;
       
    52 import java.util.Random;
       
    53 import java.util.Set;
       
    54 import java.util.stream.Collectors;
       
    55 
       
    56 import jdk.test.lib.process.OutputAnalyzer;
       
    57 import jdk.test.lib.process.ProcessTools;
       
    58 
       
    59 import org.testng.annotations.BeforeClass;
       
    60 import org.testng.annotations.Test;
       
    61 
       
    62 import static org.testng.Assert.assertEquals;
       
    63 import static org.testng.Assert.assertTrue;
       
    64 
       
    65 public class FindTest {
       
    66 
       
    67     private static final Random rand = new Random();
       
    68     private static final boolean isAIX = System.getProperty("os.name").equals("AIX");
       
    69     private static Path top;
       
    70     private static String TOP;
       
    71 
       
    72     @BeforeClass
       
    73     public static void createFileTree() throws Exception {
       
    74         top = CreateFileTree.create();
       
    75         TOP = top.toAbsolutePath().toString();
       
    76     }
       
    77 
       
    78     @Test
       
    79     public void printTreeTest() throws Throwable {
       
    80         // print the file tree and compare output with find(1)
       
    81         assertOutputEquals(printFileTree(top), runFind("find", TOP));
       
    82     }
       
    83 
       
    84     @Test
       
    85     public void printTreeFollowLinkTest() throws Throwable {
       
    86         // print the file tree, following links, and compare output with find(1).
       
    87 
       
    88         // On AIX "find -follow" may core dump on recursive links without '-L'
       
    89         // see: http://www-01.ibm.com/support/docview.wss?uid=isg1IV28143
       
    90         String[] cmds = isAIX
       
    91                       ? new String[]{"find", "-L", TOP, "-follow"}
       
    92                       : new String[]{"find", TOP, "-follow"};
       
    93         OutputAnalyzer expected = runFind(cmds);
       
    94 
       
    95         // Some versions of find(1) output cycles (sym links to ancestor
       
    96         // directories), other versions do not. For that reason we run
       
    97         // PrintFileTree with the -printCycles option when the output without
       
    98         // this option differs to find(1).
       
    99         try {
       
   100             assertOutputEquals(printFileTree(top, "-follow"), expected);
       
   101         } catch (AssertionError x) {
       
   102             assertOutputEquals(printFileTree(top, "-follow", "-printCycles"), expected);
       
   103         }
       
   104     }
       
   105 
       
   106     private void assertOutputEquals(List<String> actual, OutputAnalyzer expected)
       
   107             throws IOException {
       
   108         List<String> expectedList = Arrays.asList(expected.getStdout()
       
   109                                           .split(System.lineSeparator()));
       
   110         assertEquals(actual.size(), expectedList.size());
       
   111         assertTrue(actual.removeAll(expectedList));
       
   112     }
       
   113 
       
   114     private OutputAnalyzer runFind(String... cmds) throws Throwable {
       
   115         return ProcessTools.executeCommand(cmds);
       
   116     }
       
   117 
       
   118     /**
       
   119      * Invokes Files.walkFileTree to traverse a file tree and prints
       
   120      * each of the directories and files. The -follow option causes symbolic
       
   121      * links to be followed and the -printCycles option will print links
       
   122      * where the target of the link is an ancestor directory.
       
   123      */
       
   124     private static List<String> printFileTree(Path dir, String... opts) throws Exception {
       
   125         List<Path> fileTreeList = new ArrayList<>();
       
   126 
       
   127         List<String> optsList = Arrays.asList(opts);
       
   128         boolean followLinks = optsList.contains("-follow");
       
   129         boolean reportCycles = optsList.contains("-printCycles");
       
   130 
       
   131         Set<FileVisitOption> options = new HashSet<>();
       
   132         if (followLinks)
       
   133             options.add(FileVisitOption.FOLLOW_LINKS);
       
   134 
       
   135         Files.walkFileTree(dir, options, Integer.MAX_VALUE, new FileVisitor<Path>() {
       
   136             @Override
       
   137             public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
       
   138                 fileTreeList.add(dir);
       
   139                 return FileVisitResult.CONTINUE;
       
   140             }
       
   141             @Override
       
   142             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
       
   143                 fileTreeList.add(file);
       
   144                 return FileVisitResult.CONTINUE;
       
   145             }
       
   146             @Override
       
   147             public FileVisitResult postVisitDirectory(Path dir, IOException exc)
       
   148                 throws IOException
       
   149             {
       
   150                 if (exc != null)
       
   151                     throw exc;
       
   152                 return FileVisitResult.CONTINUE;
       
   153             }
       
   154             @Override
       
   155             public FileVisitResult visitFileFailed(Path file, IOException exc)
       
   156                 throws IOException
       
   157             {
       
   158                 if (followLinks && (exc instanceof FileSystemLoopException)) {
       
   159                     if (reportCycles)
       
   160                         fileTreeList.add(file);
       
   161                     return FileVisitResult.CONTINUE;
       
   162                 } else {
       
   163                     throw exc;
       
   164                 }
       
   165             }
       
   166         });
       
   167 
       
   168         return fileTreeList.stream()
       
   169                            .map(f -> f.toAbsolutePath().toString())
       
   170                            .collect(Collectors.toCollection(ArrayList::new));
       
   171     }
       
   172 }