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