Path: blob/master/test/jdk/java/nio/channels/FileChannel/Transfer2GPlus.java
66646 views
/*1* Copyright (c) 2021, 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* @test25* @bug 827130826* @summary Verify that transferTo() copies more than Integer.MAX_VALUE bytes27* @library .. /test/lib28* @build jdk.test.lib.Platform29* @run main Transfer2GPlus30*/3132import java.io.File;33import java.io.DataOutputStream;34import java.io.FileOutputStream;35import java.io.IOException;36import java.io.RandomAccessFile;37import java.nio.ByteBuffer;38import java.nio.channels.Channels;39import java.nio.channels.FileChannel;40import java.nio.channels.WritableByteChannel;41import java.nio.file.Files;42import java.nio.file.Path;43import java.nio.file.StandardOpenOption;44import java.util.Arrays;45import java.util.Random;46import jdk.test.lib.Platform;4748public class Transfer2GPlus {49private static final long BASE = (long)Integer.MAX_VALUE;50private static final int EXTRA = 1024;51private static final long LENGTH = BASE + EXTRA;5253public static void main(String[] args) throws IOException {54Path src = Files.createTempFile("src", ".dat");55src.toFile().deleteOnExit();56byte[] b = createSrcFile(src);57testToFileChannel(src, b);58testToWritableByteChannel(src, b);59}6061// Create a file of size LENGTH with EXTRA random bytes at offset BASE.62private static byte[] createSrcFile(Path src)63throws IOException {64RandomAccessFile raf = new RandomAccessFile(src.toString(), "rw");65raf.setLength(LENGTH);66raf.seek(BASE);67Random r = new Random(System.nanoTime());68byte[] b = new byte[EXTRA];69r.nextBytes(b);70raf.write(b);71return b;72}7374// Exercises transferToDirectly() on Linux and transferToTrustedChannel()75// on macOS and Windows.76private static void testToFileChannel(Path src, byte[] expected)77throws IOException {78Path dst = Files.createTempFile("dst", ".dat");79dst.toFile().deleteOnExit();80try (FileChannel srcCh = FileChannel.open(src)) {81try (FileChannel dstCh = FileChannel.open(dst,82StandardOpenOption.READ, StandardOpenOption.WRITE)) {83long total = 0L;84if ((total = srcCh.transferTo(0, LENGTH, dstCh)) < LENGTH) {85if (!Platform.isLinux())86throw new RuntimeException("Transfer too small: " + total);8788// If this point is reached we're on Linux which cannot89// transfer all LENGTH bytes in one call to sendfile(2),90// so loop to get the rest.91do {92long n = srcCh.transferTo(total, LENGTH, dstCh);93if (n == 0)94break;95total += n;96} while (total < LENGTH);97}9899if (dstCh.size() < LENGTH)100throw new RuntimeException("Target file too small: " +101dstCh.size() + " < " + LENGTH);102103System.out.println("Transferred " + total + " bytes");104105dstCh.position(BASE);106ByteBuffer bb = ByteBuffer.allocate(EXTRA);107dstCh.read(bb);108if (!Arrays.equals(bb.array(), expected))109throw new RuntimeException("Unexpected values");110}111}112}113114// Exercises transferToArbitraryChannel() on all platforms.115private static void testToWritableByteChannel(Path src, byte[] expected)116throws IOException {117File file = File.createTempFile("dst", ".dat");118file.deleteOnExit();119try (FileChannel srcCh = FileChannel.open(src)) {120// The FileOutputStream is wrapped so that newChannel() does not121// return a FileChannelImpl and so make a faster path be taken.122try (DataOutputStream stream =123new DataOutputStream(new FileOutputStream(file))) {124try (WritableByteChannel wbc = Channels.newChannel(stream)) {125long n;126if ((n = srcCh.transferTo(0, LENGTH, wbc)) < LENGTH)127throw new RuntimeException("Too few bytes transferred: " +128n + " < " + LENGTH);129130System.out.println("Transferred " + n + " bytes");131132RandomAccessFile raf = new RandomAccessFile(file, "r");133raf.seek(BASE);134byte[] b = new byte[EXTRA];135raf.read(b);136if (!Arrays.equals(b, expected))137throw new RuntimeException("Unexpected values");138}139}140}141}142}143144145