test/jdk/java/io/File/MaxPathLength.java
author dholmes
Wed, 06 Nov 2019 21:18:42 -0500
changeset 58956 9a0a5e70eeb2
parent 47216 71c04702a3d5
permissions -rw-r--r--
8233454: Test fails with assert(!is_init_completed(), "should only happen during init") after JDK-8229516 Reviewed-by: jiefu, dcubed

/*
 * Copyright (c) 2002, 2013, 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
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/* @test
   @bug 4759207 4403166 4165006 4403166 6182812 6274272 7160013
   @summary Test to see if win32 path length can be greater than 260
 */

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.DirectoryNotEmptyException;

public class MaxPathLength {
    private static String sep = File.separator;
    private static String pathComponent = sep +
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    private static String fileName =
                 "areallylongfilenamethatsforsur";
    private static boolean isWindows = false;

    private static final int MAX_LENGTH = 256;

    private static int counter = 0;

    public static void main(String[] args) throws Exception {
        String osName = System.getProperty("os.name");
        if (osName.startsWith("Windows")) {
            isWindows = true;
        }

        for (int i = 4; i < 7; i++) {
            String name = fileName;
            while (name.length() < MAX_LENGTH) {
                testLongPath (i, name, false);
                testLongPath (i, name, true);
                name = getNextName(name);
            }
        }

        // test long paths on windows
        // And these long pathes cannot be handled on Solaris and Mac platforms
        if (isWindows) {
            String name = fileName;
            while (name.length() < MAX_LENGTH) {
                testLongPath (20, name, false);
                testLongPath (20, name, true);
                name = getNextName(name);
            }
        }
    }

    private static String getNextName(String fName) {
        return (fName.length() < MAX_LENGTH/2) ? fName + fName
                                               : fName + "A";
    }

    static void testLongPath(int max, String fn,
                             boolean tryAbsolute) throws Exception {
        String[] created = new String[max];
        String pathString = ".";
        for (int i = 0; i < max -1; i++) {
            pathString = pathString + pathComponent + (counter++);
            created[max - 1 -i] = pathString;
        }

        File dirFile = new File(pathString);
        File f = new File(pathString + sep + fn);

        String tPath = f.getPath();
        if (tryAbsolute) {
            tPath = f.getCanonicalPath();
        }
        created[0] = tPath;

        //for getCanonicalPath testing on win32
        File fu = new File(pathString + sep + fn.toUpperCase());

        if (dirFile.exists()) {
            System.err.println("Warning: Test directory structure exists already!");
            return;
        }

        try {
            Files.createDirectories(dirFile.toPath());

            if (tryAbsolute)
                dirFile = new File(dirFile.getCanonicalPath());
            if (!dirFile.isDirectory())
                throw new RuntimeException ("File.isDirectory() failed");
            f = new File(tPath);
            if (!f.createNewFile()) {
                throw new RuntimeException ("File.createNewFile() failed");
            }

            if (!f.exists())
                throw new RuntimeException ("File.exists() failed");
            if (!f.isFile())
                throw new RuntimeException ("File.isFile() failed");
            if (!f.canRead())
                throw new RuntimeException ("File.canRead() failed");
            if (!f.canWrite())
                throw new RuntimeException ("File.canWrite() failed");

            if (!f.delete())
                throw new RuntimeException ("File.delete() failed");

            FileOutputStream fos = new FileOutputStream(f);
            fos.write(1);
            fos.close();

            if (f.length() != 1)
                throw new RuntimeException ("File.length() failed");
            long time = System.currentTimeMillis();
            if (!f.setLastModified(time))
                throw new RuntimeException ("File.setLastModified() failed");
            if (f.lastModified() == 0) {
                throw new RuntimeException ("File.lastModified() failed");
            }
            String[] list = dirFile.list();
            if (list == null || !fn.equals(list[0])) {
                throw new RuntimeException ("File.list() failed");
            }

            File[] flist = dirFile.listFiles();
            if (flist == null || !fn.equals(flist[0].getName()))
                throw new RuntimeException ("File.listFiles() failed");

            if (isWindows &&
                !fu.getCanonicalPath().equals(f.getCanonicalPath()))
                throw new RuntimeException ("getCanonicalPath() failed");

            char[] cc = tPath.toCharArray();
            cc[cc.length-1] = 'B';
            File nf = new File(new String(cc));
            if (!f.renameTo(nf)) {
                /*there is a known issue that renameTo fails if
                  (1)the path is a UNC path and
                  (2)the path length is bigger than 1092
                  so don't stop if above are true
                */
                String abPath = f.getAbsolutePath();
                if (!abPath.startsWith("\\\\") ||
                    abPath.length() < 1093) {
                    throw new RuntimeException ("File.renameTo() failed for lenth="
                                                + abPath.length());
                }
            } else {
                if (!nf.canRead())
                    throw new RuntimeException ("Renamed file is not readable");
                if (!nf.canWrite())
                    throw new RuntimeException ("Renamed file is not writable");
                if (nf.length() != 1)
                    throw new RuntimeException ("Renamed file's size is not correct");
                if (!nf.renameTo(f)) {
                    created[0] = nf.getPath();
                }
                /* add a script to test these two if we got a regression later
                if (!f.setReadOnly())
                    throw new RuntimeException ("File.setReadOnly() failed");
                f.deleteOnExit();
                */
            }
        } finally {
            // Clean up
            for (int i = 0; i < max; i++) {
                Path p = (new File(created[i])).toPath();
                try {
                    Files.deleteIfExists(p);
                    // Test if the file is really deleted and wait for 1 second at most
                    for (int j = 0; j < 10 && Files.exists(p); j++) {
                        Thread.sleep(100);
                    }
                } catch (DirectoryNotEmptyException ex) {
                    // Give up the clean-up, let jtreg handle it.
                    System.err.println("Dir, " + p + ", is not empty");
                    break;
                }
            }
        }
    }
}