Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/nio/channels/FileChannel/Transfers.java
38828 views
/*1* Copyright (c) 2002, 2010, 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*/2829import java.io.*;30import java.nio.*;31import java.nio.channels.*;32import java.util.*;333435public class Transfers {3637static PrintStream out = System.out;3839private static class Failure40extends RuntimeException41{4243Failure(Exception x) {44super(x);45}4647Failure(String s) {48super(s);49}5051}525354// -- Writing and reading random bytes --5556private static void writeBytes(byte[] ba, FileChannel fc,57int off, int len)58throws IOException59{60fc.position(off);61if (fc.write(ByteBuffer.wrap(ba, 0, len)) != len)62throw new IOException("Incomplete write");63fc.position(0);64}6566private static void writeRandomBytes(long seed,67FileChannel fc, int off, int len)68throws IOException69{70Random r = new Random(seed);71byte[] ba = new byte[len];72r.nextBytes(ba);73writeBytes(ba, fc, off, len);74}7576private static void writeZeroBytes(FileChannel fc, int off, int len)77throws IOException78{79byte[] ba = new byte[len];80writeBytes(ba, fc, off, len);81}8283private static void checkBytes(FileChannel fc, int off, int len,84byte[] bytes)85throws IOException86{87ByteBuffer bb = ByteBuffer.allocate(len);88fc.position(off);89if (fc.read(bb) != len)90throw new IOException("Incomplete read");91bb.flip();92ByteBuffer bab = ByteBuffer.wrap(bytes, 0, len);93if (!bb.equals(bab))94throw new Failure("Wrong data written");95}9697private static void checkRandomBytes(FileChannel fc, int off, int len,98long seed)99throws IOException100{101byte[] ba = new byte[len];102Random r = new Random(seed);103r.nextBytes(ba);104checkBytes(fc, off, len, ba);105}106107private static void checkZeroBytes(FileChannel fc, int off, int len)108throws IOException109{110byte[] ba = new byte[len];111checkBytes(fc, off, len, ba);112}113114// For debugging115//116private static void dump(FileChannel fc)117throws IOException118{119int sz = (int)fc.size();120ByteBuffer bb = ByteBuffer.allocate(sz);121fc.position(0);122if (fc.read(bb) != sz)123throw new IOException("Incomplete read");124bb.flip();125byte prev = -1;126int r = 0; // Repeats127int n = 0;128while (bb.hasRemaining() && (n < 32)) {129byte b = bb.get();130if (b == prev) {131r++;132continue;133}134if (r > 0) {135int c = prev & 0xff;136if (c < 0x10)137out.print('0');138out.print(Integer.toHexString(c));139if (r > 1) {140out.print("[");141out.print(r);142out.print("]");143}144n++;145}146prev = b;147r = 1;148}149if (r > 0) {150int c = prev & 0xff;151if (c < 0x10)152out.print('0');153out.print(Integer.toHexString(c));154if (r > 1) {155out.print("[");156out.print(r);157out.print("]");158}159n++;160}161if (bb.hasRemaining())162out.print("...");163out.println();164}165166167168static File sourceFile;169static File targetFile;170171// -- Self-verifying sources and targets --172173static abstract class Source {174175protected final int size;176protected final long seed;177private final String name;178179Source(int size, long seed, String name) {180this.size = size;181this.seed = seed;182this.name = name;183}184185String name() {186return name;187}188189abstract ReadableByteChannel channel();190191abstract void verify() throws IOException;192193}194195static class FileSource196extends Source197{198private final File fn;199private final RandomAccessFile raf;200private final FileChannel fc;201202FileSource(int size, long seed) throws IOException {203super(size, seed, "FileChannel");204fn = sourceFile;205raf = new RandomAccessFile(fn, "rw");206fc = raf.getChannel();207fc.position(0);208writeRandomBytes(seed, fc, 0, size);209}210211ReadableByteChannel channel() {212return fc;213}214215void verify() throws IOException {216if (fc.position() != size)217throw new Failure("Wrong position: "218+ fc.position() + " (expected " + size +219")");220checkRandomBytes(fc, 0, size, seed);221fc.close();222raf.close(); // Bug in 1.4.0223}224225}226227static class UserSource228extends Source229{230private ReadableByteChannel ch;231private final ByteBuffer src;232233UserSource(int size, long seed) {234super(size, seed, "UserChannel");235236final byte[] bytes = new byte[size + 1];237Random r = new Random(seed);238r.nextBytes(bytes);239src = ByteBuffer.wrap(bytes);240241ch = new ReadableByteChannel() {242public int read(ByteBuffer dst) {243if (!src.hasRemaining())244return -1;245int nr = Math.min(src.remaining(), dst.remaining());246ByteBuffer s = src.duplicate();247s.limit(s.position() + nr);248dst.put(s);249src.position(src.position() + nr);250return nr;251}252public boolean isOpen() {253return true;254}255public void close() { }256};257}258259ReadableByteChannel channel() {260return ch;261}262263void verify() {264if (src.remaining() != 1)265throw new Failure("Source has " + src.remaining()266+ " bytes remaining (expected 1)");267}268269}270271static abstract class Target {272273protected final int size;274protected final long seed;275private final String name;276277Target(int size, long seed, String name) {278this.size = size;279this.seed = seed;280this.name = name;281}282283String name() {284return name;285}286287abstract WritableByteChannel channel();288289abstract void verify() throws IOException;290291}292293static class FileTarget294extends Target295{296private final File fn;297private final RandomAccessFile raf;298private final FileChannel fc;299300FileTarget(int size, long seed) throws IOException {301super(size, seed, "FileChannel");302fn = targetFile;303raf = new RandomAccessFile(fn, "rw");304fc = raf.getChannel();305fc.position(0);306}307308WritableByteChannel channel() {309return fc;310}311312void verify() throws IOException {313if (fc.position() != size)314throw new Failure("Wrong position: "315+ fc.position() + " (expected " + size + ")");316checkRandomBytes(fc, 0, size, seed);317fc.close();318raf.close(); // Bug in 1.4.0319}320321}322323static class UserTarget324extends Target325{326private WritableByteChannel ch;327private final ByteBuffer dst;328329UserTarget(int size, long seed) {330super(size, seed, "UserChannel");331dst = ByteBuffer.wrap(new byte[size + 1]);332333ch = new WritableByteChannel() {334public int write(ByteBuffer src) {335int nr = Math.min(src.remaining(), dst.remaining());336ByteBuffer s = src.duplicate();337s.limit(s.position() + nr);338dst.put(s);339src.position(src.position() + nr);340return nr;341}342public boolean isOpen() {343return true;344}345public void close() { }346};347}348349WritableByteChannel channel() {350return ch;351}352353void verify() {354if (dst.remaining() != 1)355throw new Failure("Destination has " + dst.remaining()356+ " bytes remaining (expected 1)");357byte[] ba = new byte[size];358Random r = new Random(seed);359r.nextBytes(ba);360dst.flip();361ByteBuffer rbb = ByteBuffer.wrap(ba, 0, size);362if (!dst.equals(rbb))363throw new Failure("Wrong data written");364}365366}367368369// Generates a sequence of ints of the form 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,370// 15, 16, 17, 31, 32, 33, ..., 2^i-1, 2^i, 2^i+1, ..., max.371372static class IntGenerator {373374private int max;375private int cur = -1;376private int p2 = 8;377378IntGenerator(int max) {379this.max = max;380}381382boolean hasNext() {383return cur < max;384}385386int next() {387if (cur >= max)388throw new IllegalStateException();389if (cur < 6) {390cur++;391return cur;392}393if (cur == p2 + 1) {394p2 <<= 1;395cur = p2 - 1;396return cur;397}398cur++;399return cur;400}401402}403404405// -- Tests --406407private static final int MAX_XFER_SIZE = 1 << 14;408private static final int MAX_FILE_SIZE = MAX_XFER_SIZE << 1;409410private static boolean debug = false;411private static boolean verbose = false;412413static void show(String dir, String channelName, int off, int len) {414if (!verbose)415return;416out.println(dir + " " + channelName +417": offset " + off + ", length " + len);418}419420static void testTo(long seed, FileChannel fc, int off, int len, Target tgt)421throws IOException422{423show("To", tgt.name(), off, len);424425// Clear source, then randomize just the source region426writeZeroBytes(fc, 0, MAX_FILE_SIZE);427writeRandomBytes(seed, fc, off, len);428429// Randomize position430int pos = (int)seed & 0xfff;431fc.position(pos);432433int n = (int)fc.transferTo(off, len, tgt.channel());434if (n != len)435throw new Failure("Incorrect transfer length: " + n436+ " (expected " + len + ")");437438// Check that source wasn't changed439if (fc.position() != pos)440throw new Failure("Position changed");441if (debug)442dump(fc);443checkRandomBytes(fc, off, len, seed);444writeZeroBytes(fc, off, len);445checkZeroBytes(fc, 0, MAX_FILE_SIZE);446447// Check that target was updated correctly448tgt.verify();449}450451static void testFrom(long seed, Source src, FileChannel fc, int off, int len)452throws IOException453{454show("From", src.name(), off, len);455456// Clear target457writeZeroBytes(fc, 0, MAX_FILE_SIZE);458459// Randomize position460int pos = (int)seed & 0xfff;461fc.position(pos);462463int n = (int)fc.transferFrom(src.channel(), off, len);464if (n != len)465throw new Failure("Incorrect transfer length: " + n466+ " (expected " + len + ")");467468// Check that source didn't change, and was read correctly469src.verify();470471// Check that target was updated correctly472if (fc.position() != pos)473throw new Failure("Position changed");474if (debug)475dump(fc);476checkRandomBytes(fc, off, len, seed);477writeZeroBytes(fc, off, len);478checkZeroBytes(fc, 0, MAX_FILE_SIZE);479}480481public static void main(String[] args)482throws Exception483{484if (args.length > 0) {485if (args[0].indexOf('v') >= 0)486verbose = true;487if (args[0].indexOf('d') >= 0)488debug = verbose = true;489}490491sourceFile = File.createTempFile("xfer.src.", "");492sourceFile.deleteOnExit();493targetFile = File.createTempFile("xfer.tgt.", "");494targetFile.deleteOnExit();495496File fn = File.createTempFile("xfer.fch.", "");497fn.deleteOnExit();498FileChannel fc = new RandomAccessFile(fn, "rw").getChannel();499500Random rnd = new Random();501int failures = 0;502503for (boolean to = false;; to = true) {504for (boolean user = false;; user = true) {505if (!verbose)506out.print((to ? "To " : "From ") +507(user ? "user channel" : "file channel")508+ ":");509IntGenerator offGen = new IntGenerator(MAX_XFER_SIZE + 2);510while (offGen.hasNext()) {511int off = offGen.next();512if (!verbose) out.print(" " + off);513IntGenerator lenGen = new IntGenerator(MAX_XFER_SIZE + 2);514while (lenGen.hasNext()) {515int len = lenGen.next();516long s = rnd.nextLong();517String chName = null;518try {519if (to) {520Target tgt;521if (user)522tgt = new UserTarget(len, s);523else524tgt = new FileTarget(len, s);525chName = tgt.name();526testTo(s, fc, off, len, tgt);527}528else {529Source src;530if (user)531src = new UserSource(len, s);532else533src = new FileSource(len, s);534chName = src.name();535testFrom(s, src, fc, off, len);536}537} catch (Failure x) {538out.println();539out.println("FAILURE: " + chName540+ ", offset " + off541+ ", length " + len);542x.printStackTrace(out);543failures++;544}545}546}547if (!verbose)548out.println();549if (user)550break;551}552if (to)553break;554}555556sourceFile.delete();557targetFile.delete();558fn.delete();559560if (failures > 0) {561out.println();562throw new RuntimeException("Some tests failed");563}564565}566567}568569570