1/*
2 * Copyright (c) 2001, 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/* @test
25 * @bug 4638365
26 * @key intermittent
27 * @summary Test FileChannel.transferFrom and transferTo for 4GB files
28 * @run testng/timeout=300 Transfer4GBFile
29 */
30
31import java.io.BufferedWriter;
32import java.io.File;
33import java.io.FileInputStream;
34import java.io.FileOutputStream;
35import java.io.IOException;
36import java.io.OutputStreamWriter;
37import java.io.PrintStream;
38import java.io.RandomAccessFile;
39import java.nio.ByteBuffer;
40import java.nio.channels.FileChannel;
41import java.nio.file.StandardOpenOption;
42import java.nio.file.FileAlreadyExistsException;
43import java.util.concurrent.TimeUnit;
44
45import org.testng.annotations.Test;
46
47public class Transfer4GBFile {
48
49    private static PrintStream err = System.err;
50    private static PrintStream out = System.out;
51
52    // Test transferTo with large file
53    @Test
54    public void xferTest04() throws Exception { // for bug 4638365
55        File source = File.createTempFile("blah", null);
56        source.deleteOnExit();
57        long testSize = ((long)Integer.MAX_VALUE) * 2;
58        initTestFile(source, 10);
59        RandomAccessFile raf = new RandomAccessFile(source, "rw");
60        FileChannel fc = raf.getChannel();
61        out.println("  Writing large file...");
62        long t0 = System.nanoTime();
63        fc.write(ByteBuffer.wrap("Use the source!".getBytes()), testSize - 40);
64        long t1 = System.nanoTime();
65        out.printf("  Wrote large file in %d ns (%d ms) %n",
66            t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
67
68        fc.close();
69        raf.close();
70
71        File sink = File.createTempFile("sink", null);
72        sink.deleteOnExit();
73
74        FileInputStream fis = new FileInputStream(source);
75        FileChannel sourceChannel = fis.getChannel();
76
77        raf = new RandomAccessFile(sink, "rw");
78        FileChannel sinkChannel = raf.getChannel();
79
80        long bytesWritten = sourceChannel.transferTo(testSize -40, 10,
81                                                     sinkChannel);
82        if (bytesWritten != 10) {
83            throw new RuntimeException("Transfer test 4 failed " +
84                                       bytesWritten);
85        }
86        sourceChannel.close();
87        sinkChannel.close();
88
89        source.delete();
90        sink.delete();
91    }
92
93    // Test transferFrom with large file
94    @Test
95    public void xferTest05() throws Exception { // for bug 4638365
96        // Create a source file & large sink file for the test
97        File source = File.createTempFile("blech", null);
98        source.deleteOnExit();
99        initTestFile(source, 100);
100
101        // Create the sink file as a sparse file if possible
102        File sink = null;
103        FileChannel fc = null;
104        while (fc == null) {
105            sink = File.createTempFile("sink", null);
106            // re-create as a sparse file
107            sink.delete();
108            try {
109                fc = FileChannel.open(sink.toPath(),
110                                      StandardOpenOption.CREATE_NEW,
111                                      StandardOpenOption.WRITE,
112                                      StandardOpenOption.SPARSE);
113            } catch (FileAlreadyExistsException ignore) {
114                // someone else got it
115            }
116        }
117        sink.deleteOnExit();
118
119        long testSize = ((long)Integer.MAX_VALUE) * 2;
120        try {
121            out.println("  Writing large file...");
122            long t0 = System.nanoTime();
123            fc.write(ByteBuffer.wrap("Use the source!".getBytes()),
124                     testSize - 40);
125            long t1 = System.nanoTime();
126            out.printf("  Wrote large file in %d ns (%d ms) %n",
127            t1 - t0, TimeUnit.NANOSECONDS.toMillis(t1 - t0));
128        } catch (IOException e) {
129            // Can't set up the test, abort it
130            err.println("xferTest05 was aborted.");
131            return;
132        } finally {
133            fc.close();
134        }
135
136        // Get new channels for the source and sink and attempt transfer
137        FileChannel sourceChannel = new FileInputStream(source).getChannel();
138        try {
139            FileChannel sinkChannel = new RandomAccessFile(sink, "rw").getChannel();
140            try {
141                long bytesWritten = sinkChannel.transferFrom(sourceChannel,
142                                                             testSize - 40, 10);
143                if (bytesWritten != 10) {
144                    throw new RuntimeException("Transfer test 5 failed " +
145                                               bytesWritten);
146                }
147            } finally {
148                sinkChannel.close();
149            }
150        } finally {
151            sourceChannel.close();
152        }
153
154        source.delete();
155        sink.delete();
156    }
157
158    /**
159     * Creates file blah of specified size in bytes.
160     */
161    private static void initTestFile(File blah, long size) throws Exception {
162        if (blah.exists())
163            blah.delete();
164        FileOutputStream fos = new FileOutputStream(blah);
165        BufferedWriter awriter
166            = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));
167
168        for(int i=0; i<size; i++) {
169            awriter.write("e");
170        }
171        awriter.flush();
172        awriter.close();
173    }
174}
175