1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17package libcore.java.nio.file; 18 19import com.sun.nio.file.ExtendedWatchEventModifier; 20 21import org.junit.After; 22import org.junit.Before; 23import org.junit.Rule; 24import org.junit.Test; 25 26import java.io.File; 27import java.io.IOException; 28import java.net.URI; 29import java.net.URISyntaxException; 30import java.nio.file.ClosedWatchServiceException; 31import java.nio.file.FileSystems; 32import java.nio.file.Files; 33import java.nio.file.LinkOption; 34import java.nio.file.NoSuchFileException; 35import java.nio.file.NotDirectoryException; 36import java.nio.file.Path; 37import java.nio.file.Paths; 38import java.nio.file.WatchEvent; 39import java.nio.file.WatchKey; 40import java.nio.file.WatchService; 41import java.util.ArrayList; 42import java.util.Iterator; 43import java.util.List; 44 45import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; 46import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; 47import static junit.framework.TestCase.assertFalse; 48import static junit.framework.TestCase.assertNull; 49import static junit.framework.TestCase.assertTrue; 50import static org.junit.Assert.assertEquals; 51import static org.junit.Assert.fail; 52 53public class LinuxPathTest { 54 55 @Rule 56 public FilesSetup filesSetup = new FilesSetup(); 57 58 /** 59 * CTS doesn't allow creating files in the test directory, however, Vogar allows creation of 60 * new files in the test directory. Therefore, for the tests which don't require write 61 * permission, dummyPath would serve the purpose, however, for the others, {@link 62 * FilesSetup#getTestDirPath()} should be used. 63 */ 64 private static final Path dummyPath = Paths.get("dummyPath"); 65 66 @Test 67 public void test_getFileSystem() { 68 assertTrue(dummyPath.getFileSystem().provider() instanceof 69 sun.nio.fs.LinuxFileSystemProvider); 70 } 71 72 @Test 73 public void test_isAbsolute() { 74 assertFalse(dummyPath.isAbsolute()); 75 Path absolutePath = dummyPath.toAbsolutePath(); 76 assertTrue(absolutePath.isAbsolute()); 77 } 78 79 @Test 80 public void test_getRoot() { 81 assertEquals(Paths.get("/"), dummyPath.toAbsolutePath().getRoot()); 82 assertNull(dummyPath.getRoot()); 83 } 84 85 @Test 86 public void test_getFileName() { 87 assertEquals(dummyPath, dummyPath.getFileName()); 88 assertEquals(dummyPath, dummyPath.toAbsolutePath().getFileName()); 89 assertNull(dummyPath.getRoot()); 90 assertEquals(Paths.get("data"), Paths.get("/data").getFileName()); 91 assertEquals(Paths.get("data"), Paths.get("/data/").getFileName()); 92 assertEquals(Paths.get(".."), Paths.get("/data/dir1/..").getFileName()); 93 } 94 95 @Test 96 public void test_getParent() { 97 assertNull(dummyPath.getParent()); 98 assertEquals(Paths.get("rootDir"), Paths.get("rootDir/dir").getParent()); 99 } 100 101 @Test 102 public void test_getNameCount() { 103 assertEquals(0, Paths.get("/").getNameCount()); 104 assertEquals(1, Paths.get("/dir").getNameCount()); 105 assertEquals(2, Paths.get("/dir/dir").getNameCount()); 106 assertEquals(2, Paths.get("/dir/..").getNameCount()); 107 } 108 109 @Test 110 public void test_getName() { 111 assertEquals(Paths.get("t"), Paths.get("/t/t1/t2/t3").getName(0)); 112 assertEquals(Paths.get("t2"), Paths.get("/t/t1/t2/t3").getName(2)); 113 assertEquals(Paths.get("t3"), Paths.get("/t/t1/t2/t3").getName(3)); 114 115 // Without root. 116 assertEquals(Paths.get("t3"), Paths.get("t/t1/t2/t3").getName(3)); 117 118 // Invalid index. 119 try { 120 Paths.get("/t/t1/t2/t3").getName(4); 121 fail(); 122 } catch (IllegalArgumentException expected) {} 123 124 // Negative index value. 125 try { 126 Paths.get("/t/t1/t2/t3").getName(-1); 127 fail(); 128 } catch (IllegalArgumentException expected) {} 129 } 130 131 @Test 132 public void test_subPath() { 133 assertEquals(Paths.get("t1/t2"), Paths.get("t1/t2/t3").subpath(0, 2)); 134 assertEquals(Paths.get("t2"), Paths.get("t1/t2/t3").subpath(1, 2)); 135 136 try { 137 Paths.get("t1/t2/t3").subpath(1, 1); 138 fail(); 139 } catch (IllegalArgumentException expected) {} 140 141 try { 142 assertEquals(Paths.get("t1/t1"), Paths.get("t1/t2/t3").subpath(1, 0)); 143 fail(); 144 } catch (IllegalArgumentException expected) {} 145 146 try { 147 assertEquals(Paths.get("t1/t1"), Paths.get("t1/t2/t3").subpath(1, 5)); 148 fail(); 149 } catch (IllegalArgumentException expected) {} 150 } 151 152 @Test 153 public void test_startsWith$String() { 154 assertTrue(Paths.get("t1/t2").startsWith("t1")); 155 assertTrue(dummyPath.toAbsolutePath().startsWith("/")); 156 assertTrue(Paths.get("t1/t2/t3").startsWith("t1/t2")); 157 assertFalse(Paths.get("t1/t2").startsWith("t2")); 158 } 159 160 @Test(expected = NullPointerException.class) 161 public void test_startsWith$String_NPE() { 162 filesSetup.getTestPath().startsWith((String) null); 163 } 164 165 @Test 166 public void test_startsWith$Path() { 167 assertTrue(Paths.get("t1/t2").startsWith(Paths.get("t1"))); 168 assertTrue(dummyPath.toAbsolutePath().startsWith(Paths.get("/"))); 169 assertTrue(Paths.get("t1/t2/t3").startsWith(Paths.get("t1/t2"))); 170 assertFalse(Paths.get("t1/t2").startsWith(Paths.get("t2"))); 171 } 172 173 @Test(expected = NullPointerException.class) 174 public void test_startsWith$Path_NPE() { 175 filesSetup.getTestPath().startsWith((Path) null); 176 } 177 178 @Test 179 public void test_endsWith$Path() { 180 assertTrue(Paths.get("t1/t2").endsWith(Paths.get("t2"))); 181 assertTrue(Paths.get("t1/t2/t3").endsWith(Paths.get("t2/t3"))); 182 assertFalse(Paths.get("t1/t2").endsWith(Paths.get("t1"))); 183 assertTrue(Paths.get("/").endsWith(Paths.get("/"))); 184 assertFalse(Paths.get("/data/").endsWith(Paths.get("/"))); 185 } 186 187 @Test(expected = NullPointerException.class) 188 public void test_endsWith$Path_NPE() { 189 filesSetup.getTestPath().endsWith((Path)null); 190 } 191 192 @Test 193 public void test_endsWith$String() { 194 assertTrue(Paths.get("t1/t2").endsWith("t2")); 195 assertTrue(Paths.get("t1/t2/t3").endsWith("t2/t3")); 196 assertFalse(Paths.get("t1/t2").endsWith("t1")); 197 assertTrue(Paths.get("/").endsWith("/")); 198 assertFalse(Paths.get("/data/").endsWith("/")); 199 } 200 201 @Test(expected = NullPointerException.class) 202 public void test_endsWith$String_NPE() { 203 filesSetup.getTestPath().endsWith((String)null); 204 } 205 206 @Test 207 public void test_normalize() { 208 assertEquals(Paths.get("t2/t3"), Paths.get("t1/../t2/t3").normalize()); 209 assertEquals(Paths.get("../t2/t3"), Paths.get("t1/../../t2/t3").normalize()); 210 assertEquals(Paths.get("t1/t2/t3"), Paths.get("t1/./t2/t3").normalize()); 211 assertEquals(Paths.get("t1/t2/t3"), Paths.get("t1/././t2/t3").normalize()); 212 assertEquals(Paths.get("t1/t2/t3"), Paths.get("t1/././t2/t3").normalize()); 213 assertEquals(Paths.get("t1"), Paths.get("t1/")); 214 } 215 216 @Test 217 public void test_resolve$Path() { 218 Path p = Paths.get("p"); 219 Path p1 = Paths.get("p1"); 220 Path p1p = Paths.get("p1/p"); 221 assertEquals(p1p, p1.resolve(p)); 222 assertEquals(p.toAbsolutePath(), p1.resolve(p.toAbsolutePath())); 223 assertEquals(p1p.toAbsolutePath(), p1.toAbsolutePath().resolve(p)); 224 } 225 226 @Test(expected = NullPointerException.class) 227 public void test_resolve$Path_NPE() { 228 dummyPath.resolve((Path)null); 229 } 230 231 @Test 232 public void test_resolve$String() { 233 Path p = Paths.get("p"); 234 Path p1 = Paths.get("p1"); 235 Path p1p = Paths.get("p1/p"); 236 assertEquals(p1p, p1.resolve("p")); 237 assertEquals(p1p.toAbsolutePath(), p1.toAbsolutePath().resolve("p")); 238 } 239 240 @Test(expected = NullPointerException.class) 241 public void test_resolve$String_NPE() { 242 dummyPath.resolve((String)null); 243 } 244 245 @Test 246 public void test_resolveSibling$Path() { 247 Path c2 = Paths.get("c2"); 248 Path parent_c1 = Paths.get("parent/c1"); 249 Path parent_c2 = Paths.get("parent/c2"); 250 assertEquals(parent_c2, parent_c1.resolveSibling(c2)); 251 assertEquals(c2.toAbsolutePath(), parent_c1.resolveSibling(c2.toAbsolutePath())); 252 assertEquals(parent_c2.toAbsolutePath(), parent_c1.toAbsolutePath().resolveSibling(c2)); 253 } 254 255 @Test(expected = NullPointerException.class) 256 public void test_resolveSibling$String_Path() { 257 dummyPath.resolveSibling((Path) null); 258 } 259 260 @Test 261 public void test_resolveSibling$String() { 262 Path c2 = Paths.get("c2"); 263 Path parent_c1 = Paths.get("parent/c1"); 264 Path parent_c2 = Paths.get("parent/c2"); 265 assertEquals(parent_c2, parent_c1.resolveSibling(c2.toString())); 266 assertEquals(c2.toAbsolutePath(), parent_c1.resolveSibling(c2.toAbsolutePath().toString())); 267 assertEquals(parent_c2.toAbsolutePath(), parent_c1.toAbsolutePath() 268 .resolveSibling(c2.toString())); 269 } 270 271 @Test(expected = NullPointerException.class) 272 public void test_resolveSibling$String_NPE() { 273 dummyPath.resolveSibling((String)null); 274 } 275 276 @Test 277 public void test_relativize() { 278 Path p1 = Paths.get("t1/t2/t3"); 279 Path p2 = Paths.get("t1/t2"); 280 assertEquals(Paths.get(".."), p1.relativize(p2)); 281 assertEquals(Paths.get(".."), p1.toAbsolutePath().relativize(p2.toAbsolutePath())); 282 assertEquals(Paths.get("t3"), p2.relativize(p1)); 283 284 // Can't be relativized as either of the paths are relative and the other is not. 285 try { 286 p1.relativize(p2.toAbsolutePath()); 287 fail(); 288 } catch (IllegalArgumentException expected) {} 289 290 try { 291 p1.toAbsolutePath().relativize(p2); 292 fail(); 293 } catch (IllegalArgumentException expected) {} 294 } 295 296 @Test(expected = NullPointerException.class) 297 public void test_relativize_NPE() { 298 dummyPath.relativize(null); 299 } 300 301 @Test 302 public void test_toURI() throws URISyntaxException { 303 assertEquals(new URI("file://" + dummyPath.toAbsolutePath().toString()), dummyPath.toUri()); 304 assertEquals(new URI("file:///"), Paths.get("/").toUri()); 305 assertEquals(new URI("file:///dir/.."), Paths.get(("/dir/..")).toUri()); 306 assertEquals(new URI("file:///../"), Paths.get(("/..")).toUri()); 307 assertEquals(new URI("file:///dir/.."), Paths.get(("/dir/..")).toUri()); 308 assertEquals(new URI("file:///./"), Paths.get(("/.")).toUri()); 309 assertEquals(new URI("file:///dir/."), Paths.get(("/dir/.")).toUri()); 310 // For unicode characters. 311 assertEquals(new URI("file:///%E0%A4%B0%E0%A4%BE%E0%A4%B9."), Paths.get(("/राह.")).toUri()); 312 } 313 314 @Test 315 public void test_toAbsolutePath() { 316 assertFalse(dummyPath.isAbsolute()); 317 assertTrue(dummyPath.toAbsolutePath().isAbsolute()); 318 } 319 320 @Test 321 public void test_toRealPath() throws IOException { 322 // When file doesn't exist. 323 try { 324 dummyPath.toRealPath(); 325 fail(); 326 } catch (NoSuchFileException expected) {} 327 Files.createFile(filesSetup.getTestPath()); 328 Path realPath = filesSetup.getTestPath().toRealPath(); 329 assertTrue(Files.isSameFile(filesSetup.getTestPath().toAbsolutePath(), realPath)); 330 assertTrue(realPath.isAbsolute()); 331 assertFalse(Files.isSymbolicLink(realPath)); 332 333 Path dir = Paths.get(filesSetup.getTestDir(), "dir1/dir2"); 334 Path file = Paths.get(filesSetup.getTestDir(), "dir1/dir2/../../file"); 335 Files.createDirectories(dir); 336 Files.createFile(file); 337 realPath = file.toRealPath(); 338 assertTrue(Files.isSameFile(file.toAbsolutePath(), realPath)); 339 assertTrue(realPath.isAbsolute()); 340 assertFalse(Files.isSymbolicLink(realPath)); 341 342 // Sym links. 343 Path symLink = Paths.get(filesSetup.getTestDir(), "symlink"); 344 Files.createSymbolicLink(symLink, filesSetup.getTestPath().toAbsolutePath()); 345 realPath = symLink.toRealPath(); 346 assertTrue(Files.isSameFile(symLink, realPath)); 347 assertTrue(realPath.isAbsolute()); 348 assertFalse(Files.isSymbolicLink(realPath)); 349 350 realPath = symLink.toRealPath(LinkOption.NOFOLLOW_LINKS); 351 assertTrue(Files.isSameFile(symLink, realPath)); 352 assertTrue(realPath.isAbsolute()); 353 assertTrue(Files.isSymbolicLink(realPath)); 354 } 355 356 @Test 357 public void test_toFile() { 358 File file = dummyPath.toFile(); 359 assertEquals(dummyPath.toAbsolutePath().toString(), file.getAbsolutePath()); 360 } 361 362 @Test 363 public void test_register$WatchService$WatchEvent_Kind() throws IOException, 364 InterruptedException { 365 WatchService watchService = FileSystems.getDefault().newWatchService(); 366 WatchEvent.Kind<?>[] events = {ENTRY_CREATE, ENTRY_DELETE}; 367 Path file = Paths.get(filesSetup.getTestDir(), "directory/file"); 368 assertFalse(Files.exists(file)); 369 Path directory = Paths.get(filesSetup.getTestDir(), "directory"); 370 Files.createDirectories(directory); 371 WatchKey key = directory.register(watchService, events); 372 373 // Creating, modifying and deleting the file. 374 Files.createFile(file); 375 assertTrue(Files.exists(file)); 376 // EVENT_MODIFY should not be logged. 377 Files.newOutputStream(file).write("hello".getBytes()); 378 Files.delete(file); 379 assertFalse(Files.exists(file)); 380 381 assertTrue(key.isValid()); 382 assertEquals(directory, key.watchable()); 383 List<WatchEvent<?>> eventList = new ArrayList<>(); 384 385 // Wait for the events to be recorded by WatchService. 386 while(true) { 387 eventList.addAll(key.pollEvents()); 388 if (eventList.size() == 2) break; 389 Thread.sleep(1000); 390 } 391 // Wait for the events to be recorded by watchService. 392 assertEquals(2, eventList.size()); 393 assertEquals(ENTRY_CREATE, eventList.get(0).kind()); 394 assertEquals(ENTRY_DELETE, eventList.get(1).kind()); 395 } 396 397 @Test 398 public void test_register$WatchService$WatchEvent_Kind_NPE() throws IOException, 399 InterruptedException { 400 WatchService watchService = FileSystems.getDefault().newWatchService(); 401 WatchEvent.Kind<?>[] events = {ENTRY_CREATE, ENTRY_DELETE}; 402 Path directory = Paths.get(filesSetup.getTestDir(), "directory"); 403 Files.createDirectories(directory); 404 try { 405 directory.register(null, events); 406 fail(); 407 } catch (NullPointerException expected) {} 408 409 try { 410 directory.register(watchService, (WatchEvent.Kind<?>) null); 411 fail(); 412 } catch (NullPointerException expected) {} 413 } 414 415 @Test 416 public void test_register$WatchService$WatchEvent_Kind_Exception() throws IOException { 417 WatchService watchService = FileSystems.getDefault().newWatchService(); 418 Path directory = Paths.get(filesSetup.getTestDir(), "directory1"); 419 Files.createFile(directory); 420 421 // When file is not a directory. 422 try { 423 directory.register(watchService, ENTRY_CREATE); 424 fail(); 425 } catch (NotDirectoryException expected) {} 426 427 // When the events are not supported. 428 Files.deleteIfExists(directory); 429 Files.createDirectories(directory); 430 WatchEvent.Kind<?>[] events = {new NonStandardEvent<>()}; 431 try { 432 directory.register(watchService, events); 433 fail(); 434 } catch (UnsupportedOperationException expected) {} 435 436 // When the watch service is closed. 437 watchService.close(); 438 try { 439 directory.register(watchService, ENTRY_CREATE); 440 fail(); 441 } catch (ClosedWatchServiceException expected) {} 442 } 443 444 @Test 445 public void test_register$WatchService$WatchEvent_Kind_Exception_NPE() throws IOException { 446 WatchService watchService = FileSystems.getDefault().newWatchService(); 447 Path directory = Paths.get(filesSetup.getTestDir(), "directory1"); 448 Files.createDirectories(directory); 449 450 // When file is not a directory. 451 try { 452 directory.register(null, ENTRY_CREATE); 453 fail(); 454 } catch (NullPointerException expected) {} 455 456 try { 457 directory.register(watchService, null); 458 fail(); 459 } catch (NullPointerException expected) {} 460 } 461 462 @Test 463 public void test_register$WatchService$WatchEvent_Kind$WatchEvent_Modifier() throws IOException 464 { 465 WatchService watchService = FileSystems.getDefault().newWatchService(); 466 WatchEvent.Kind<?>[] events = {ENTRY_CREATE}; 467 Path dirRoot = Paths.get(filesSetup.getTestDir(), "dir"); 468 Files.createDirectories(dirRoot); 469 try { 470 WatchKey key = dirRoot.register(watchService, events, 471 ExtendedWatchEventModifier.FILE_TREE); 472 fail(); 473 } catch (UnsupportedOperationException expected) { 474 assertTrue(expected.getMessage().contains("Modifier not supported")); 475 } 476 } 477 478 @Test 479 public void test_register$WatchService$WatchEvent_Kind$WatchEvent_Modifier_NPE() 480 throws IOException { 481 WatchService watchService = FileSystems.getDefault().newWatchService(); 482 WatchEvent.Kind<?>[] events = {ENTRY_CREATE}; 483 Path dirRoot = Paths.get(filesSetup.getTestDir(), "dir"); 484 Files.createDirectories(dirRoot); 485 try { 486 WatchKey key = dirRoot.register(null, events, 487 ExtendedWatchEventModifier.FILE_TREE); 488 fail(); 489 } catch (NullPointerException expected) {} 490 491 try { 492 WatchKey key = dirRoot.register(watchService, null, 493 ExtendedWatchEventModifier.FILE_TREE); 494 fail(); 495 } catch (NullPointerException expected) {} 496 } 497 498 @Test 499 public void test_iterator() { 500 Path p = Paths.get("f1/f2/f3"); 501 Iterator<Path> pathIterator = p.iterator(); 502 assertEquals(Paths.get("f1"), pathIterator.next()); 503 assertEquals(Paths.get("f2"), pathIterator.next()); 504 assertEquals(Paths.get("f3"), pathIterator.next()); 505 assertFalse(pathIterator.hasNext()); 506 } 507 508 @Test 509 public void test_iterator_hasRoot() { 510 Path p = Paths.get("/f1/f2/f3"); 511 Iterator<Path> pathIterator = p.iterator(); 512 assertEquals(Paths.get("f1"), pathIterator.next()); 513 assertEquals(Paths.get("f2"), pathIterator.next()); 514 assertEquals(Paths.get("f3"), pathIterator.next()); 515 assertFalse(pathIterator.hasNext()); 516 } 517 518 @Test 519 public void test_compareTo() { 520 Path p1 = Paths.get("d/a"); 521 Path p2 = Paths.get("d/b"); 522 assertTrue(p1.compareTo(p2) < 0); 523 assertTrue(p2.compareTo(p1) > 0); 524 assertTrue(p1.compareTo(p1) == 0); 525 } 526 527 @Test(expected = NullPointerException.class) 528 public void test_compareTo_NPE() { 529 filesSetup.getTestPath().compareTo(null); 530 } 531 532 @Test 533 public void test_equals() { 534 Path p1 = Paths.get("a/b"); 535 Path p2 = Paths.get("a/../a/b"); 536 Path p3 = p1.toAbsolutePath(); 537 assertFalse(p1.equals(p2)); 538 assertTrue(p1.equals(p1)); 539 assertFalse(p1.equals(p3)); 540 } 541 542 @Test 543 public void test_equals_NPE() { 544 // Should not throw NPE. 545 filesSetup.getTestPath().equals(null); 546 } 547 548 @Test 549 public void test_hashCode() { 550 Path p1 = Paths.get("f1/f2/f3"); 551 assertEquals(-642657684, p1.hashCode()); 552 553 // With root component. 554 Path p2 = Paths.get("/f1/f2/f3"); 555 assertEquals(306328475, p2.hashCode()); 556 } 557 558 @Test 559 public void test_toString() { 560 Path p = Paths.get("f1/f2/f3"); 561 assertEquals("f1/f2/f3", p.toString()); 562 563 p = Paths.get(""); 564 assertEquals("", p.toString()); 565 566 p = Paths.get(".."); 567 assertEquals("..", p.toString()); 568 569 p = Paths.get("."); 570 assertEquals(".", p.toString()); 571 572 p = Paths.get("dir/"); 573 assertEquals("dir", p.toString()); 574 575 p = Paths.get("/dir"); 576 assertEquals("/dir", p.toString()); 577 } 578 579 private static class NonStandardEvent<T> implements WatchEvent.Kind<T> { 580 581 @Override 582 public String name() { 583 return null; 584 } 585 586 @Override 587 public Class<T> type() { 588 return null; 589 } 590 } 591}