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