From 5b7ba9ffdd3936822a72506132673594dfcdb24a Mon Sep 17 00:00:00 2001 From: Ashley Scopes <73482956+ascopes@users.noreply.github.com> Date: Sat, 27 May 2023 09:56:05 +0100 Subject: [PATCH 1/2] Add PathFileObject#getAbsolutePath Create PathFileObject#getAbsolutePath and make it return the same thing as PathFileObject#getFullPath. I have then deprecated PathFileObject#getFullPath as the naming is not completely clear as to what a 'full path' implies. This will be removed in 1.0.0. --- .../jct/assertions/PathFileObjectAssert.java | 17 +++++++++- .../jct/containers/impl/JarContainerImpl.java | 4 +-- .../impl/PathWrappingContainerImpl.java | 4 +-- .../jct/filemanagers/PathFileObject.java | 34 +++++++++++++------ .../unit/filemanagers/PathFileObjectTest.java | 17 +++++++++- 5 files changed, 59 insertions(+), 17 deletions(-) diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/assertions/PathFileObjectAssert.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/assertions/PathFileObjectAssert.java index 836151a60..f538f1fea 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/assertions/PathFileObjectAssert.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/assertions/PathFileObjectAssert.java @@ -55,14 +55,29 @@ public AbstractPathAssert relativePath() { } /** - * Perform an assertion on the file object's full path. + * Perform an assertion on the file object's absolute path. * * @return the assertions for the path. * @throws AssertionError if the file object is null. + * @deprecated use {@link #absolutePath()} instead. */ + @Deprecated(forRemoval = true, since = "0.7.3") + @SuppressWarnings("removal") public AbstractPathAssert fullPath() { isNotNull(); return assertThat(actual.getFullPath()); } + + /** + * Perform an assertion on the file object's absolute path. + * + * @return the assertions for the path. + * @throws AssertionError if the file object is null. + */ + public AbstractPathAssert absolutePath() { + isNotNull(); + + return assertThat(actual.getAbsolutePath()); + } } diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/JarContainerImpl.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/JarContainerImpl.java index 0160716b1..c7c183499 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/JarContainerImpl.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/JarContainerImpl.java @@ -90,7 +90,7 @@ public void close() throws IOException { @Override public boolean contains(PathFileObject fileObject) { - var path = fileObject.getFullPath(); + var path = fileObject.getAbsolutePath(); var root = holder.access().getPathRoot().getPath(); return path.startsWith(root) && Files.isRegularFile(path); } @@ -183,7 +183,7 @@ public String inferBinaryName(PathFileObject javaFileObject) { // we cannot then parse the URI back to a path without removing the `file://` bit first. Since // we assume we always have instances of PathJavaFileObject here, let's just cast to that and // get the correct path immediately. - var fullPath = javaFileObject.getFullPath(); + var fullPath = javaFileObject.getAbsolutePath(); if (fullPath.startsWith( holder.access().getPathRoot().getPath())) { return FileUtils.pathToBinaryName(javaFileObject.getRelativePath()); diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/PathWrappingContainerImpl.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/PathWrappingContainerImpl.java index e868c497b..a4a392a0c 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/PathWrappingContainerImpl.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/containers/impl/PathWrappingContainerImpl.java @@ -74,7 +74,7 @@ public void close() throws IOException { @Override public boolean contains(PathFileObject fileObject) { - var path = fileObject.getFullPath(); + var path = fileObject.getAbsolutePath(); return path.startsWith(root.getPath()) && Files.isRegularFile(path); } @@ -143,7 +143,7 @@ public PathRoot getPathRoot() { @Override public String inferBinaryName(PathFileObject javaFileObject) { - return javaFileObject.getFullPath().startsWith(root.getPath()) + return javaFileObject.getAbsolutePath().startsWith(root.getPath()) ? FileUtils.pathToBinaryName(javaFileObject.getRelativePath()) : null; } diff --git a/java-compiler-testing/src/main/java/io/github/ascopes/jct/filemanagers/PathFileObject.java b/java-compiler-testing/src/main/java/io/github/ascopes/jct/filemanagers/PathFileObject.java index d94fcad42..808336d69 100644 --- a/java-compiler-testing/src/main/java/io/github/ascopes/jct/filemanagers/PathFileObject.java +++ b/java-compiler-testing/src/main/java/io/github/ascopes/jct/filemanagers/PathFileObject.java @@ -69,7 +69,7 @@ public final class PathFileObject implements JavaFileObject { private final Location location; private final Path rootPath; private final Path relativePath; - private final Path fullPath; + private final Path absolutePath; private final String name; private final URI uri; private final Kind kind; @@ -93,15 +93,15 @@ public PathFileObject(Location location, Path rootPath, Path relativePath) { this.location = location; this.rootPath = rootPath; - // TODO(ascopes): should we allow absolute paths here? Not sure that it makes a lot of sense - // here. + // TODO(ascopes): should we allow absolute paths in the input here? Not sure that it makes a + // lot of sense. this.relativePath = relativePath.isAbsolute() ? rootPath.relativize(relativePath) : relativePath; - fullPath = rootPath.resolve(relativePath); + absolutePath = rootPath.resolve(relativePath); name = this.relativePath.toString(); - uri = fullPath.toUri(); + uri = absolutePath.toUri(); kind = FileUtils.pathToKind(relativePath); } @@ -113,7 +113,7 @@ public PathFileObject(Location location, Path rootPath, Path relativePath) { @Override public boolean delete() { try { - return Files.deleteIfExists(fullPath); + return Files.deleteIfExists(absolutePath); } catch (IOException ex) { LOGGER.debug("Ignoring error deleting {}", uri, ex); return false; @@ -133,6 +133,15 @@ public boolean equals(@Nullable Object other) { return other instanceof FileObject && uri.equals(((FileObject) other).toUri()); } + /** + * Get the absolute path of this file object. + * + * @return the full path. + */ + public Path getAbsolutePath() { + return absolutePath; + } + /** * Get the class access level, where appropriate. * @@ -182,9 +191,12 @@ public String getCharContent(boolean ignoreEncodingErrors) throws IOException { * Get the full path of this file object. * * @return the full path. + * @deprecated use {@link #getAbsolutePath()} instead. */ + @Deprecated(since = "0.7.3", forRemoval = true) + @SuppressWarnings("DeprecatedIsStillUsed") public Path getFullPath() { - return fullPath; + return absolutePath; } /** @@ -206,7 +218,7 @@ public Kind getKind() { @Override public long getLastModified() { try { - return Files.getLastModifiedTime(fullPath).toMillis(); + return Files.getLastModifiedTime(absolutePath).toMillis(); } catch (IOException ex) { LOGGER.debug("Ignoring error reading last modified time for {}", uri, ex); return NOT_MODIFIED; @@ -402,13 +414,13 @@ public String toString() { } private InputStream openUnbufferedInputStream() throws IOException { - return Files.newInputStream(fullPath); + return Files.newInputStream(absolutePath); } private OutputStream openUnbufferedOutputStream() throws IOException { // Ensure parent directories exist first. - Files.createDirectories(fullPath.getParent()); - return Files.newOutputStream(fullPath); + Files.createDirectories(absolutePath.getParent()); + return Files.newOutputStream(absolutePath); } private CharsetDecoder decoder(boolean ignoreEncodingErrors) { diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/filemanagers/PathFileObjectTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/filemanagers/PathFileObjectTest.java index 7f5e6d84e..b971a6e41 100644 --- a/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/filemanagers/PathFileObjectTest.java +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/filemanagers/PathFileObjectTest.java @@ -202,6 +202,7 @@ void equalsReturnsTrueIfTheFileObjectHasTheSameUri() { } @DisplayName(".equals(PathFileObject) returns true if the file object is the same instance") + @SuppressWarnings("EqualsWithItself") @Test void equalsReturnsTrueIfTheFileObjectIsTheSameInstance() { // Given @@ -212,7 +213,20 @@ void equalsReturnsTrueIfTheFileObjectIsTheSameInstance() { var fileObject = new PathFileObject(location, rootPath, relativePath); // Then - assertThat(fileObject).isEqualTo(fileObject); + assertThat(fileObject.equals(fileObject)).isTrue(); + } + + @DisplayName(".getAbsolutePath() returns the absolute path") + @Test + void getAbsolutePathReturnsTheAbsolutePath() { + // Given + var rootPath = someAbsolutePath(); + var relativePath = someRelativePath(); + var fileObject = new PathFileObject(someLocation(), rootPath, relativePath); + + // Then + assertThat(fileObject.getAbsolutePath()) + .isEqualTo(rootPath.resolve(relativePath)); } @DisplayName(".getAccessLevel() returns null") @@ -310,6 +324,7 @@ void getCharContentPropagatesEncodingErrors() throws IOException { @DisplayName(".getFullPath() returns the full path") @Test + @SuppressWarnings("removal") void getFullPathReturnsTheFullPath() { // Given var rootPath = someAbsolutePath(); From 04fde1da5ea800ed4b3e24ecfa66c7314053b087 Mon Sep 17 00:00:00 2001 From: Ashley Scopes <73482956+ascopes@users.noreply.github.com> Date: Sat, 27 May 2023 09:56:38 +0100 Subject: [PATCH 2/2] Add tests for PathFileObjectAssert --- .../assertions/PathFileObjectAssertTest.java | 129 ++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/assertions/PathFileObjectAssertTest.java diff --git a/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/assertions/PathFileObjectAssertTest.java b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/assertions/PathFileObjectAssertTest.java new file mode 100644 index 000000000..a924ae445 --- /dev/null +++ b/java-compiler-testing/src/test/java/io/github/ascopes/jct/tests/unit/assertions/PathFileObjectAssertTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 - 2023, the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.github.ascopes.jct.tests.unit.assertions; + +import io.github.ascopes.jct.assertions.PathFileObjectAssert; +import io.github.ascopes.jct.filemanagers.PathFileObject; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static io.github.ascopes.jct.tests.helpers.Fixtures.someAbsolutePath; +import static io.github.ascopes.jct.tests.helpers.Fixtures.someRelativePath; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * {@link PathFileObjectAssert} tests. + * + * @author Ashley Scopes + */ +@DisplayName("PathFileObjectAssert tests") +class PathFileObjectAssertTest { + + @DisplayName("PathFileObjectAssert#relativePath tests") + @Nested + class RelativePathTest { + + @DisplayName(".relativePath() fails if the path file object is null") + @Test + void relativePathFailsIfThePathFileObjectIsNull() { + // Given + var assertions = new PathFileObjectAssert(null); + + // Then + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(assertions::relativePath); + } + + @DisplayName(".relativePath() returns assertions on the relative path") + @Test + void relativePathReturnsAssertionsOnTheRelativePath() { + // Given + var path = someRelativePath(); + var pathFileObject = mock(PathFileObject.class); + when(pathFileObject.getRelativePath()).thenReturn(path); + var assertions = new PathFileObjectAssert(pathFileObject); + + // Then + assertThatNoException() + .isThrownBy(() -> assertions.relativePath().isSameAs(path)); + } + } + + @DisplayName("PathFileObjectAssert#fullPath tests") + @Nested + @SuppressWarnings("removal") + class FullPathTest { + + @DisplayName(".fullPath() fails if the path file object is null") + @Test + void fullPathFailsIfThePathFileObjectIsNull() { + // Given + var assertions = new PathFileObjectAssert(null); + + // Then + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(assertions::fullPath); + } + + @DisplayName(".fullPath() returns assertions on the absolute path") + @Test + void fullPathReturnsAssertionsOnTheFullPath() { + // Given + var path = someAbsolutePath(); + var pathFileObject = mock(PathFileObject.class); + when(pathFileObject.getFullPath()).thenReturn(path); + var assertions = new PathFileObjectAssert(pathFileObject); + + // Then + assertThatNoException() + .isThrownBy(() -> assertions.fullPath().isSameAs(path)); + } + } + + @DisplayName("PathFileObjectAssert#absolutePath tests") + @Nested + class AbsolutePathTest { + + @DisplayName(".absolutePath() fails if the path file object is null") + @Test + void absolutePathFailsIfThePathFileObjectIsNull() { + // Given + var assertions = new PathFileObjectAssert(null); + + // Then + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(assertions::absolutePath); + } + + @DisplayName(".absolutePath() returns assertions on the absolute path") + @Test + void absolutePathReturnsAssertionsOnTheAbsolutePath() { + // Given + var path = someAbsolutePath(); + var pathFileObject = mock(PathFileObject.class); + when(pathFileObject.getAbsolutePath()).thenReturn(path); + var assertions = new PathFileObjectAssert(pathFileObject); + + // Then + assertThatNoException() + .isThrownBy(() -> assertions.absolutePath().isSameAs(path)); + } + } +}