|
23 | 23 | import static org.junit.Assert.assertFalse; |
24 | 24 | import static org.junit.Assert.assertTrue; |
25 | 25 | import static org.junit.Assume.assumeFalse; |
| 26 | +import static org.mockito.ArgumentMatchers.any; |
| 27 | +import static org.mockito.ArgumentMatchers.eq; |
26 | 28 | import static org.mockito.Mockito.doThrow; |
27 | 29 | import static org.mockito.Mockito.mock; |
| 30 | +import static org.mockito.Mockito.never; |
28 | 31 | import static org.mockito.Mockito.verify; |
29 | 32 | import static org.mockito.Mockito.when; |
30 | 33 |
|
|
35 | 38 | import java.nio.file.NoSuchFileException; |
36 | 39 | import java.nio.file.Path; |
37 | 40 | import java.nio.file.Paths; |
| 41 | +import java.util.ArrayList; |
38 | 42 | import java.util.List; |
| 43 | +import org.apache.beam.sdk.io.FileSystem.LineageLevel; |
39 | 44 | import org.apache.beam.sdk.io.fs.CreateOptions; |
40 | 45 | import org.apache.beam.sdk.io.fs.MatchResult; |
41 | 46 | import org.apache.beam.sdk.io.fs.MoveOptions; |
|
54 | 59 | import org.junit.rules.TemporaryFolder; |
55 | 60 | import org.junit.runner.RunWith; |
56 | 61 | import org.junit.runners.JUnit4; |
| 62 | +import org.mockito.MockedStatic; |
| 63 | +import org.mockito.Mockito; |
57 | 64 |
|
58 | 65 | /** Tests for {@link FileSystems}. */ |
59 | 66 | @RunWith(JUnit4.class) |
@@ -337,6 +344,97 @@ public void testMatchNewDirectory() { |
337 | 344 | } |
338 | 345 | } |
339 | 346 |
|
| 347 | + @Test |
| 348 | + public void testReportSourceLineageFewFiles() { |
| 349 | + List<ResourceId> resources = new ArrayList<>(); |
| 350 | + for (int i = 0; i < 5; i++) { |
| 351 | + resources.add(mockResourceId("/dir/file" + i, "/dir/")); |
| 352 | + } |
| 353 | + |
| 354 | + try (MockedStatic<FileSystems> mocked = |
| 355 | + Mockito.mockStatic(FileSystems.class, Mockito.CALLS_REAL_METHODS)) { |
| 356 | + mocked |
| 357 | + .when(() -> FileSystems.reportSourceLineage(any(ResourceId.class))) |
| 358 | + .thenAnswer(inv -> null); |
| 359 | + mocked |
| 360 | + .when(() -> FileSystems.reportSourceLineage(any(ResourceId.class), any())) |
| 361 | + .thenAnswer(inv -> null); |
| 362 | + |
| 363 | + FileSystems.reportSourceLineage(resources); |
| 364 | + |
| 365 | + for (ResourceId r : resources) { |
| 366 | + mocked.verify(() -> FileSystems.reportSourceLineage(r)); |
| 367 | + } |
| 368 | + } |
| 369 | + } |
| 370 | + |
| 371 | + @Test |
| 372 | + public void testReportSourceLineageManyFilesFewDirs() { |
| 373 | + ResourceId dir = mockResourceId("/dir/", null); |
| 374 | + List<ResourceId> resources = new ArrayList<>(); |
| 375 | + for (int i = 0; i < 150; i++) { |
| 376 | + resources.add(mockResourceId("/dir/file" + i, dir)); |
| 377 | + } |
| 378 | + |
| 379 | + try (MockedStatic<FileSystems> mocked = |
| 380 | + Mockito.mockStatic(FileSystems.class, Mockito.CALLS_REAL_METHODS)) { |
| 381 | + mocked |
| 382 | + .when(() -> FileSystems.reportSourceLineage(any(ResourceId.class))) |
| 383 | + .thenAnswer(inv -> null); |
| 384 | + mocked |
| 385 | + .when(() -> FileSystems.reportSourceLineage(any(ResourceId.class), any())) |
| 386 | + .thenAnswer(inv -> null); |
| 387 | + |
| 388 | + FileSystems.reportSourceLineage(resources); |
| 389 | + |
| 390 | + // Should report the unique directory, not individual files |
| 391 | + mocked.verify(() -> FileSystems.reportSourceLineage(dir)); |
| 392 | + mocked.verify( |
| 393 | + () -> FileSystems.reportSourceLineage(any(ResourceId.class), any(LineageLevel.class)), |
| 394 | + never()); |
| 395 | + } |
| 396 | + } |
| 397 | + |
| 398 | + @Test |
| 399 | + public void testReportSourceLineageManyFilesManyDirs() { |
| 400 | + List<ResourceId> resources = new ArrayList<>(); |
| 401 | + for (int i = 0; i < 150; i++) { |
| 402 | + ResourceId dir = mockResourceId("/dir" + i + "/", null); |
| 403 | + resources.add(mockResourceId("/dir" + i + "/file", dir)); |
| 404 | + } |
| 405 | + |
| 406 | + try (MockedStatic<FileSystems> mocked = |
| 407 | + Mockito.mockStatic(FileSystems.class, Mockito.CALLS_REAL_METHODS)) { |
| 408 | + mocked |
| 409 | + .when(() -> FileSystems.reportSourceLineage(any(ResourceId.class))) |
| 410 | + .thenAnswer(inv -> null); |
| 411 | + mocked |
| 412 | + .when(() -> FileSystems.reportSourceLineage(any(ResourceId.class), any())) |
| 413 | + .thenAnswer(inv -> null); |
| 414 | + |
| 415 | + FileSystems.reportSourceLineage(resources); |
| 416 | + |
| 417 | + // Should fall back to TOP_LEVEL reporting |
| 418 | + mocked.verify( |
| 419 | + () -> FileSystems.reportSourceLineage(any(ResourceId.class), eq(LineageLevel.TOP_LEVEL))); |
| 420 | + // Should not report individual files or directories at FILE level |
| 421 | + mocked.verify(() -> FileSystems.reportSourceLineage(any(ResourceId.class)), never()); |
| 422 | + } |
| 423 | + } |
| 424 | + |
| 425 | + private ResourceId mockResourceId(String path, Object dir) { |
| 426 | + ResourceId resourceId = mock(ResourceId.class); |
| 427 | + when(resourceId.toString()).thenReturn(path); |
| 428 | + if (dir instanceof String) { |
| 429 | + ResourceId dirId = mock(ResourceId.class); |
| 430 | + when(dirId.toString()).thenReturn((String) dir); |
| 431 | + when(resourceId.getCurrentDirectory()).thenReturn(dirId); |
| 432 | + } else if (dir instanceof ResourceId) { |
| 433 | + when(resourceId.getCurrentDirectory()).thenReturn((ResourceId) dir); |
| 434 | + } |
| 435 | + return resourceId; |
| 436 | + } |
| 437 | + |
340 | 438 | private static List<ResourceId> toResourceIds(List<Path> paths, final boolean isDirectory) { |
341 | 439 | return FluentIterable.from(paths) |
342 | 440 | .transform(path -> (ResourceId) LocalResourceId.fromPath(path, isDirectory)) |
|
0 commit comments