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 4434723 4482726 4559072 4795550 5081340 5103988 6984545 26 * @summary Test FileChannel.transferFrom and transferTo (use -Dseed=X to set PRNG seed) 27 * @library .. 28 * @library /test/lib 29 * @run testng/timeout=300 Transfer 30 * @key randomness 31 */ 32 33 import java.io.BufferedReader; 34 import java.io.File; 35 import java.io.FileInputStream; 36 import java.io.FileOutputStream; 37 import java.io.InputStreamReader; 38 import java.io.IOException; 39 import java.io.RandomAccessFile; 40 import java.io.Reader; 41 import java.net.InetAddress; 42 import java.net.InetSocketAddress; 43 import java.nio.ByteBuffer; 44 import java.nio.channels.FileChannel; 45 import java.nio.channels.NonReadableChannelException; 46 import java.nio.channels.Pipe; 47 import java.nio.channels.ServerSocketChannel; 48 import java.nio.channels.SocketChannel; 49 import java.nio.channels.spi.SelectorProvider; 50 import java.util.Random; 51 import java.util.concurrent.TimeUnit; 52 53 import jdk.test.lib.RandomFactory; 54 55 import org.testng.annotations.Test; 56 57 public class Transfer { 58 59 private static Random generator = RandomFactory.getRandom(); 60 61 @Test 62 public void testFileChannel() throws Exception { 63 File source = File.createTempFile("source", null); 64 source.deleteOnExit(); 65 File sink = File.createTempFile("sink", null); 66 sink.deleteOnExit(); 67 68 FileOutputStream fos = new FileOutputStream(source); 69 FileChannel sourceChannel = fos.getChannel(); 70 sourceChannel.write(ByteBuffer.wrap( 71 "Use the source, Luke!".getBytes())); 72 sourceChannel.close(); 73 74 FileInputStream fis = new FileInputStream(source); 75 sourceChannel = fis.getChannel(); 76 77 RandomAccessFile raf = new RandomAccessFile(sink, "rw"); 78 FileChannel sinkChannel = raf.getChannel(); 79 long oldSinkPosition = sinkChannel.position(); 80 long oldSourcePosition = sourceChannel.position(); 81 82 long bytesWritten = sinkChannel.transferFrom(sourceChannel, 0, 10); 83 if (bytesWritten != 10) 84 throw new RuntimeException("Transfer failed"); 85 86 if (sourceChannel.position() == oldSourcePosition) 87 throw new RuntimeException("Source position didn't change"); 88 89 if (sinkChannel.position() != oldSinkPosition) 90 throw new RuntimeException("Sink position changed"); 91 92 if (sinkChannel.size() != 10) 93 throw new RuntimeException("Unexpected sink size"); 94 95 bytesWritten = sinkChannel.transferFrom(sourceChannel, 1000, 10); 96 97 if (bytesWritten > 0) 98 throw new RuntimeException("Wrote past file size"); 99 100 sourceChannel.close(); 101 sinkChannel.close(); 102 103 source.delete(); 104 sink.delete(); 105 } 106 107 @Test 108 public void testReadableByteChannel() throws Exception { 109 int[] testSizes = { 0, 10, 1023, 1024, 1025, 2047, 2048, 2049 }; 110 111 for (int size : testSizes) { 112 SelectorProvider sp = SelectorProvider.provider(); 113 Pipe p = sp.openPipe(); 114 Pipe.SinkChannel sink = p.sink(); 115 Pipe.SourceChannel source = p.source(); 116 sink.configureBlocking(false); 117 118 ByteBuffer outgoingdata = ByteBuffer.allocateDirect(size + 10); 119 byte[] someBytes = new byte[size + 10]; 120 generator.nextBytes(someBytes); 121 outgoingdata.put(someBytes); 122 outgoingdata.flip(); 123 124 int totalWritten = 0; 125 while (totalWritten < size + 10) { 126 int written = sink.write(outgoingdata); 127 if (written < 0) 128 throw new Exception("Write failed"); 129 totalWritten += written; 130 } 131 132 File f = File.createTempFile("blah"+size, null); 133 f.deleteOnExit(); 134 RandomAccessFile raf = new RandomAccessFile(f, "rw"); 135 FileChannel fc = raf.getChannel(); 136 long oldPosition = fc.position(); 137 138 long bytesWritten = fc.transferFrom(source, 0, size); 139 fc.force(true); 140 if (bytesWritten != size) 141 throw new RuntimeException("Transfer failed"); 142 143 if (fc.position() != oldPosition) 144 throw new RuntimeException("Position changed"); 145 146 if (fc.size() != size) 147 throw new RuntimeException("Unexpected sink size "+ fc.size()); 148 149 fc.close(); 150 sink.close(); 151 source.close(); 152 153 f.delete(); 154 } 155 } 156 157 @Test 158 public void xferTest02() throws Exception { // for bug 4482726 159 byte[] srcData = new byte[5000]; 160 for (int i=0; i<5000; i++) 161 srcData[i] = (byte)generator.nextInt(); 162 163 // get filechannel for the source file. 164 File source = File.createTempFile("source", null); 165 source.deleteOnExit(); 166 RandomAccessFile raf1 = new RandomAccessFile(source, "rw"); 167 FileChannel fc1 = raf1.getChannel(); 168 169 // write out data to the file channel 170 long bytesWritten = 0; 171 while (bytesWritten < 5000) { 172 bytesWritten = fc1.write(ByteBuffer.wrap(srcData)); 173 } 174 175 // get filechannel for the dst file. 176 File dest = File.createTempFile("dest", null); 177 dest.deleteOnExit(); 178 RandomAccessFile raf2 = new RandomAccessFile(dest, "rw"); 179 FileChannel fc2 = raf2.getChannel(); 180 181 int bytesToWrite = 3000; 182 int startPosition = 1000; 183 184 bytesWritten = fc1.transferTo(startPosition, bytesToWrite, fc2); 185 186 fc1.close(); 187 fc2.close(); 188 raf1.close(); 189 raf2.close(); 190 191 source.delete(); 192 dest.delete(); 193 } 194 195 @Test 196 public void xferTest03() throws Exception { // for bug 4559072 197 byte[] srcData = new byte[] {1,2,3,4} ; 198 199 // get filechannel for the source file. 200 File source = File.createTempFile("source", null); 201 source.deleteOnExit(); 202 RandomAccessFile raf1 = new RandomAccessFile(source, "rw"); 203 FileChannel fc1 = raf1.getChannel(); 204 fc1.truncate(0); 205 206 // write out data to the file channel 207 int bytesWritten = 0; 208 while (bytesWritten < 4) { 209 bytesWritten = fc1.write(ByteBuffer.wrap(srcData)); 210 } 211 212 // get filechannel for the dst file. 213 File dest = File.createTempFile("dest", null); 214 dest.deleteOnExit(); 215 RandomAccessFile raf2 = new RandomAccessFile(dest, "rw"); 216 FileChannel fc2 = raf2.getChannel(); 217 fc2.truncate(0); 218 219 fc1.transferTo(0, srcData.length + 1, fc2); 220 221 if (fc2.size() > 4) 222 throw new Exception("xferTest03 failed"); 223 224 fc1.close(); 225 fc2.close(); 226 raf1.close(); 227 raf2.close(); 228 229 source.delete(); 230 dest.delete(); 231 } 232 233 // xferTest04() and xferTest05() moved to Transfer4GBFile.java 234 235 static void checkFileData(File file, String expected) throws Exception { 236 FileInputStream fis = new FileInputStream(file); 237 Reader r = new BufferedReader(new InputStreamReader(fis, "ASCII")); 238 StringBuilder sb = new StringBuilder(); 239 int c; 240 while ((c = r.read()) != -1) 241 sb.append((char)c); 242 String contents = sb.toString(); 243 if (! contents.equals(expected)) 244 throw new Exception("expected: " + expected 245 + ", got: " + contents); 246 r.close(); 247 } 248 249 // Test transferFrom asking for more bytes than remain in source 250 @Test 251 public void xferTest06() throws Exception { // for bug 5081340 252 String data = "Use the source, Luke!"; 253 254 File source = File.createTempFile("source", null); 255 source.deleteOnExit(); 256 File sink = File.createTempFile("sink", null); 257 sink.deleteOnExit(); 258 259 FileOutputStream fos = new FileOutputStream(source); 260 fos.write(data.getBytes("ASCII")); 261 fos.close(); 262 263 FileChannel sourceChannel = 264 new RandomAccessFile(source, "rw").getChannel(); 265 sourceChannel.position(7); 266 long remaining = sourceChannel.size() - sourceChannel.position(); 267 FileChannel sinkChannel = 268 new RandomAccessFile(sink, "rw").getChannel(); 269 long n = sinkChannel.transferFrom(sourceChannel, 0L, 270 sourceChannel.size()); // overflow 271 if (n != remaining) 272 throw new Exception("n == " + n + ", remaining == " + remaining); 273 274 sinkChannel.close(); 275 sourceChannel.close(); 276 277 checkFileData(source, data); 278 checkFileData(sink, data.substring(7,data.length())); 279 280 source.delete(); 281 } 282 283 // Test transferTo to non-blocking socket channel 284 @Test 285 public void xferTest07() throws Exception { // for bug 5103988 286 File source = File.createTempFile("source", null); 287 source.deleteOnExit(); 288 289 FileChannel sourceChannel = new RandomAccessFile(source, "rw") 290 .getChannel(); 291 sourceChannel.position(32000L) 292 .write(ByteBuffer.wrap("The End".getBytes())); 293 294 // The sink is a non-blocking socket channel 295 ServerSocketChannel ssc = ServerSocketChannel.open(); 296 ssc.socket().bind(new InetSocketAddress(0)); 297 InetSocketAddress sa = new InetSocketAddress( 298 InetAddress.getLocalHost(), ssc.socket().getLocalPort()); 299 SocketChannel sink = SocketChannel.open(sa); 300 sink.configureBlocking(false); 301 SocketChannel other = ssc.accept(); 302 303 long size = sourceChannel.size(); 304 305 // keep sending until congested 306 long n; 307 do { 308 n = sourceChannel.transferTo(0, size, sink); 309 } while (n > 0); 310 311 sourceChannel.close(); 312 sink.close(); 313 other.close(); 314 ssc.close(); 315 source.delete(); 316 } 317 318 // xferTest08() moved to TransferTo6GBFile.java 319 320 // Test that transferFrom with FileChannel source that is not readable 321 // throws NonReadableChannelException 322 @Test 323 public void xferTest09() throws Exception { // for bug 6984545 324 File source = File.createTempFile("source", null); 325 source.deleteOnExit(); 326 327 File target = File.createTempFile("target", null); 328 target.deleteOnExit(); 329 330 FileChannel fc1 = new FileOutputStream(source).getChannel(); 331 FileChannel fc2 = new RandomAccessFile(target, "rw").getChannel(); 332 try { 333 fc2.transferFrom(fc1, 0L, 0); 334 throw new RuntimeException("NonReadableChannelException expected"); 335 } catch (NonReadableChannelException expected) { 336 } finally { 337 fc1.close(); 338 fc2.close(); 339 } 340 } 341 }