Path: blob/master/test/jdk/java/nio/channels/FileChannel/Transfers.java
41154 views
/*1* Copyright (c) 2002, 2017, 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/* @test24* @summary Comprehensive test for FileChannel.transfer{From,To}25* @bug 470812026* @author Mark Reinhold27* @run main/timeout=300 Transfers28*/2930import java.io.*;31import java.nio.*;32import java.nio.channels.*;33import java.util.*;343536public class Transfers {3738static PrintStream out = System.out;3940private static class Failure41extends RuntimeException42{4344Failure(Exception x) {45super(x);46}4748Failure(String s) {49super(s);50}5152}535455// -- Writing and reading random bytes --5657private static void writeBytes(byte[] ba, FileChannel fc,58int off, int len)59throws IOException60{61fc.position(off);62if (fc.write(ByteBuffer.wrap(ba, 0, len)) != len)63throw new IOException("Incomplete write");64fc.position(0);65}6667private static void writeRandomBytes(long seed,68FileChannel fc, int off, int len)69throws IOException70{71Random r = new Random(seed);72byte[] ba = new byte[len];73r.nextBytes(ba);74writeBytes(ba, fc, off, len);75}7677private static void writeZeroBytes(FileChannel fc, int off, int len)78throws IOException79{80byte[] ba = new byte[len];81writeBytes(ba, fc, off, len);82}8384private static void checkBytes(FileChannel fc, int off, int len,85byte[] bytes)86throws IOException87{88ByteBuffer bb = ByteBuffer.allocate(len);89fc.position(off);90if (fc.read(bb) != len)91throw new IOException("Incomplete read");92bb.flip();93ByteBuffer bab = ByteBuffer.wrap(bytes, 0, len);94if (!bb.equals(bab))95throw new Failure("Wrong data written");96}9798private static void checkRandomBytes(FileChannel fc, int off, int len,99long seed)100throws IOException101{102byte[] ba = new byte[len];103Random r = new Random(seed);104r.nextBytes(ba);105checkBytes(fc, off, len, ba);106}107108private static void checkZeroBytes(FileChannel fc, int off, int len)109throws IOException110{111byte[] ba = new byte[len];112checkBytes(fc, off, len, ba);113}114115// For debugging116//117private static void dump(FileChannel fc)118throws IOException119{120int sz = (int)fc.size();121ByteBuffer bb = ByteBuffer.allocate(sz);122fc.position(0);123if (fc.read(bb) != sz)124throw new IOException("Incomplete read");125bb.flip();126byte prev = -1;127int r = 0; // Repeats128int n = 0;129while (bb.hasRemaining() && (n < 32)) {130byte b = bb.get();131if (b == prev) {132r++;133continue;134}135if (r > 0) {136int c = prev & 0xff;137if (c < 0x10)138out.print('0');139out.print(Integer.toHexString(c));140if (r > 1) {141out.print("[");142out.print(r);143out.print("]");144}145n++;146}147prev = b;148r = 1;149}150if (r > 0) {151int c = prev & 0xff;152if (c < 0x10)153out.print('0');154out.print(Integer.toHexString(c));155if (r > 1) {156out.print("[");157out.print(r);158out.print("]");159}160n++;161}162if (bb.hasRemaining())163out.print("...");164out.println();165}166167168169static File sourceFile;170static File targetFile;171172// -- Self-verifying sources and targets --173174static abstract class Source {175176protected final int size;177protected final long seed;178private final String name;179180Source(int size, long seed, String name) {181this.size = size;182this.seed = seed;183this.name = name;184}185186String name() {187return name;188}189190abstract ReadableByteChannel channel();191192abstract void verify() throws IOException;193194}195196static class FileSource197extends Source198{199private final File fn;200private final RandomAccessFile raf;201private final FileChannel fc;202203FileSource(int size, long seed) throws IOException {204super(size, seed, "FileChannel");205fn = sourceFile;206raf = new RandomAccessFile(fn, "rw");207fc = raf.getChannel();208fc.position(0);209writeRandomBytes(seed, fc, 0, size);210}211212ReadableByteChannel channel() {213return fc;214}215216void verify() throws IOException {217if (fc.position() != size)218throw new Failure("Wrong position: "219+ fc.position() + " (expected " + size +220")");221checkRandomBytes(fc, 0, size, seed);222fc.close();223raf.close(); // Bug in 1.4.0224}225226}227228static class UserSource229extends Source230{231private ReadableByteChannel ch;232private final ByteBuffer src;233234UserSource(int size, long seed) {235super(size, seed, "UserChannel");236237final byte[] bytes = new byte[size + 1];238Random r = new Random(seed);239r.nextBytes(bytes);240src = ByteBuffer.wrap(bytes);241242ch = new ReadableByteChannel() {243public int read(ByteBuffer dst) {244if (!src.hasRemaining())245return -1;246int nr = Math.min(src.remaining(), dst.remaining());247ByteBuffer s = src.duplicate();248s.limit(s.position() + nr);249dst.put(s);250src.position(src.position() + nr);251return nr;252}253public boolean isOpen() {254return true;255}256public void close() { }257};258}259260ReadableByteChannel channel() {261return ch;262}263264void verify() {265if (src.remaining() != 1)266throw new Failure("Source has " + src.remaining()267+ " bytes remaining (expected 1)");268}269270}271272static abstract class Target {273274protected final int size;275protected final long seed;276private final String name;277278Target(int size, long seed, String name) {279this.size = size;280this.seed = seed;281this.name = name;282}283284String name() {285return name;286}287288abstract WritableByteChannel channel();289290abstract void verify() throws IOException;291292}293294static class FileTarget295extends Target296{297private final File fn;298private final RandomAccessFile raf;299private final FileChannel fc;300301FileTarget(int size, long seed) throws IOException {302super(size, seed, "FileChannel");303fn = targetFile;304raf = new RandomAccessFile(fn, "rw");305fc = raf.getChannel();306fc.position(0);307}308309WritableByteChannel channel() {310return fc;311}312313void verify() throws IOException {314if (fc.position() != size)315throw new Failure("Wrong position: "316+ fc.position() + " (expected " + size + ")");317checkRandomBytes(fc, 0, size, seed);318fc.close();319raf.close(); // Bug in 1.4.0320}321322}323324static class UserTarget325extends Target326{327private WritableByteChannel ch;328private final ByteBuffer dst;329330UserTarget(int size, long seed) {331super(size, seed, "UserChannel");332dst = ByteBuffer.wrap(new byte[size + 1]);333334ch = new WritableByteChannel() {335public int write(ByteBuffer src) {336int nr = Math.min(src.remaining(), dst.remaining());337ByteBuffer s = src.duplicate();338s.limit(s.position() + nr);339dst.put(s);340src.position(src.position() + nr);341return nr;342}343public boolean isOpen() {344return true;345}346public void close() { }347};348}349350WritableByteChannel channel() {351return ch;352}353354void verify() {355if (dst.remaining() != 1)356throw new Failure("Destination has " + dst.remaining()357+ " bytes remaining (expected 1)");358byte[] ba = new byte[size];359Random r = new Random(seed);360r.nextBytes(ba);361dst.flip();362ByteBuffer rbb = ByteBuffer.wrap(ba, 0, size);363if (!dst.equals(rbb))364throw new Failure("Wrong data written");365}366367}368369370// Generates a sequence of ints of the form 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,371// 15, 16, 17, 31, 32, 33, ..., 2^i-1, 2^i, 2^i+1, ..., max.372373static class IntGenerator {374375private int max;376private int cur = -1;377private int p2 = 8;378379IntGenerator(int max) {380this.max = max;381}382383boolean hasNext() {384return cur < max;385}386387int next() {388if (cur >= max)389throw new IllegalStateException();390if (cur < 6) {391cur++;392return cur;393}394if (cur == p2 + 1) {395p2 <<= 1;396cur = p2 - 1;397return cur;398}399cur++;400return cur;401}402403}404405406// -- Tests --407408private static final int MAX_XFER_SIZE = 1 << 14;409private static final int MAX_FILE_SIZE = MAX_XFER_SIZE << 1;410411private static boolean debug = false;412private static boolean verbose = false;413414static void show(String dir, String channelName, int off, int len) {415if (!verbose)416return;417out.println(dir + " " + channelName +418": offset " + off + ", length " + len);419}420421static void testTo(long seed, FileChannel fc, int off, int len, Target tgt)422throws IOException423{424show("To", tgt.name(), off, len);425426// Clear source, then randomize just the source region427writeZeroBytes(fc, 0, MAX_FILE_SIZE);428writeRandomBytes(seed, fc, off, len);429430// Randomize position431int pos = (int)seed & 0xfff;432fc.position(pos);433434int n = (int)fc.transferTo(off, len, tgt.channel());435if (n != len)436throw new Failure("Incorrect transfer length: " + n437+ " (expected " + len + ")");438439// Check that source wasn't changed440if (fc.position() != pos)441throw new Failure("Position changed");442if (debug)443dump(fc);444checkRandomBytes(fc, off, len, seed);445writeZeroBytes(fc, off, len);446checkZeroBytes(fc, 0, MAX_FILE_SIZE);447448// Check that target was updated correctly449tgt.verify();450}451452static void testFrom(long seed, Source src, FileChannel fc, int off, int len)453throws IOException454{455show("From", src.name(), off, len);456457// Clear target458writeZeroBytes(fc, 0, MAX_FILE_SIZE);459460// Randomize position461int pos = (int)seed & 0xfff;462fc.position(pos);463464int n = (int)fc.transferFrom(src.channel(), off, len);465if (n != len)466throw new Failure("Incorrect transfer length: " + n467+ " (expected " + len + ")");468469// Check that source didn't change, and was read correctly470src.verify();471472// Check that target was updated correctly473if (fc.position() != pos)474throw new Failure("Position changed");475if (debug)476dump(fc);477checkRandomBytes(fc, off, len, seed);478writeZeroBytes(fc, off, len);479checkZeroBytes(fc, 0, MAX_FILE_SIZE);480}481482public static void main(String[] args)483throws Exception484{485if (args.length > 0) {486if (args[0].indexOf('v') >= 0)487verbose = true;488if (args[0].indexOf('d') >= 0)489debug = verbose = true;490}491492File testDir = new File(System.getProperty("test.dir", "."));493494sourceFile = File.createTempFile("xfer.src.", "", testDir);495sourceFile.deleteOnExit();496targetFile = File.createTempFile("xfer.tgt.", "", testDir);497targetFile.deleteOnExit();498499File fn = File.createTempFile("xfer.fch.", "", testDir);500fn.deleteOnExit();501502Random rnd = new Random();503int failures = 0;504505try (FileChannel fc = new RandomAccessFile(fn, "rw").getChannel()) {506for (boolean to = false;; to = true) {507for (boolean user = false;; user = true) {508if (!verbose)509out.print((to ? "To " : "From ") +510(user ? "user channel" : "file channel")511+ ":");512IntGenerator offGen = new IntGenerator(MAX_XFER_SIZE + 2);513while (offGen.hasNext()) {514int off = offGen.next();515if (!verbose) out.print(" " + off);516IntGenerator lenGen = new IntGenerator(MAX_XFER_SIZE + 2);517while (lenGen.hasNext()) {518int len = lenGen.next();519long s = rnd.nextLong();520String chName = null;521try {522if (to) {523Target tgt;524if (user)525tgt = new UserTarget(len, s);526else527tgt = new FileTarget(len, s);528chName = tgt.name();529testTo(s, fc, off, len, tgt);530}531else {532Source src;533if (user)534src = new UserSource(len, s);535else536src = new FileSource(len, s);537chName = src.name();538testFrom(s, src, fc, off, len);539}540} catch (Failure x) {541out.println();542out.println("FAILURE: " + chName543+ ", offset " + off544+ ", length " + len);545x.printStackTrace(out);546failures++;547}548}549}550if (!verbose)551out.println();552if (user)553break;554}555if (to)556break;557}558}559560sourceFile.delete();561targetFile.delete();562fn.delete();563564if (failures > 0) {565out.println();566throw new RuntimeException("Some tests failed");567}568569out.println("Test succeeded.");570}571}572573574