walkFiles consistently relative or absolute#3773
walkFiles consistently relative or absolute#3773chingor13 merged 4 commits intogoogleapis:masterfrom
Conversation
The expected behavior from Files.walkFileTree is that if the starting path is absolute, then all the visited paths are absolute. If the starting path is relative, then all the visited paths are relative. This PR adds a test for this behavior, and shows that our current code fails for an absolute path: it returns a mix of relative and absolute paths. This PR also adds a code change to fix the problem, so the actual behavior matches what is expected. This should fix issue googleapis#3772
pongad
left a comment
There was a problem hiding this comment.
@hzyi-google Do you also want to take a look?
...contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/it/ITGcsNio.java
Outdated
Show resolved
Hide resolved
...contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/it/ITGcsNio.java
Show resolved
Hide resolved
|
Hi. I would think that these modifications, along with the ones in #3775, would allow the following unit test to pass: @Test
public void testWalkFileTree() throws IOException {
Path baseDir = Paths.get(URI.create("gs://bucket/liverpool"));
//Base directory with an ending forwards slash is not passing either
//Path baseDir = Paths.get(URI.create("gs://bucket/liverpool/"));
Path file1 = baseDir.resolve("firmino.player");
Path file2 = baseDir.resolve("salah.player");
Files.createFile(file1);
Files.createFile(file2);
Set<Path> expectedDirs = Sets.newHashSet(baseDir);
Set<Path> expectedFiles = Sets.newHashSet(file1,file2);
final Set<Path> foundDirs = Sets.newHashSet();
final Set<Path> foundFiles = Sets.newHashSet();
FileVisitor<Path> testVisitor = new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
assertThat(foundDirs).doesNotContain(dir);
foundDirs.add(dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
foundFiles.add(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
assertThat(foundDirs).contains(dir);
return FileVisitResult.CONTINUE;
}
};
Files.walkFileTree(baseDir,Sets.newHashSet(FileVisitOption.FOLLOW_LINKS),Integer.MAX_VALUE,testVisitor);
assertThat(foundFiles).containsExactlyElementsIn(expectedFiles);
assertThat(foundDirs).containsExactlyElementsIn(expectedDirs);
}Files.walkFileTree visits the Basedir twice, first without an ending slash, and then with an ending slash. Best regards, |
|
@olifly I see there is a bug in this code snippet: Once I fixed the code snippet, it passed with just the code in this PR. |
Hi. Maybe it's the combination of these two pull requests, but changing the test to insert the expected Paths one at a time into the Sets is not making it pass for me. Files.walkFileTree is still calling preVisitDirectory twice for the base dir, once without a forward slash and once with it. Here's my modified code @Test
public void testWalkFileTree() throws IOException {
Path baseDir = Paths.get(URI.create("gs://bucket/liverpool"));
Path file1 = baseDir.resolve("firmino.player");
Path file2 = baseDir.resolve("salah.player");
Files.createFile(file1);
Files.createFile(file2);
Set<Path> expectedDirs = Sets.newHashSet();
expectedDirs.add(baseDir);
Set<Path> expectedFiles = Sets.newHashSet();
expectedFiles.add(file1);
expectedFiles.add(file2);
final Set<Path> foundDirs = Sets.newHashSet();
final Set<Path> foundFiles = Sets.newHashSet();
FileVisitor<Path> testVisitor = new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
assertThat(foundDirs).doesNotContain(dir);
foundDirs.add(dir);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
foundFiles.add(file);
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
assertThat(foundDirs).contains(dir);
return FileVisitResult.CONTINUE;
}
};
Files.walkFileTree(baseDir,Sets.newHashSet(FileVisitOption.FOLLOW_LINKS),Integer.MAX_VALUE,testVisitor);
assertThat(foundFiles).containsExactlyElementsIn(expectedFiles);
assertThat(foundDirs).containsExactlyElementsIn(expectedDirs);
}The test passes if the baseDir has a forward slash, gs://bucket/liverpool/, but fails on: gs://bucket/liverpool I'm pretty sure Liverpool is not to blame though :) JDK Used: 1.8, u 181. Best Regards, |
chingor13
left a comment
There was a problem hiding this comment.
Looks straight-forward - just a question about the clarity of the test.
...contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/it/ITGcsNio.java
Outdated
Show resolved
Hide resolved
...contrib/google-cloud-nio/src/test/java/com/google/cloud/storage/contrib/nio/it/ITGcsNio.java
Show resolved
Hide resolved
|
@chingor13 the functions returns the folders and files traversed, so the 5 paths are: I added them as comment to the code in case another reader wonders too. (sorry, for some reason GitHub isn't letting me reply to your comment directly). |
|
@jean-philippe-martin - The changes you did to pull request #3775 did indeed solve the issue. Thanks a bunch. Can't wait for these changes to be merged upstream :) Best Regards |
|
@olifly thanks for checking, that's great! I'm glad this works for you now. I see the reviewers have already merged in this PR so we're halfway there! |
|
Thank you @chingor13 ! |
…to v2-rev20250427-2.0.0 (#3773)
…to v2-rev20250427-2.0.0 (#3773)
… to v2.38.0 (#3773) This PR contains the following updates: | Package | Change | Age | Adoption | Passing | Confidence | |---|---|---|---|---|---| | [com.google.errorprone:error_prone_annotations](https://errorprone.info) ([source](https://redirect.github.com/google/error-prone)) | `2.36.0` -> `2.38.0` | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | [](https://docs.renovatebot.com/merge-confidence/) | --- > [!WARNING] > Some dependencies could not be looked up. Check the Dependency Dashboard for more information. --- ### Release Notes <details> <summary>google/error-prone (com.google.errorprone:error_prone_annotations)</summary> ### [`v2.38.0`](https://redirect.github.com/google/error-prone/releases/tag/v2.38.0): Error Prone 2.38.0 New checks: - [`AddNullMarkedToPackageInfo`](https://errorprone.info/bugpattern/AddNullMarkedToPackageInfo): adds [`@org.jspecify.annotations.NullMarked`](https://jspecify.dev/docs/api/org/jspecify/annotations/NullMarked.html) annotation to package-info files - [`IntLiteralCast`](https://errorprone.info/bugpattern/IntLiteralCast): Suggests a literal of the desired type instead of casting an int literal to a long, float, or double - [`MisleadingEmptyVarargs`](https://errorprone.info/bugpattern/MisleadingEmptyVarargs): Discourages calling varargs methods that expect at least one argument with no arguments, like Mockito's `thenThrow` - [`PreconditionsExpensiveString`](https://errorprone.info/bugpattern/PreconditionsExpensiveString): Discourages expensive string formatting in Guava `Preconditions` checks - [`SelfSet`](https://errorprone.info/bugpattern/SelfSet): Detects mistakes like `proto.setFoo(proto.getFoo())` - [`UnnecessaryCopy`](https://errorprone.info/bugpattern/UnnecessaryCopy): detect unnecessary copies of proto Lists and Maps. Closed issues: [#​4924](https://redirect.github.com/google/error-prone/issues/4924), [#​4897](https://redirect.github.com/google/error-prone/issues/4897), [#​4995](https://redirect.github.com/google/error-prone/issues/4995) Full changelog: google/error-prone@v2.37.0...v2.38.0 ### [`v2.37.0`](https://redirect.github.com/google/error-prone/releases/tag/v2.37.0): Error Prone 2.37.0 [Compare Source](https://redirect.github.com/google/error-prone/compare/v2.36.0...v2.37.0) Changes: - The annotations that were previously in `error_prone_type_annotations` have been been merged into `error_prone_annotations`. `error_prone_type_annotations` is now deprecated, and will be removed in a future release. New checks: - [`AssignmentExpression`](https://errorprone.info/bugpattern/AssignmentExpression) - The use of an assignment expression can be surprising and hard to read; consider factoring out the assignment to a separate statement. - [`IntFloatConversion`](https://errorprone.info/bugpattern/IntFloatConversion) - Detect calls to `scalb` that should be using the double overload instead - [`InvalidSnippet`](https://errorprone.info/bugpattern/InvalidSnippet) - Detects snippets which omit the `:` required for inline code. - [`JUnit4EmptyMethods`](https://errorprone.info/bugpattern/JUnit4EmptyMethods) - Detects empty JUnit4 `@Before`, `@After`, `@BeforeClass`, and `@AfterClass` methods. - [`MockIllegalThrows`](https://errorprone.info/bugpattern/MockIllegalThrows) - Detects cases where Mockito is configured to throw checked exception types which are impossible. - [`NegativeBoolean`](https://errorprone.info/bugpattern/NegativeBoolean) - Prefer positive boolean names. - [`RuleNotRun`](https://errorprone.info/bugpattern/RuleNotRun) - Detects `TestRule`s not annotated with `@Rule`, that won't be run. - [`StringConcatToTextBlock`](https://errorprone.info/bugpattern/StringConcatToTextBlock) - Replaces concatenated multiline strings with text blocks. - [`TimeInStaticInitializer`](https://errorprone.info/bugpattern/TimeInStaticInitializer) - Detects accesses of the system time in static contexts. Closed issues: - Propagate check flags in patch mode ([#​4699](https://redirect.github.com/google/error-prone/issues/4699)) - Fixes a crash in ComputeIfAbsentAmbiguousReference ([#​4736](https://redirect.github.com/google/error-prone/issues/4736)) - Show the field name in HidingField diagnostics ([#​4775](https://redirect.github.com/google/error-prone/issues/4775)) - Add support for jakarta annotations to some checks ([#​4782](https://redirect.github.com/google/error-prone/issues/4782)) - FloatingPointAssertionWithinEpsilonTest depends on default locale ([#​4815](https://redirect.github.com/google/error-prone/issues/4815)) - `@InlineMe` patching of `Strings.repeat` produces broken code ([#​4819](https://redirect.github.com/google/error-prone/issues/4819)) - Fix a crash in IdentifierName on unnamed (`_`) variables ([#​4847](https://redirect.github.com/google/error-prone/issues/4847)) - Fix a crash in ArgumentParameterSwap ([#​490](https://redirect.github.com/google/error-prone/issues/490)) Full changelog: google/error-prone@v2.36.0...v2.37.0 </details> --- ### Configuration 📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about these updates again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/sdk-platform-java). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yNjQuMCIsInVwZGF0ZWRJblZlciI6IjM5LjI2NC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
🤖 I have created a release *beep* *boop* --- <details><summary>2.56.3</summary> ## [2.56.3](googleapis/sdk-platform-java@v2.56.2...v2.56.3) (2025-05-02) ### Bug Fixes * Only send mtlsEndpoint if it is non-null ([#3767](googleapis/sdk-platform-java#3767)) ([7068cbe](googleapis/sdk-platform-java@7068cbe)) * subscribe Airlock Docker image definition to GRPC updates ([#3765](googleapis/sdk-platform-java#3765)) ([3b8f9ca](googleapis/sdk-platform-java@3b8f9ca)) ### Dependencies * update dependency com.google.errorprone:error_prone_annotations to v2.38.0 ([#3773](googleapis/sdk-platform-java#3773)) ([43ea661](googleapis/sdk-platform-java@43ea661)) * update gapic-showcase to 36.2 ([#3771](googleapis/sdk-platform-java#3771)) ([6808c9b](googleapis/sdk-platform-java@6808c9b)) * update google auth library dependencies to v1.34.0 ([#3772](googleapis/sdk-platform-java#3772)) ([8efcac5](googleapis/sdk-platform-java@8efcac5)) * Update maven-shared-utils to v3.2.1 ([#3768](googleapis/sdk-platform-java#3768)) ([47f7907](googleapis/sdk-platform-java@47f7907)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> Co-authored-by: Lawrence Qiu <lawrenceqiu@google.com>
The expected behavior from Files.walkFileTree is that if the starting path is absolute, then all the visited paths are absolute. If the starting path is relative, then all the visited paths are relative.
This PR adds a test for this behavior, and shows that our current code
fails for an absolute path: it returns a mix of relative and absolute
paths.
This PR also adds a code change to fix the problem, so the actual
behavior matches what is expected.
This should fix issue #3772