1 /* 2 * Copyright (c) 2008, 2011, 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 4313887 26 * @summary Unit test for java.nio.file.Files.newByteChannel 27 * @library .. 28 */ 29 30 import java.nio.ByteBuffer; 31 import java.nio.file.*; 32 import static java.nio.file.StandardOpenOption.*; 33 import static com.sun.nio.file.ExtendedOpenOption.*; 34 import java.nio.file.attribute.FileAttribute; 35 import java.nio.channels.*; 36 import java.io.IOException; 37 import java.util.*; 38 39 public class SBC { 40 41 static boolean supportsLinks; 42 43 public static void main(String[] args) throws Exception { 44 Path dir = TestUtil.createTemporaryDirectory(); 45 try { 46 supportsLinks = TestUtil.supportsLinks(dir); 47 48 // open options 49 createTests(dir); 50 appendTests(dir); 51 truncateExistingTests(dir); 52 noFollowLinksTests(dir); 53 54 // SeekableByteChannel methods 55 sizeTruncatePositionTests(dir); 56 57 // platform specific 58 if (System.getProperty("os.name").startsWith("Windows")) 59 dosSharingOptionTests(dir); 60 61 // misc. tests 62 badCombinations(dir); 63 unsupportedOptions(dir); 64 nullTests(dir); 65 66 } finally { 67 TestUtil.removeAll(dir); 68 } 69 } 70 71 // test CREATE and CREATE_NEW options 72 static void createTests(Path dir) throws Exception { 73 Path file = dir.resolve("foo"); 74 75 // CREATE 76 try { 77 // create file (no existing file) 78 Files.newByteChannel(file, CREATE, WRITE).close(); 79 if (Files.notExists(file)) 80 throw new RuntimeException("File not created"); 81 82 // create file (existing file) 83 Files.newByteChannel(file, CREATE, WRITE).close(); 84 85 // create file where existing file is a sym link 86 if (supportsLinks) { 87 Path link = Files.createSymbolicLink(dir.resolve("link"), file); 88 try { 89 // file already exists 90 Files.newByteChannel(link, CREATE, WRITE).close(); 91 92 // file does not exist 93 Files.delete(file); 94 Files.newByteChannel(link, CREATE, WRITE).close(); 95 if (Files.notExists(file)) 96 throw new RuntimeException("File not created"); 97 98 } finally { 99 TestUtil.deleteUnchecked(link); 100 } 101 } 102 103 } finally { 104 TestUtil.deleteUnchecked(file); 105 } 106 107 // CREATE_NEW 108 try { 109 // create file 110 Files.newByteChannel(file, CREATE_NEW, WRITE).close(); 111 if (Files.notExists(file)) 112 throw new RuntimeException("File not created"); 113 114 // create should fail 115 try { 116 SeekableByteChannel sbc = 117 Files.newByteChannel(file, CREATE_NEW, WRITE); 118 sbc.close(); 119 throw new RuntimeException("FileAlreadyExistsException not thrown"); 120 } catch (FileAlreadyExistsException x) { } 121 122 // create should fail 123 if (supportsLinks) { 124 Path link = dir.resolve("link"); 125 Path target = dir.resolve("thisDoesNotExist"); 126 Files.createSymbolicLink(link, target); 127 try { 128 129 try { 130 SeekableByteChannel sbc = 131 Files.newByteChannel(file, CREATE_NEW, WRITE); 132 sbc.close(); 133 throw new RuntimeException("FileAlreadyExistsException not thrown"); 134 } catch (FileAlreadyExistsException x) { } 135 136 } finally { 137 TestUtil.deleteUnchecked(link); 138 } 139 } 140 141 142 } finally { 143 TestUtil.deleteUnchecked(file); 144 } 145 146 // CREATE_NEW + SPARSE 147 try { 148 try (SeekableByteChannel sbc = Files.newByteChannel(file, CREATE_NEW, WRITE, SPARSE)) { 149 final long hole = 2L * 1024L * 1024L * 1024L; 150 sbc.position(hole); 151 write(sbc, "hello"); 152 long size = sbc.size(); 153 if (size != (hole + 5)) 154 throw new RuntimeException("Unexpected size"); 155 } 156 } finally { 157 TestUtil.deleteUnchecked(file); 158 } 159 } 160 161 // test APPEND option 162 static void appendTests(Path dir) throws Exception { 163 Path file = dir.resolve("foo"); 164 try { 165 // "hello there" should be written to file 166 try (SeekableByteChannel sbc = Files.newByteChannel(file, CREATE_NEW, WRITE, APPEND)) { 167 write(sbc, "hello "); 168 sbc.position(0L); 169 write(sbc, "there"); 170 } 171 172 // check file 173 try (Scanner s = new Scanner(file)) { 174 String line = s.nextLine(); 175 if (!line.equals("hello there")) 176 throw new RuntimeException("Unexpected file contents"); 177 } 178 179 // check that read is not allowed 180 try (SeekableByteChannel sbc = Files.newByteChannel(file, APPEND)) { 181 sbc.read(ByteBuffer.allocate(100)); 182 } catch (NonReadableChannelException x) { 183 } 184 } finally { 185 // clean-up 186 TestUtil.deleteUnchecked(file); 187 } 188 } 189 190 // test TRUNCATE_EXISTING option 191 static void truncateExistingTests(Path dir) throws Exception { 192 Path file = dir.resolve("foo"); 193 try { 194 try (SeekableByteChannel sbc = Files.newByteChannel(file, CREATE_NEW, WRITE)) { 195 write(sbc, "Have a nice day!"); 196 } 197 198 // re-open with truncate option 199 // write short message and check 200 try (SeekableByteChannel sbc = Files.newByteChannel(file, WRITE, TRUNCATE_EXISTING)) { 201 write(sbc, "Hello there!"); 202 } 203 try (Scanner s = new Scanner(file)) { 204 String line = s.nextLine(); 205 if (!line.equals("Hello there!")) 206 throw new RuntimeException("Unexpected file contents"); 207 } 208 209 // re-open with create + truncate option 210 // check file is of size 0L 211 try (SeekableByteChannel sbc = Files.newByteChannel(file, WRITE, CREATE, TRUNCATE_EXISTING)) { 212 long size = ((FileChannel)sbc).size(); 213 if (size != 0L) 214 throw new RuntimeException("File not truncated"); 215 } 216 217 } finally { 218 // clean-up 219 TestUtil.deleteUnchecked(file); 220 } 221 222 } 223 224 // test NOFOLLOW_LINKS option 225 static void noFollowLinksTests(Path dir) throws Exception { 226 if (!supportsLinks) 227 return; 228 Path file = Files.createFile(dir.resolve("foo")); 229 try { 230 // ln -s foo link 231 Path link = dir.resolve("link"); 232 Files.createSymbolicLink(link, file); 233 234 // open with NOFOLLOW_LINKS option 235 try { 236 Files.newByteChannel(link, READ, LinkOption.NOFOLLOW_LINKS); 237 throw new RuntimeException(); 238 } catch (IOException x) { 239 } finally { 240 TestUtil.deleteUnchecked(link); 241 } 242 243 } finally { 244 // clean-up 245 TestUtil.deleteUnchecked(file); 246 } 247 } 248 249 // test size/truncate/position methods 250 static void sizeTruncatePositionTests(Path dir) throws Exception { 251 Path file = dir.resolve("foo"); 252 try { 253 try (SeekableByteChannel sbc = Files.newByteChannel(file, CREATE_NEW, READ, WRITE)) { 254 if (sbc.size() != 0L) 255 throw new RuntimeException("Unexpected size"); 256 257 // check size 258 write(sbc, "hello"); 259 if (sbc.size() != 5L) 260 throw new RuntimeException("Unexpected size"); 261 262 // truncate (size and position should change) 263 sbc.truncate(4L); 264 if (sbc.size() != 4L) 265 throw new RuntimeException("Unexpected size"); 266 if (sbc.position() != 4L) 267 throw new RuntimeException("Unexpected position"); 268 269 // truncate (position should not change) 270 sbc.position(2L).truncate(3L); 271 if (sbc.size() != 3L) 272 throw new RuntimeException("Unexpected size"); 273 if (sbc.position() != 2L) 274 throw new RuntimeException("Unexpected position"); 275 } 276 } finally { 277 TestUtil.deleteUnchecked(file); 278 } 279 } 280 281 // Windows specific options for the use by applications that really want 282 // to use legacy DOS sharing options 283 static void dosSharingOptionTests(Path dir) throws Exception { 284 Path file = Files.createFile(dir.resolve("foo")); 285 try { 286 // no sharing 287 try (SeekableByteChannel ch = Files.newByteChannel(file, READ, NOSHARE_READ, 288 NOSHARE_WRITE, NOSHARE_DELETE)) 289 { 290 try { 291 Files.newByteChannel(file, READ); 292 throw new RuntimeException("Sharing violation expected"); 293 } catch (IOException ignore) { } 294 try { 295 Files.newByteChannel(file, WRITE); 296 throw new RuntimeException("Sharing violation expected"); 297 } catch (IOException ignore) { } 298 try { 299 Files.delete(file); 300 throw new RuntimeException("Sharing violation expected"); 301 } catch (IOException ignore) { } 302 } 303 304 // read allowed 305 try (SeekableByteChannel ch = Files.newByteChannel(file, READ, NOSHARE_WRITE, NOSHARE_DELETE)) { 306 Files.newByteChannel(file, READ).close(); 307 try { 308 Files.newByteChannel(file, WRITE); 309 throw new RuntimeException("Sharing violation expected"); 310 } catch (IOException ignore) { } 311 try { 312 Files.delete(file); 313 throw new RuntimeException("Sharing violation expected"); 314 } catch (IOException ignore) { } 315 } 316 317 // write allowed 318 try (SeekableByteChannel ch = Files.newByteChannel(file, READ, NOSHARE_READ, NOSHARE_DELETE)) { 319 try { 320 Files.newByteChannel(file, READ); 321 throw new RuntimeException("Sharing violation expected"); 322 } catch (IOException ignore) { } 323 Files.newByteChannel(file, WRITE).close(); 324 try { 325 Files.delete(file); 326 throw new RuntimeException("Sharing violation expected"); 327 } catch (IOException ignore) { } 328 } 329 330 // delete allowed 331 try (SeekableByteChannel ch = Files.newByteChannel(file, READ, NOSHARE_READ, NOSHARE_WRITE)) { 332 try { 333 Files.newByteChannel(file, READ); 334 throw new RuntimeException("Sharing violation expected"); 335 } catch (IOException ignore) { } 336 try { 337 Files.newByteChannel(file, WRITE); 338 throw new RuntimeException("Sharing violation expected"); 339 } catch (IOException ignore) { } 340 Files.delete(file); 341 } 342 343 } finally { 344 TestUtil.deleteUnchecked(file); 345 } 346 } 347 348 // invalid combinations of options 349 static void badCombinations(Path dir) throws Exception { 350 Path file = dir.resolve("bad"); 351 352 try { 353 Files.newByteChannel(file, READ, APPEND); 354 throw new RuntimeException("IllegalArgumentException expected"); 355 } catch (IllegalArgumentException x) { } 356 357 try { 358 Files.newByteChannel(file, WRITE, APPEND, TRUNCATE_EXISTING); 359 throw new RuntimeException("IllegalArgumentException expected"); 360 } catch (IllegalArgumentException x) { } 361 } 362 363 // unsupported operations 364 static void unsupportedOptions(Path dir) throws Exception { 365 Path file = dir.resolve("bad"); 366 367 OpenOption badOption = new OpenOption() { }; 368 try { 369 Files.newByteChannel(file, badOption); 370 throw new RuntimeException("UnsupportedOperationException expected"); 371 } catch (UnsupportedOperationException e) { } 372 try { 373 Files.newByteChannel(file, READ, WRITE, badOption); 374 throw new RuntimeException("UnsupportedOperationException expected"); 375 } catch (UnsupportedOperationException e) { } 376 } 377 378 // null handling 379 static void nullTests(Path dir) throws Exception { 380 Path file = dir.resolve("foo"); 381 382 try { 383 OpenOption[] opts = { READ, null }; 384 Files.newByteChannel((Path)null, opts); 385 throw new RuntimeException("NullPointerException expected"); 386 } catch (NullPointerException x) { } 387 388 try { 389 Files.newByteChannel(file, (OpenOption[])null); 390 throw new RuntimeException("NullPointerException expected"); 391 } catch (NullPointerException x) { } 392 393 try { 394 OpenOption[] opts = { READ, null }; 395 Files.newByteChannel(file, opts); 396 throw new RuntimeException("NullPointerException expected"); 397 } catch (NullPointerException x) { } 398 399 try { 400 Files.newByteChannel(file, (Set<OpenOption>)null); 401 throw new RuntimeException("NullPointerException expected"); 402 } catch (NullPointerException x) { } 403 404 try { 405 Set<OpenOption> opts = new HashSet<>(); 406 opts.add(READ); 407 opts.add(null); 408 Files.newByteChannel(file, opts); 409 throw new RuntimeException("NullPointerException expected"); 410 } catch (NullPointerException x) { } 411 412 try { 413 EnumSet<StandardOpenOption> opts = EnumSet.of(READ); 414 Files.newByteChannel(file, opts, (FileAttribute[])null); 415 throw new RuntimeException("NullPointerException expected"); 416 } catch (NullPointerException x) { } 417 418 try { 419 EnumSet<StandardOpenOption> opts = EnumSet.of(READ); 420 FileAttribute[] attrs = { null }; 421 Files.newByteChannel(file, opts, attrs); 422 throw new RuntimeException("NullPointerException expected"); 423 } catch (NullPointerException x) { } 424 } 425 426 static void write(WritableByteChannel wbc, String msg) throws IOException { 427 ByteBuffer buf = ByteBuffer.wrap(msg.getBytes()); 428 while (buf.hasRemaining()) 429 wbc.write(buf); 430 } 431 }