1 /* 2 * Copyright (c) 2008, 2014, 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 6838333 7017446 8011537 8042470 26 * @summary Unit test for java.nio.file.WatchService 27 * @library .. 28 * @run main Basic 29 */ 30 31 import java.nio.file.*; 32 import static java.nio.file.StandardWatchEventKinds.*; 33 import java.nio.file.attribute.*; 34 import java.io.*; 35 import java.util.*; 36 import java.util.concurrent.TimeUnit; 37 38 /** 39 * Unit test for WatchService that exercises all methods in various scenarios. 40 */ 41 42 public class Basic { 43 44 static void checkKey(WatchKey key, Path dir) { 45 if (!key.isValid()) 46 throw new RuntimeException("Key is not valid"); 47 if (key.watchable() != dir) 48 throw new RuntimeException("Unexpected watchable"); 49 } 50 51 static void takeExpectedKey(WatchService watcher, WatchKey expected) { 52 System.out.println("take events..."); 53 WatchKey key; 54 try { 55 key = watcher.take(); 56 } catch (InterruptedException x) { stm32_timer_get_count(struct udevice * dev)57 // not expected 58 throw new RuntimeException(x); 59 } 60 if (key != expected) 61 throw new RuntimeException("removed unexpected key"); 62 } 63 64 static void checkExpectedEvent(Iterable<WatchEvent<?>> events, stm32_timer_probe(struct udevice * dev)65 WatchEvent.Kind<?> expectedKind, 66 Object expectedContext) 67 { 68 WatchEvent<?> event = events.iterator().next(); 69 System.out.format("got event: type=%s, count=%d, context=%s\n", 70 event.kind(), event.count(), event.context()); 71 if (event.kind() != expectedKind) 72 throw new RuntimeException("unexpected event"); 73 if (!expectedContext.equals(event.context())) 74 throw new RuntimeException("unexpected context"); 75 } 76 77 /** 78 * Simple test of each of the standard events 79 */ 80 static void testEvents(Path dir) throws IOException { 81 System.out.println("-- Standard Events --"); 82 83 FileSystem fs = FileSystems.getDefault(); 84 Path name = fs.getPath("foo"); 85 86 try (WatchService watcher = fs.newWatchService()) { 87 // --- ENTRY_CREATE --- 88 89 // register for event 90 System.out.format("register %s for ENTRY_CREATE\n", dir); 91 WatchKey myKey = dir.register(watcher, 92 new WatchEvent.Kind<?>[]{ ENTRY_CREATE }); 93 checkKey(myKey, dir); 94 95 // create file 96 Path file = dir.resolve("foo"); 97 System.out.format("create %s\n", file); 98 Files.createFile(file); 99 100 // remove key and check that we got the ENTRY_CREATE event 101 takeExpectedKey(watcher, myKey); 102 checkExpectedEvent(myKey.pollEvents(), 103 StandardWatchEventKinds.ENTRY_CREATE, name); 104 105 System.out.println("reset key"); 106 if (!myKey.reset()) 107 throw new RuntimeException("key has been cancalled"); 108 109 System.out.println("OKAY"); 110 111 // --- ENTRY_DELETE --- 112 113 System.out.format("register %s for ENTRY_DELETE\n", dir); 114 WatchKey deleteKey = dir.register(watcher, 115 new WatchEvent.Kind<?>[]{ ENTRY_DELETE }); 116 if (deleteKey != myKey) 117 throw new RuntimeException("register did not return existing key"); 118 checkKey(deleteKey, dir); 119 120 System.out.format("delete %s\n", file); 121 Files.delete(file); 122 takeExpectedKey(watcher, myKey); 123 checkExpectedEvent(myKey.pollEvents(), 124 StandardWatchEventKinds.ENTRY_DELETE, name); 125 126 System.out.println("reset key"); 127 if (!myKey.reset()) 128 throw new RuntimeException("key has been cancalled"); 129 130 System.out.println("OKAY"); 131 132 // create the file for the next test 133 Files.createFile(file); 134 135 // --- ENTRY_MODIFY --- 136 137 System.out.format("register %s for ENTRY_MODIFY\n", dir); 138 WatchKey newKey = dir.register(watcher, 139 new WatchEvent.Kind<?>[]{ ENTRY_MODIFY }); 140 if (newKey != myKey) 141 throw new RuntimeException("register did not return existing key"); 142 checkKey(newKey, dir); 143 144 System.out.format("update: %s\n", file); 145 try (OutputStream out = Files.newOutputStream(file, StandardOpenOption.APPEND)) { 146 out.write("I am a small file".getBytes("UTF-8")); 147 } 148 149 // remove key and check that we got the ENTRY_MODIFY event 150 takeExpectedKey(watcher, myKey); 151 checkExpectedEvent(myKey.pollEvents(), 152 StandardWatchEventKinds.ENTRY_MODIFY, name); 153 System.out.println("OKAY"); 154 155 // done 156 Files.delete(file); 157 } 158 } 159 160 /** 161 * Check that a cancelled key will never be queued 162 */ 163 static void testCancel(Path dir) throws IOException { 164 System.out.println("-- Cancel --"); 165 166 try (WatchService watcher = FileSystems.getDefault().newWatchService()) { 167 168 System.out.format("register %s for events\n", dir); 169 WatchKey myKey = dir.register(watcher, 170 new WatchEvent.Kind<?>[]{ ENTRY_CREATE }); 171 checkKey(myKey, dir); 172 173 System.out.println("cancel key"); 174 myKey.cancel(); 175 176 // create a file in the directory 177 Path file = dir.resolve("mars"); 178 System.out.format("create: %s\n", file); 179 Files.createFile(file); 180 181 // poll for keys - there will be none 182 System.out.println("poll..."); 183 try { 184 WatchKey key = watcher.poll(3000, TimeUnit.MILLISECONDS); 185 if (key != null) 186 throw new RuntimeException("key should not be queued"); 187 } catch (InterruptedException x) { 188 throw new RuntimeException(x); 189 } 190 191 // done 192 Files.delete(file); 193 194 System.out.println("OKAY"); 195 } 196 } 197 198 /** 199 * Check that deleting a registered directory causes the key to be 200 * cancelled and queued. 201 */ 202 static void testAutomaticCancel(Path dir) throws IOException { 203 System.out.println("-- Automatic Cancel --"); 204 205 Path subdir = Files.createDirectory(dir.resolve("bar")); 206 207 try (WatchService watcher = FileSystems.getDefault().newWatchService()) { 208 209 System.out.format("register %s for events\n", subdir); 210 WatchKey myKey = subdir.register(watcher, 211 new WatchEvent.Kind<?>[]{ ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY }); 212 213 System.out.format("delete: %s\n", subdir); 214 Files.delete(subdir); 215 takeExpectedKey(watcher, myKey); 216 217 System.out.println("reset key"); 218 if (myKey.reset()) 219 throw new RuntimeException("Key was not cancelled"); 220 if (myKey.isValid()) 221 throw new RuntimeException("Key is still valid"); 222 223 System.out.println("OKAY"); 224 225 } 226 } 227 228 /** 229 * Asynchronous close of watcher causes blocked threads to wakeup 230 */ 231 static void testWakeup(Path dir) throws IOException { 232 System.out.println("-- Wakeup Tests --"); 233 final WatchService watcher = FileSystems.getDefault().newWatchService(); 234 Runnable r = new Runnable() { 235 public void run() { 236 try { 237 Thread.sleep(5000); 238 System.out.println("close WatchService..."); 239 watcher.close(); 240 } catch (InterruptedException x) { 241 x.printStackTrace(); 242 } catch (IOException x) { 243 x.printStackTrace(); 244 } 245 } 246 }; 247 248 // start thread to close watch service after delay 249 new Thread(r).start(); 250 251 try { 252 System.out.println("take..."); 253 watcher.take(); 254 throw new RuntimeException("ClosedWatchServiceException not thrown"); 255 } catch (InterruptedException x) { 256 throw new RuntimeException(x); 257 } catch (ClosedWatchServiceException x) { 258 System.out.println("ClosedWatchServiceException thrown"); 259 } 260 261 System.out.println("OKAY"); 262 } 263 264 /** 265 * Simple test to check exceptions and other cases 266 */ 267 @SuppressWarnings("unchecked") 268 static void testExceptions(Path dir) throws IOException { 269 System.out.println("-- Exceptions and other simple tests --"); 270 271 WatchService watcher = FileSystems.getDefault().newWatchService(); 272 try { 273 274 // Poll tests 275 276 WatchKey key; 277 System.out.println("poll..."); 278 key = watcher.poll(); 279 if (key != null) 280 throw new RuntimeException("no keys registered"); 281 282 System.out.println("poll with timeout..."); 283 try { 284 long start = System.nanoTime(); 285 key = watcher.poll(3000, TimeUnit.MILLISECONDS); 286 if (key != null) 287 throw new RuntimeException("no keys registered"); 288 long waited = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); 289 if (waited < 2900) 290 throw new RuntimeException("poll was too short"); 291 } catch (InterruptedException x) { 292 throw new RuntimeException(x); 293 } 294 295 // IllegalArgumentException 296 System.out.println("IllegalArgumentException tests..."); 297 try { 298 dir.register(watcher /*empty event list*/); 299 throw new RuntimeException("IllegalArgumentException not thrown"); 300 } catch (IllegalArgumentException x) { 301 } 302 try { 303 // OVERFLOW is ignored so this is equivalent to the empty set 304 dir.register(watcher, OVERFLOW); 305 throw new RuntimeException("IllegalArgumentException not thrown"); 306 } catch (IllegalArgumentException x) { 307 } 308 try { 309 // OVERFLOW is ignored even if specified multiple times 310 dir.register(watcher, OVERFLOW, OVERFLOW); 311 throw new RuntimeException("IllegalArgumentException not thrown"); 312 } catch (IllegalArgumentException x) { 313 } 314 315 // UnsupportedOperationException 316 try { 317 dir.register(watcher, 318 new WatchEvent.Kind<Object>() { 319 @Override public String name() { return "custom"; } 320 @Override public Class<Object> type() { return Object.class; } 321 }); 322 throw new RuntimeException("UnsupportedOperationException not thrown"); 323 } catch (UnsupportedOperationException x) { 324 } 325 try { 326 dir.register(watcher, 327 new WatchEvent.Kind<?>[]{ ENTRY_CREATE }, 328 new WatchEvent.Modifier() { 329 @Override public String name() { return "custom"; } 330 }); 331 throw new RuntimeException("UnsupportedOperationException not thrown"); 332 } catch (UnsupportedOperationException x) { 333 } 334 335 // NullPointerException 336 System.out.println("NullPointerException tests..."); 337 try { 338 dir.register(null, ENTRY_CREATE); 339 throw new RuntimeException("NullPointerException not thrown"); 340 } catch (NullPointerException x) { 341 } 342 try { 343 dir.register(watcher, new WatchEvent.Kind<?>[]{ null }); 344 throw new RuntimeException("NullPointerException not thrown"); 345 } catch (NullPointerException x) { 346 } 347 try { 348 dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE }, 349 (WatchEvent.Modifier)null); 350 throw new RuntimeException("NullPointerException not thrown"); 351 } catch (NullPointerException x) { 352 } 353 } finally { 354 watcher.close(); 355 } 356 357 // -- ClosedWatchServiceException -- 358 359 System.out.println("ClosedWatchServiceException tests..."); 360 361 try { 362 watcher.poll(); 363 throw new RuntimeException("ClosedWatchServiceException not thrown"); 364 } catch (ClosedWatchServiceException x) { 365 } 366 367 // assume that poll throws exception immediately 368 long start = System.nanoTime(); 369 try { 370 watcher.poll(10000, TimeUnit.MILLISECONDS); 371 throw new RuntimeException("ClosedWatchServiceException not thrown"); 372 } catch (InterruptedException x) { 373 throw new RuntimeException(x); 374 } catch (ClosedWatchServiceException x) { 375 long waited = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); 376 if (waited > 5000) 377 throw new RuntimeException("poll was too long"); 378 } 379 380 try { 381 watcher.take(); 382 throw new RuntimeException("ClosedWatchServiceException not thrown"); 383 } catch (InterruptedException x) { 384 throw new RuntimeException(x); 385 } catch (ClosedWatchServiceException x) { 386 } 387 388 try { 389 dir.register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_CREATE }); 390 throw new RuntimeException("ClosedWatchServiceException not thrown"); 391 } catch (ClosedWatchServiceException x) { 392 } 393 394 System.out.println("OKAY"); 395 } 396 397 /** 398 * Test that directory can be registered with more than one watch service 399 * and that events don't interfere with each other 400 */ 401 static void testTwoWatchers(Path dir) throws IOException { 402 System.out.println("-- Two watchers test --"); 403 404 FileSystem fs = FileSystems.getDefault(); 405 WatchService watcher1 = fs.newWatchService(); 406 WatchService watcher2 = fs.newWatchService(); 407 try { 408 Path name1 = fs.getPath("gus1"); 409 Path name2 = fs.getPath("gus2"); 410 411 // create gus1 412 Path file1 = dir.resolve(name1); 413 System.out.format("create %s\n", file1); 414 Files.createFile(file1); 415 416 // register with both watch services (different events) 417 System.out.println("register for different events"); 418 WatchKey key1 = dir.register(watcher1, 419 new WatchEvent.Kind<?>[]{ ENTRY_CREATE }); 420 WatchKey key2 = dir.register(watcher2, 421 new WatchEvent.Kind<?>[]{ ENTRY_DELETE }); 422 423 if (key1 == key2) 424 throw new RuntimeException("keys should be different"); 425 426 // create gus2 427 Path file2 = dir.resolve(name2); 428 System.out.format("create %s\n", file2); 429 Files.createFile(file2); 430 431 // check that key1 got ENTRY_CREATE 432 takeExpectedKey(watcher1, key1); 433 checkExpectedEvent(key1.pollEvents(), 434 StandardWatchEventKinds.ENTRY_CREATE, name2); 435 436 // check that key2 got zero events 437 WatchKey key = watcher2.poll(); 438 if (key != null) 439 throw new RuntimeException("key not expected"); 440 441 // delete gus1 442 Files.delete(file1); 443 444 // check that key2 got ENTRY_DELETE 445 takeExpectedKey(watcher2, key2); 446 checkExpectedEvent(key2.pollEvents(), 447 StandardWatchEventKinds.ENTRY_DELETE, name1); 448 449 // check that key1 got zero events 450 key = watcher1.poll(); 451 if (key != null) 452 throw new RuntimeException("key not expected"); 453 454 // reset for next test 455 key1.reset(); 456 key2.reset(); 457 458 // change registration with watcher2 so that they are both 459 // registered for the same event 460 System.out.println("register for same event"); 461 key2 = dir.register(watcher2, new WatchEvent.Kind<?>[]{ ENTRY_CREATE }); 462 463 // create file and key2 should be queued 464 System.out.format("create %s\n", file1); 465 Files.createFile(file1); 466 takeExpectedKey(watcher2, key2); 467 checkExpectedEvent(key2.pollEvents(), 468 StandardWatchEventKinds.ENTRY_CREATE, name1); 469 470 System.out.println("OKAY"); 471 472 } finally { 473 watcher2.close(); 474 watcher1.close(); 475 } 476 } 477 478 /** 479 * Test that thread interruped status is preserved upon a call 480 * to register() 481 */ 482 static void testThreadInterrupt(Path dir) throws IOException { 483 System.out.println("-- Thread interrupted status test --"); 484 485 FileSystem fs = FileSystems.getDefault(); 486 Thread curr = Thread.currentThread(); 487 try (WatchService watcher = fs.newWatchService()) { 488 System.out.println("interrupting current thread"); 489 curr.interrupt(); 490 dir.register(watcher, ENTRY_CREATE); 491 if (!curr.isInterrupted()) 492 throw new RuntimeException("thread should remain interrupted"); 493 System.out.println("current thread is still interrupted"); 494 System.out.println("OKAY"); 495 } finally { 496 curr.interrupted(); 497 } 498 } 499 500 public static void main(String[] args) throws IOException { 501 Path dir = TestUtil.createTemporaryDirectory(); 502 try { 503 504 testEvents(dir); 505 testCancel(dir); 506 testAutomaticCancel(dir); 507 testWakeup(dir); 508 testExceptions(dir); 509 testTwoWatchers(dir); 510 testThreadInterrupt(dir); 511 512 } finally { 513 TestUtil.removeAll(dir); 514 } 515 } 516 } 517