LargeFileAvailable.java revision 6073:cea72c2bf071
1/*
2 * Copyright (c) 2010, 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 * @bug 6402006 7030573
27 * @summary Test if available returns correct value when reading
28 *          a large file.
29 */
30
31import java.io.*;
32import java.nio.ByteBuffer;
33import java.nio.channels.*;
34import java.nio.file.Files;
35import static java.nio.file.StandardOpenOption.*;
36
37public class LargeFileAvailable {
38    public static void main(String args[]) throws Exception {
39        // Create a temporary file in the current directory.
40        // Use it to check if we have 7G available for
41        // a large sparse file test. As a fallback use whatever
42        // space is available, so the test can proceed.
43        File file = File.createTempFile("largefile", null, new File("."));
44        long spaceavailable = file.getUsableSpace();
45        long filesize = Math.min(spaceavailable,  7405576182L);
46        if (spaceavailable == 0L) {
47            // A full disk is considered fatal.
48            throw new RuntimeException("No space available for temp file.");
49        }
50
51        createLargeFile(filesize, file);
52
53        try (FileInputStream fis = new FileInputStream(file)) {
54            if (file.length() != filesize) {
55                throw new RuntimeException("unexpected file size = "
56                                           + file.length());
57            }
58
59            long bigSkip = Math.min(filesize/2, 3110608882L);
60            long remaining = filesize;
61            remaining -= skipBytes(fis, bigSkip, remaining);
62            remaining -= skipBytes(fis, 10L, remaining);
63            remaining -= skipBytes(fis, bigSkip, remaining);
64            if (fis.available() != (int) remaining) {
65                 throw new RuntimeException("available() returns "
66                     + fis.available() + " but expected " + remaining);
67            }
68        } finally {
69            file.delete();
70        }
71    }
72
73    // Skip toSkip number of bytes and expect that the available() method
74    // returns avail number of bytes.
75    private static long skipBytes(InputStream is, long toSkip, long avail)
76            throws IOException {
77        long skip = is.skip(toSkip);
78        if (skip != toSkip) {
79            throw new RuntimeException("skip() returns " + skip
80                + " but expected " + toSkip);
81        }
82        long remaining = avail - skip;
83        int expected = remaining >= Integer.MAX_VALUE
84                           ? Integer.MAX_VALUE
85                           : (int) remaining;
86
87        System.out.println("Skipped " + skip + " bytes "
88            + " available() returns " + expected +
89            " remaining=" + remaining);
90        if (is.available() != expected) {
91            throw new RuntimeException("available() returns "
92                + is.available() + " but expected " + expected);
93        }
94        return skip;
95    }
96
97    private static void createLargeFile(long filesize,
98                                        File file) throws Exception {
99        // Recreate a large file as a sparse file if possible
100        Files.delete(file.toPath());
101
102        try (FileChannel fc =
103             FileChannel.open(file.toPath(),
104                              CREATE_NEW, WRITE, SPARSE)) {
105            ByteBuffer bb = ByteBuffer.allocate(1).put((byte)1);
106            bb.rewind();
107            int rc = fc.write(bb, filesize - 1);
108
109            if (rc != 1) {
110                throw new RuntimeException("Failed to write 1 byte"
111                                           + " to the large file");
112            }
113        }
114        return;
115    }
116}
117