Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/io/pathNames/General.java
38812 views
/*1* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24@summary Common definitions for general exhaustive pathname tests25@author Mark Reinhold26*/2728import java.io.*;29import java.util.*;30import java.nio.file.*;313233public class General {3435public static boolean debug = false;3637private static boolean win32 = (File.separatorChar == '\\');3839private static int gensymCounter = 0;4041protected static final String userDir = System.getProperty("user.dir");4243protected static String baseDir = null;44protected static String relative = null;4546/* Generate a filename unique to this run */47private static String gensym() {48return "x." + ++gensymCounter;49}5051/**52* Create files and folders in the test working directory.53* The purpose is to make sure the test will not go out of54* its user dir when walking the file tree.55*56* @param depth The number of directory levels to be created under57* the user directory. It should be the maximum value58* of the depths passed to checkNames method (including59* direct or indirect calling) in a whole test.60*/61protected static void initTestData(int depth) throws IOException {62File parent = new File(userDir);63for (int i = 0; i < depth; i++) {64File tmp = new File(parent, gensym());65tmp.createNewFile();66tmp = new File(parent, gensym());67if (tmp.mkdir())68parent = tmp;69else70throw new IOException("Fail to create directory, " + tmp);71}72baseDir = parent.getAbsolutePath();73relative = baseDir.substring(userDir.length() + 1);74}7576/**77* Find a file in the given subdirectory, or descend into further78* subdirectories, if any, if no file is found here. Return null if no79* file can be found anywhere beneath the given subdirectory.80* @param dir Directory at which we started81* @param subdir Subdirectory that we're exploring82* @param dl Listing of subdirectory83*/84private static String findSomeFile(String dir, String subdir, String[] dl) {85for (int i = 0; i < dl.length; i++) {86File f = new File(subdir, dl[i]);87File df = new File(dir, f.getPath());88if (Files.isRegularFile(df.toPath(), LinkOption.NOFOLLOW_LINKS)) {89return f.getPath();90}91}92for (int i = 0; i < dl.length; i++) {93File f = (subdir.length() == 0) ? new File(dl[i])94: new File(subdir, dl[i]);95File df = new File(dir, f.getPath());96if (Files.isDirectory(df.toPath(), LinkOption.NOFOLLOW_LINKS)) {97String[] dl2 = df.list();98if (dl2 != null) {99String ff = findSomeFile(dir, f.getPath(), dl2);100if (ff != null) return ff;101}102}103}104return null;105}106107108/**109* Construct a string that names a file in the given directory. If create110* is true, then create a file if none is found, and throw an exception if111* that is not possible; otherwise, return null if no file can be found.112*/113private static String findSomeFile(String dir, boolean create) {114File d = new File(dir);115String[] dl = d.list();116if (dl == null) {117throw new RuntimeException("Can't list " + dir);118}119for (int i = 0; i < dl.length; i++) {120File f = new File(dir, dl[i]);121if (Files.isRegularFile(f.toPath(), LinkOption.NOFOLLOW_LINKS)) {122return dl[i];123}124}125String f = findSomeFile(dir, "", dl);126if (f != null) {127return f;128}129if (create) {130File nf = new File(d, gensym());131OutputStream os;132try {133os = new FileOutputStream(nf);134os.close();135} catch (IOException x) {136throw new RuntimeException("Can't create a file in " + dir);137}138return nf.getName();139}140return null;141}142143144/**145* Construct a string that names a subdirectory of the given directory.146* If create is true, then create a subdirectory if none is found, and147* throw an exception if that is not possible; otherwise, return null if148* no subdirectory can be found.149*/150private static String findSomeDir(String dir, boolean create) {151File d = new File(dir);152String[] dl = d.list();153if (dl == null) {154throw new RuntimeException("Can't list " + dir);155}156for (int i = 0; i < dl.length; i++) {157File f = new File(d, dl[i]);158if (Files.isDirectory(f.toPath(), LinkOption.NOFOLLOW_LINKS)) {159String[] dl2 = f.list();160if (dl2 == null || dl2.length >= 250) {161/* Heuristic to avoid scanning huge directories */162continue;163}164return dl[i];165}166}167if (create) {168File sd = new File(d, gensym());169if (sd.mkdir()) return sd.getName();170}171return null;172}173174175/** Construct a string that does not name a file in the given directory */176private static String findNon(String dir) {177File d = new File(dir);178String[] x = new String[] { "foo", "bar", "baz" };179for (int i = 0; i < x.length; i++) {180File f = new File(d, x[i]);181if (!f.exists()) {182return x[i];183}184}185for (int i = 0; i < 1024; i++) {186String n = "xx" + Integer.toString(i);187File f = new File(d, n);188if (!f.exists()) {189return n;190}191}192throw new RuntimeException("Can't find a non-existent file in " + dir);193}194195196/** Ensure that the named file does not exist */197public static void ensureNon(String fn) {198if ((new File(fn)).exists()) {199throw new RuntimeException("Test path " + fn + " exists");200}201}202203204/** Tell whether the given character is a "slash" on this platform */205private static boolean isSlash(char x) {206if (x == File.separatorChar) return true;207if (win32 && (x == '/')) return true;208return false;209}210211212/**213* Trim trailing slashes from the given string, but leave singleton slashes214* alone (they denote root directories)215*/216private static String trimTrailingSlashes(String s) {217int n = s.length();218if (n == 0) return s;219n--;220while ((n > 0) && isSlash(s.charAt(n))) {221if ((n >= 1) && s.charAt(n - 1) == ':') break;222n--;223}224return s.substring(0, n + 1);225}226227228/** Concatenate two paths, trimming slashes as needed */229private static String pathConcat(String a, String b) {230if (a.length() == 0) return b;231if (b.length() == 0) return a;232if (isSlash(a.charAt(a.length() - 1))233|| isSlash(b.charAt(0))234|| (win32 && (a.charAt(a.length() - 1) == ':'))) {235return a + b;236} else {237return a + File.separatorChar + b;238}239}240241242243/** Hash table of input pathnames, used to detect duplicates */244private static Hashtable<String, String> checked = new Hashtable<>();245246/**247* Check the given pathname. Its canonical pathname should be the given248* answer. If the path names a file that exists and is readable, then249* FileInputStream and RandomAccessFile should both be able to open it.250*/251public static void check(String answer, String path) throws IOException {252String ans = trimTrailingSlashes(answer);253if (path.length() == 0) return;254if (checked.get(path) != null) {255System.err.println("DUP " + path);256return;257}258checked.put(path, path);259260String cpath;261try {262File f = new File(path);263cpath = f.getCanonicalPath();264if (f.exists() && f.isFile() && f.canRead()) {265InputStream in = new FileInputStream(path);266in.close();267RandomAccessFile raf = new RandomAccessFile(path, "r");268raf.close();269}270} catch (IOException x) {271System.err.println(ans + " <-- " + path + " ==> " + x);272if (debug) return;273else throw x;274}275if (cpath.equals(ans)) {276System.err.println(ans + " <== " + path);277} else {278System.err.println(ans + " <-- " + path + " ==> " + cpath + " MISMATCH");279if (!debug) {280throw new RuntimeException("Mismatch: " + path + " ==> " + cpath +281", should be " + ans);282}283}284}285286287288/*289* The following three mutually-recursive methods generate and check a tree290* of filenames of arbitrary depth. Each method has (at least) these291* arguments:292*293* int depth Remaining tree depth294* boolean create Controls whether test files and directories295* will be created as needed296* String ans Expected answer for the check method (above)297* String ask Input pathname to be passed to the check method298*/299300301/** Check a single slash case, plus its children */302private static void checkSlash(int depth, boolean create,303String ans, String ask, String slash)304throws Exception305{306check(ans, ask + slash);307checkNames(depth, create,308ans.endsWith(File.separator) ? ans : ans + File.separator,309ask + slash);310}311312313/** Check slash cases for the given ask string */314public static void checkSlashes(int depth, boolean create,315String ans, String ask)316throws Exception317{318check(ans, ask);319if (depth == 0) return;320321checkSlash(depth, create, ans, ask, "/");322checkSlash(depth, create, ans, ask, "//");323checkSlash(depth, create, ans, ask, "///");324if (win32) {325checkSlash(depth, create, ans, ask, "\\");326checkSlash(depth, create, ans, ask, "\\\\");327checkSlash(depth, create, ans, ask, "\\/");328checkSlash(depth, create, ans, ask, "/\\");329checkSlash(depth, create, ans, ask, "\\\\\\");330}331}332333334/** Check name cases for the given ask string */335public static void checkNames(int depth, boolean create,336String ans, String ask)337throws Exception338{339int d = depth - 1;340File f = new File(ans);341String n;342343/* Normal name */344if (f.exists()) {345if (Files.isDirectory(f.toPath(), LinkOption.NOFOLLOW_LINKS) && f.list() != null) {346if ((n = findSomeFile(ans, create)) != null)347checkSlashes(d, create, ans + n, ask + n);348if ((n = findSomeDir(ans, create)) != null)349checkSlashes(d, create, ans + n, ask + n);350}351n = findNon(ans);352checkSlashes(d, create, ans + n, ask + n);353} else {354n = "foo" + depth;355checkSlashes(d, create, ans + n, ask + n);356}357358/* "." */359checkSlashes(d, create, trimTrailingSlashes(ans), ask + ".");360361/* ".." */362if ((n = f.getParent()) != null) {363String n2;364if (win32365&& ((n2 = f.getParentFile().getParent()) != null)366&& n2.equals("\\\\")) {367/* Win32 resolves \\foo\bar\.. to \\foo\bar */368checkSlashes(d, create, ans, ask + "..");369} else {370checkSlashes(d, create, n, ask + "..");371}372}373else {374if (win32)375checkSlashes(d, create, ans, ask + "..");376else {377// Fix for 4237875. We must ensure that we are sufficiently378// deep in the path hierarchy to test parents this high up379File thisPath = new File(ask);380File nextPath = new File(ask + "..");381if (!thisPath.getCanonicalPath().equals(nextPath.getCanonicalPath()))382checkSlashes(d, create, ans + "..", ask + "..");383}384}385}386}387388389