1 /*
   2  * Copyright (c) 2012, 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  * @summary function test for Files.list()/find()/walk()/lines()
  27  * @library /sqeutil
  28  * @(#) FilesLambdaTest.java
  29  * @author Tristan Yan
  30  * @run testng/othervm FilesLambdaTest
  31  */
  32 
  33 import java.io.BufferedReader;
  34 import java.io.BufferedWriter;
  35 import java.io.IOException;
  36 import java.nio.charset.Charset;
  37 import java.nio.file.FileVisitResult;
  38 import java.nio.file.Files;
  39 import java.nio.file.LinkOption;
  40 import java.nio.file.NotDirectoryException;
  41 import java.nio.file.Path;
  42 import java.nio.file.Paths;
  43 import java.nio.file.SimpleFileVisitor;
  44 import java.nio.file.attribute.BasicFileAttributes;
  45 import java.util.ArrayList;
  46 import java.util.Collections;
  47 import java.util.List;
  48 import java.util.Random;
  49 import java.util.function.Consumer;
  50 import java.util.stream.Collectors;
  51 import java.util.stream.Stream;
  52 import static org.testng.Assert.*;
  53 import org.testng.annotations.AfterClass;
  54 import org.testng.annotations.BeforeClass;
  55 import org.testng.annotations.Test;
  56 
  57 public class FilesLambdaTest {
  58     private static final Random rand = new Random(System.nanoTime());
  59 
  60     private static final String TEST_SRC = System.getProperty("test.src");
  61 
  62     private static final String ROOT_NAME = "FilesLambdaTest" + System.nanoTime();
  63 
  64     private static final String LINES_TEST_FILE = "lines" +  System.nanoTime();
  65 
  66     private static final int MAX_FILES_NUMBER = 1 << 6;
  67 
  68     private static final Charset UTF8 = Charset.forName("UTF-8");
  69 
  70     private final static int MIN_LEN = 1 << 2;
  71 
  72     private final static int MAX_LEN = 1 << 8;
  73 
  74     private final static int LINES_NUM = 1 << 8;
  75 
  76     private static final String[][] folders = {
  77         {"A01"},
  78         {"A01", "AA02"},
  79         {"A01", "AB02"},
  80         {"A01", "AC02"},
  81         {"B01"},
  82         {"B01", "BA02"},
  83         {"B01", "BA02", "BAA03"},
  84         {"B01", "BA02", "BAA03", "BAAA04", "BAAAA05", "BAAAAA06", "BAAAAAA07",
  85          "BAAAAAAA08", "BAAAAAAAA09", "BAAAAAAAAA10", "BAAAAAAAAAA11"},
  86         {"C01"},
  87         {"C01", "CA02"},
  88         {"C01", "CD02"},
  89         {"D01", "DA02", "DAA03", "DAAA04", "DAAAA05", "DAAAAA06", "DAAAAAA07"},
  90         {"E01"},
  91         {"E01", "EA02"},
  92         {"E01", "EB02", "EBB03"},
  93         {"E01", "EC02", "ECC03", "ECCC04"},
  94         {"E01", "ED02", "EDD03", "EDDD04", "EDDDD05"},
  95         {"E01", "EE02", "EEE03", "EEEE04", "EEEEE05", "EEEEEE06"},
  96         {"E01", "EF02", "EFF03", "EFFF04", "EFFFF05", "EFFFFF06"},
  97         {"E01", "EG02", "EGG03", "EGGG04", "EGGGG05", "EGGGGG06", "EGGGGGG07"},
  98         {"E01", "EH02", "EHH03", "EHHH04", "EHHHH05", "EHHHHH06", "EHHHHHH07",
  99          "EHHHHHHH08"},
 100         {"E01", "EI02", "EII03", "EIII04", "EIIII05", "EIIIII06", "EIIIIII07",
 101          "EIIIIIII08", "EIIIIIIII09"},
 102         {"E01", "EJ02", "EJJ03", "EJJJ04", "EJJJJ05", "EJJJJJ06", "EJJJJJJ07",
 103          "EJJJJJJJ08", "EJJJJJJJJ09", "EJJJJJJJJJ10"},
 104         {"E01", "EK02", "EKK03", "EKKK04", "EKKKK05", "EKKKKK06", "EKKKKKK07",
 105          "EKKKKKKK08", "EKKKKKKKK09", "EKKKKKKKKK10", "EJJJJJJJJJJ11"}
 106     };
 107 
 108     private Path root;
 109 
 110     private Path testFile;
 111 
 112     private Path notExistPath;
 113 
 114     final Consumer<Path> writeReverseWithLink = path -> {
 115         int filesCount = rand.nextInt(MAX_FILES_NUMBER);
 116         for(int count = 0; count < filesCount; count++) {
 117             String fileName = String.valueOf(rand.nextLong());
 118             Path file = path.resolve(fileName);
 119             String linkName = String.valueOf(rand.nextLong());
 120             Path link = path.resolve(linkName);
 121             try (BufferedWriter writer
 122                     = Files.newBufferedWriter(Files.createFile(file), UTF8)) {
 123                 writer.write(new StringBuilder(fileName).reverse().toString(),
 124                         0, fileName.length());
 125                 Files.createSymbolicLink(link, file);
 126             } catch (IOException ex) {
 127                 throw new RuntimeException(ex);
 128             }
 129         }
 130     };
 131 
 132     @BeforeClass
 133     public void filesSetUp() throws IOException {
 134         List<Path> paths = new ArrayList<>();
 135         root = Paths.get(TEST_SRC, ROOT_NAME);
 136         paths.add(Files.createDirectory(root));
 137         for(int i = 0; i < folders.length; i++ ) {
 138             String[] toBeCreated = folders[i];
 139             Path folder = Paths.get(ROOT_NAME, toBeCreated);
 140             paths.add(Files.createDirectories(folder));
 141         }
 142         paths.forEach(writeReverseWithLink);
 143 
 144         testFile = Paths.get(LINES_TEST_FILE);
 145         try (BufferedWriter writer
 146                 = Files.newBufferedWriter(Files.createFile(testFile), UTF8)) {
 147             for(int i = 0; i< LINES_NUM; i++) {
 148                 String line = StringUtilities.randomString(MAX_LEN, MIN_LEN);
 149                 writer.write(line, 0, line.length());
 150             }
 151         } catch (IOException ex) {
 152             throw new RuntimeException(ex);
 153         }
 154 
 155         String NOT_EXIST = "NOT_EXIST";
 156         notExistPath = Paths.get(TEST_SRC, NOT_EXIST);
 157     }
 158 
 159     @AfterClass
 160     public void filesTearDown() throws IOException {
 161         if(root != null) {
 162             Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
 163                 @Override
 164                 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
 165                     throws IOException {
 166                     Files.delete(file);
 167                     return FileVisitResult.CONTINUE;
 168                 }
 169                 @Override
 170                 public FileVisitResult postVisitDirectory(Path dir, IOException exc)
 171                     throws IOException{
 172                     Files.delete(dir);
 173                     return FileVisitResult.CONTINUE;
 174                 }
 175             });
 176         }
 177         if(testFile != null) {
 178             Files.delete(testFile);
 179         }
 180     }
 181 
 182     @Test
 183     public void testFilesList() throws IOException {
 184         checkFilesList(root);
 185     }
 186 
 187     @Test
 188     public void testWalk() throws IOException{
 189         String[] dir = folders[rand.nextInt(folders.length)];
 190         Path walkFolder = Paths.get(ROOT_NAME, dir);
 191         final int maxDepth = rand.nextInt(11);
 192         List<Path> expectedFullFileList = new ArrayList<>();
 193         List<Path> expectedMaxDepthFileList = new ArrayList<>();
 194 
 195         List<Path> expectedFullSymList = new ArrayList<>();
 196         List<Path> expectedMaxDepthSymList = new ArrayList<>();
 197 
 198         List<Path> expectedFullDirList = new ArrayList<>();
 199         List<Path> expectedMaxDepthDirList = new ArrayList<>();
 200 
 201         Files.walkFileTree(walkFolder, new SimpleFileVisitor<Path>() {
 202             @Override
 203             public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
 204                 throws IOException {
 205                 if (walkFolder.relativize(file).getNameCount() <= maxDepth) {
 206                     expectedMaxDepthFileList.add(file);
 207                     if(Files.isSymbolicLink(file)) {
 208                         expectedMaxDepthSymList.add(file);
 209                     }
 210                 }
 211                 expectedFullFileList.add(file);
 212                 if(Files.isSymbolicLink(file)) {
 213                     expectedFullSymList.add(file);
 214                 }
 215                 return FileVisitResult.CONTINUE;
 216             }
 217             @Override
 218             public FileVisitResult postVisitDirectory(Path dir, IOException exc)
 219                 throws IOException{
 220                 if (walkFolder.relativize(dir).getNameCount() <= maxDepth
 221                         || walkFolder.equals(dir)) {
 222                     expectedMaxDepthDirList.add(dir);
 223                 }
 224                 expectedFullDirList.add(dir);
 225                 return FileVisitResult.CONTINUE;
 226             }
 227         });
 228         Collections.sort(expectedFullFileList);
 229         Collections.sort(expectedMaxDepthFileList);
 230         Collections.sort(expectedFullSymList);
 231         Collections.sort(expectedMaxDepthSymList);
 232         Collections.sort(expectedFullDirList);
 233         Collections.sort(expectedMaxDepthDirList);
 234 
 235         assertEquals(expectedMaxDepthFileList,
 236                 Files.walk(walkFolder, maxDepth).filter(p -> !Files.isDirectory(p)).
 237                 sorted().collect(Collectors.toList()));
 238         assertEquals(expectedMaxDepthSymList,
 239                 Files.walk(walkFolder, maxDepth).filter(p -> Files.isSymbolicLink(p)).
 240                 sorted().collect(Collectors.toList()));
 241         assertEquals(expectedMaxDepthDirList,
 242                 Files.walk(walkFolder, maxDepth).filter(p -> Files.isDirectory(p)).
 243                 sorted().collect(Collectors.toList()));
 244         assertEquals(expectedFullFileList,
 245                 Files.walk(walkFolder).filter(p -> !Files.isDirectory(p)).
 246                 sorted().collect(Collectors.toList()));
 247         assertEquals(expectedFullSymList,
 248                 Files.walk(walkFolder).filter(p -> Files.isSymbolicLink(p)).
 249                 sorted().collect(Collectors.toList()));
 250         assertEquals(expectedFullDirList,
 251                 Files.walk(walkFolder).filter(p -> Files.isDirectory(p)).
 252                 sorted().collect(Collectors.toList()));
 253     }
 254 
 255     @Test
 256     public void testFind() throws IOException{
 257         String[] dir = folders[rand.nextInt(folders.length)];
 258         Path walkFolder = Paths.get(ROOT_NAME, dir);
 259         String walkFoderName = dir[dir.length - 1];
 260 
 261         int walkFolderDepth = Integer.parseInt(walkFoderName.substring(walkFoderName.length() - 2));
 262         int maxDepth = rand.nextInt(11);
 263         Stream<Path> stream
 264                 = Files.find(walkFolder, maxDepth, (p,bfa) -> Files.isSymbolicLink(p));
 265         stream.forEach(p -> {
 266             assertTrue(Files.isSymbolicLink(p));
 267             assertFalse(Files.isDirectory(p));
 268             assertFalse(Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS));
 269             String parentName = p.getParent().toFile().getName();
 270             int depth = Integer.parseInt(parentName.substring(parentName.length() - 2));
 271             assertTrue(depth - walkFolderDepth < maxDepth);
 272         });
 273 
 274         assertEquals(Files.find(walkFolder, maxDepth, (p,bfa) -> Files.isSymbolicLink(p)).toArray(),
 275                 Files.find(walkFolder, maxDepth, (p,bfa) -> bfa.isSymbolicLink()).toArray());
 276     }
 277 
 278     @Test
 279     public void testLines() throws IOException{
 280         Stream<String> stream = Files.lines(testFile, UTF8);
 281         List<String> lines = Files.readAllLines(testFile, UTF8);
 282         assertEquals(lines, stream.collect(Collectors.toList()));
 283     }
 284 
 285     @Test(expectedExceptions = IOException.class)
 286     public void testListNoReadAccess() throws IOException{
 287         Files.list(notExistPath);
 288     }
 289 
 290     @Test(expectedExceptions = NotDirectoryException.class)
 291     public void testListNotDirectory() throws IOException{
 292         Files.list(testFile);
 293     }
 294 
 295     @Test(expectedExceptions = IOException.class)
 296     public void testFindNoExist() throws IOException{
 297         Files.find(notExistPath, Integer.MAX_VALUE, (p, bfa) -> true);
 298     }
 299 
 300     @Test(expectedExceptions = IOException.class)
 301     public void testLinesNoExist() throws IOException{
 302         Files.lines(notExistPath, UTF8);
 303     }
 304 
 305     @Test(expectedExceptions = IOException.class)
 306     public void testWalkNoExist() throws IOException{
 307         Files.walk(notExistPath);
 308     }
 309 
 310     @Test(expectedExceptions = IOException.class)
 311     public void testWalkNoExistWithDepth() throws IOException{
 312         Files.walk(notExistPath, Integer.MAX_VALUE);
 313     }
 314 
 315     public void checkFilesList(Path checkPath){
 316         try {
 317             assert(Files.isDirectory(checkPath));
 318             Files.list(checkPath).filter(p -> Files.isDirectory(p)).forEach(p -> checkFilesList(p));
 319             assertEquals(Files.list(checkPath).filter(p -> Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS)).count(),
 320                     Files.list(checkPath).filter(p -> Files.isSymbolicLink(p)).count());
 321             assertTrue(Files.list(checkPath).filter(p -> Files.isRegularFile(p, LinkOption.NOFOLLOW_LINKS)).allMatch(file -> contentRevered(file)));
 322         } catch (IOException ex) {
 323             throw new RuntimeException(ex);
 324         }
 325     }
 326 
 327     private boolean contentRevered(Path path) {
 328         try (BufferedReader reader = Files.newBufferedReader(path, UTF8)){
 329             String fileName = path.getName(path.getNameCount() -1).toString();
 330             String reversed = new StringBuilder(reader.readLine()).reverse().toString();
 331             return (fileName.equals(reversed));
 332         } catch (IOException ex) {
 333             throw new RuntimeException(ex);
 334         }
 335     }
 336 }