Support java.nio.file Paths and FileSystems with nested jars
Add a `NestedFileSystemProvider` implementation so that the JDK's `ZipFileSystem` can load content from nested jars and nested directory entries. Creating a `ZipFileSystem` may be a relatively expensive operation as zip structures need to be parsed and in the case of directory entries a virtual datablock nees to be generated on the fly. As such, we install the `ZipFileSystem` as late as possible since in a typical application it may never be needed. This commit also tweaks Gradle and Maven plugins to ensure that the service loader file is written to repackaged jars. Closes gh-7161
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.loader.net.protocol.nested;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@@ -96,4 +97,32 @@ class NestedLocationTests {
|
||||
assertThat(location.nestedEntryName()).isEqualTo("lib/nested.jar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromUriWhenUrlIsNullThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> NestedLocation.fromUri(null))
|
||||
.withMessageContaining("'uri' must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromUriWhenNotNestedProtocolThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> NestedLocation.fromUri(new URI("file://test.jar")))
|
||||
.withMessageContaining("must use 'nested' scheme");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromUriWhenNoSeparatorThrowsExceptiuon() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> NestedLocation.fromUri(new URI("nested:test.jar!nested.jar")))
|
||||
.withMessageContaining("'path' must contain '/!'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fromUriReturnsNestedLocation() throws Exception {
|
||||
File file = new File(this.temp, "test.jar");
|
||||
NestedLocation location = NestedLocation
|
||||
.fromUri(new URI("nested:" + file.getAbsolutePath() + "/!lib/nested.jar"));
|
||||
assertThat(location.path()).isEqualTo(file.toPath());
|
||||
assertThat(location.nestedEntryName()).isEqualTo("lib/nested.jar");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.nio.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Cleaner.Cleanable;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.NonWritableChannelException;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
import org.springframework.boot.loader.ref.Cleaner;
|
||||
import org.springframework.boot.loader.testsupport.TestJar;
|
||||
import org.springframework.boot.loader.zip.AssertFileChannelDataBlocksClosed;
|
||||
import org.springframework.boot.loader.zip.ZipContent;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link NestedByteChannel}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@AssertFileChannelDataBlocksClosed
|
||||
class NestedByteChannelTests {
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
private File file;
|
||||
|
||||
private NestedByteChannel channel;
|
||||
|
||||
@BeforeEach
|
||||
void setup() throws Exception {
|
||||
this.file = new File(this.temp, "test.jar");
|
||||
TestJar.create(this.file);
|
||||
this.channel = new NestedByteChannel(this.file.toPath(), "nested.jar");
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanuo() throws Exception {
|
||||
this.channel.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isOpenWhenOpenReturnsTrue() {
|
||||
assertThat(this.channel.isOpen()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isOpenWhenClosedReturnsFalse() throws Exception {
|
||||
this.channel.close();
|
||||
assertThat(this.channel.isOpen()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void closeCleansResources() throws Exception {
|
||||
Cleaner cleaner = mock(Cleaner.class);
|
||||
Cleanable cleanable = mock(Cleanable.class);
|
||||
given(cleaner.register(any(), any())).willReturn(cleanable);
|
||||
NestedByteChannel channel = new NestedByteChannel(this.file.toPath(), "nested.jar", cleaner);
|
||||
channel.close();
|
||||
then(cleanable).should().clean();
|
||||
ArgumentCaptor<Runnable> actionCaptor = ArgumentCaptor.forClass(Runnable.class);
|
||||
then(cleaner).should().register(any(), actionCaptor.capture());
|
||||
actionCaptor.getValue().run();
|
||||
}
|
||||
|
||||
@Test
|
||||
void closeWhenAlreadyClosedDoesNothing() throws IOException {
|
||||
Cleaner cleaner = mock(Cleaner.class);
|
||||
Cleanable cleanable = mock(Cleanable.class);
|
||||
given(cleaner.register(any(), any())).willReturn(cleanable);
|
||||
NestedByteChannel channel = new NestedByteChannel(this.file.toPath(), "nested.jar", cleaner);
|
||||
channel.close();
|
||||
then(cleanable).should().clean();
|
||||
ArgumentCaptor<Runnable> actionCaptor = ArgumentCaptor.forClass(Runnable.class);
|
||||
then(cleaner).should().register(any(), actionCaptor.capture());
|
||||
actionCaptor.getValue().run();
|
||||
channel.close();
|
||||
then(cleaner).shouldHaveNoMoreInteractions();
|
||||
}
|
||||
|
||||
@Test
|
||||
void readReadsBytesAndIncrementsPosition() throws IOException {
|
||||
ByteBuffer dst = ByteBuffer.allocate(10);
|
||||
assertThat(this.channel.position()).isZero();
|
||||
this.channel.read(dst);
|
||||
assertThat(this.channel.position()).isEqualTo(10L);
|
||||
assertThat(dst.array()).isNotEqualTo(ByteBuffer.allocate(10).array());
|
||||
}
|
||||
|
||||
@Test
|
||||
void writeThrowsException() {
|
||||
assertThatExceptionOfType(NonWritableChannelException.class)
|
||||
.isThrownBy(() -> this.channel.write(ByteBuffer.allocate(10)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void positionWhenClosedThrowsException() throws Exception {
|
||||
this.channel.close();
|
||||
assertThatExceptionOfType(ClosedChannelException.class).isThrownBy(() -> this.channel.position());
|
||||
}
|
||||
|
||||
@Test
|
||||
void positionWhenOpenReturnsPosition() throws Exception {
|
||||
assertThat(this.channel.position()).isEqualTo(0L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void positionWithLongWhenClosedThrowsException() throws Exception {
|
||||
this.channel.close();
|
||||
assertThatExceptionOfType(ClosedChannelException.class).isThrownBy(() -> this.channel.position(0L));
|
||||
}
|
||||
|
||||
@Test
|
||||
void positionWithLongWhenLessThanZeroThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.channel.position(-1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void positionWithLongWhenEqualToSizeThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.channel.position(this.channel.size()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void positionWithLongWhenOpenUpdatesPosition() throws Exception {
|
||||
ByteBuffer dst1 = ByteBuffer.allocate(10);
|
||||
ByteBuffer dst2 = ByteBuffer.allocate(10);
|
||||
dst2.position(1);
|
||||
this.channel.read(dst1);
|
||||
this.channel.position(1);
|
||||
this.channel.read(dst2);
|
||||
dst2.array()[0] = dst1.array()[0];
|
||||
assertThat(dst1.array()).isEqualTo(dst2.array());
|
||||
}
|
||||
|
||||
@Test
|
||||
void sizeWhenClosedThrowsException() throws Exception {
|
||||
this.channel.close();
|
||||
assertThatExceptionOfType(ClosedChannelException.class).isThrownBy(() -> this.channel.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void sizeWhenOpenReturnsSize() throws IOException {
|
||||
try (ZipContent content = ZipContent.open(this.file.toPath())) {
|
||||
assertThat(this.channel.size()).isEqualTo(content.getEntry("nested.jar").getUncompressedSize());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.nio.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.FileStore;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributeView;
|
||||
import java.nio.file.attribute.FileStoreAttributeView;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link NestedFileStore}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class NestedFileStoreTests {
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
private NestedFileSystemProvider provider;
|
||||
|
||||
private Path jarPath;
|
||||
|
||||
private NestedFileSystem fileSystem;
|
||||
|
||||
private TestNestedFileStore fileStore;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.provider = new NestedFileSystemProvider();
|
||||
this.jarPath = new File(this.temp, "test.jar").toPath();
|
||||
this.fileSystem = new NestedFileSystem(this.provider, this.jarPath);
|
||||
this.fileStore = new TestNestedFileStore(this.fileSystem);
|
||||
}
|
||||
|
||||
@Test
|
||||
void nameReturnsName() {
|
||||
assertThat(this.fileStore.name()).isEqualTo(this.jarPath.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void typeReturnsNestedFs() {
|
||||
assertThat(this.fileStore.type()).isEqualTo("nestedfs");
|
||||
}
|
||||
|
||||
@Test
|
||||
void isReadOnlyReturnsTrue() {
|
||||
assertThat(this.fileStore.isReadOnly()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getTotalSpaceReturnsZero() throws Exception {
|
||||
assertThat(this.fileStore.getTotalSpace()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUsableSpaceReturnsZero() throws Exception {
|
||||
assertThat(this.fileStore.getUsableSpace()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUnallocatedSpaceReturnsZero() throws Exception {
|
||||
assertThat(this.fileStore.getUnallocatedSpace()).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
void supportsFileAttributeViewWithClassDelegatesToJarPathFileStore() {
|
||||
FileStore jarFileStore = mock(FileStore.class);
|
||||
given(jarFileStore.supportsFileAttributeView(BasicFileAttributeView.class)).willReturn(true);
|
||||
this.fileStore.setJarPathFileStore(jarFileStore);
|
||||
assertThat(this.fileStore.supportsFileAttributeView(BasicFileAttributeView.class)).isTrue();
|
||||
then(jarFileStore).should().supportsFileAttributeView(BasicFileAttributeView.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void supportsFileAttributeViewWithStringDelegatesToJarPathFileStore() {
|
||||
FileStore jarFileStore = mock(FileStore.class);
|
||||
given(jarFileStore.supportsFileAttributeView("basic")).willReturn(true);
|
||||
this.fileStore.setJarPathFileStore(jarFileStore);
|
||||
assertThat(this.fileStore.supportsFileAttributeView("basic")).isTrue();
|
||||
then(jarFileStore).should().supportsFileAttributeView("basic");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileStoreAttributeViewDelegatesToJarPathFileStore() {
|
||||
FileStore jarFileStore = mock(FileStore.class);
|
||||
TestFileStoreAttributeView attributeView = mock(TestFileStoreAttributeView.class);
|
||||
given(jarFileStore.getFileStoreAttributeView(TestFileStoreAttributeView.class)).willReturn(attributeView);
|
||||
this.fileStore.setJarPathFileStore(jarFileStore);
|
||||
assertThat(this.fileStore.getFileStoreAttributeView(TestFileStoreAttributeView.class)).isEqualTo(attributeView);
|
||||
then(jarFileStore).should().getFileStoreAttributeView(TestFileStoreAttributeView.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getAttributeDelegatesToJarPathFileStore() throws Exception {
|
||||
FileStore jarFileStore = mock(FileStore.class);
|
||||
given(jarFileStore.getAttribute("test")).willReturn("spring");
|
||||
this.fileStore.setJarPathFileStore(jarFileStore);
|
||||
assertThat(this.fileStore.getAttribute("test")).isEqualTo("spring");
|
||||
then(jarFileStore).should().getAttribute("test");
|
||||
}
|
||||
|
||||
static class TestNestedFileStore extends NestedFileStore {
|
||||
|
||||
TestNestedFileStore(NestedFileSystem fileSystem) {
|
||||
super(fileSystem);
|
||||
}
|
||||
|
||||
private FileStore jarPathFileStore;
|
||||
|
||||
void setJarPathFileStore(FileStore jarPathFileStore) {
|
||||
this.jarPathFileStore = jarPathFileStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FileStore getJarPathFileStore() {
|
||||
return (this.jarPathFileStore != null) ? this.jarPathFileStore : super.getJarPathFileStore();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
abstract static class TestFileStoreAttributeView implements FileStoreAttributeView {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.nio.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystemAlreadyExistsException;
|
||||
import java.nio.file.FileSystemNotFoundException;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.NotDirectoryException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.ReadOnlyFileSystemException;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.nio.file.attribute.BasicFileAttributeView;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import org.springframework.boot.loader.testsupport.TestJar;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link NestedFileSystemProvider}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class NestedFileSystemProviderTests {
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
private File file;
|
||||
|
||||
private TestNestedFileSystemProvider provider = new TestNestedFileSystemProvider();
|
||||
|
||||
private String uriPrefix;
|
||||
|
||||
@BeforeEach
|
||||
void setup() throws Exception {
|
||||
this.file = new File(this.temp, "test.jar");
|
||||
TestJar.create(this.file);
|
||||
this.uriPrefix = "nested:" + this.file.toURI().getPath() + "/!";
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSchemeReturnsScheme() {
|
||||
assertThat(this.provider.getScheme()).isEqualTo("nested");
|
||||
}
|
||||
|
||||
@Test
|
||||
void newFilesSystemWhenBadUrlThrowsException() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> this.provider.newFileSystem(new URI("bad:notreal"), Collections.emptyMap()))
|
||||
.withMessageContaining("must use 'nested' scheme");
|
||||
}
|
||||
|
||||
@Test
|
||||
void newFileSystemWhenAlreadyExistsThrowsException() throws Exception {
|
||||
this.provider.newFileSystem(new URI(this.uriPrefix + "nested.jar"), null);
|
||||
assertThatExceptionOfType(FileSystemAlreadyExistsException.class)
|
||||
.isThrownBy(() -> this.provider.newFileSystem(new URI(this.uriPrefix + "other.jar"), null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void newFileSystemReturnsFileSystem() throws Exception {
|
||||
FileSystem fileSystem = this.provider.newFileSystem(new URI(this.uriPrefix + "nested.jar"), null);
|
||||
assertThat(fileSystem).isInstanceOf(NestedFileSystem.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileSystemWhenBadUrlThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.provider.getFileSystem(new URI("bad:notreal")))
|
||||
.withMessageContaining("must use 'nested' scheme");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileSystemWhenNotCreatedThrowsException() {
|
||||
assertThatExceptionOfType(FileSystemNotFoundException.class)
|
||||
.isThrownBy(() -> this.provider.getFileSystem(new URI(this.uriPrefix + "nested.jar")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileSystemReturnsFileSystem() throws Exception {
|
||||
FileSystem expected = this.provider.newFileSystem(new URI(this.uriPrefix + "nested.jar"), null);
|
||||
assertThat(this.provider.getFileSystem(new URI(this.uriPrefix + "nested.jar"))).isSameAs(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPathWhenFileSystemExistsReturnsPath() throws Exception {
|
||||
URI uri = new URI(this.uriPrefix + "nested.jar");
|
||||
this.provider.newFileSystem(uri, null);
|
||||
assertThat(this.provider.getPath(uri)).isInstanceOf(NestedPath.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPathWhenFileSystemDoesNtExistReturnsPath() throws Exception {
|
||||
URI uri = new URI(this.uriPrefix + "nested.jar");
|
||||
assertThat(this.provider.getPath(uri)).isInstanceOf(NestedPath.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void newByteChannelReturnsByteChannel() throws Exception {
|
||||
URI uri = new URI(this.uriPrefix + "nested.jar");
|
||||
Path path = this.provider.getPath(uri);
|
||||
SeekableByteChannel byteChannel = this.provider.newByteChannel(path, Set.of(StandardOpenOption.READ));
|
||||
assertThat(byteChannel).isInstanceOf(NestedByteChannel.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void newDirectoryStreamThrowsException() throws Exception {
|
||||
URI uri = new URI(this.uriPrefix + "nested.jar");
|
||||
Path path = this.provider.getPath(uri);
|
||||
assertThatExceptionOfType(NotDirectoryException.class)
|
||||
.isThrownBy(() -> this.provider.newDirectoryStream(path, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createDirectoryThrowsException() throws Exception {
|
||||
URI uri = new URI(this.uriPrefix + "nested.jar");
|
||||
Path path = this.provider.getPath(uri);
|
||||
assertThatExceptionOfType(ReadOnlyFileSystemException.class)
|
||||
.isThrownBy(() -> this.provider.createDirectory(path));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteThrowsException() throws Exception {
|
||||
URI uri = new URI(this.uriPrefix + "nested.jar");
|
||||
Path path = this.provider.getPath(uri);
|
||||
assertThatExceptionOfType(ReadOnlyFileSystemException.class).isThrownBy(() -> this.provider.delete(path));
|
||||
}
|
||||
|
||||
@Test
|
||||
void copyThrowsException() throws Exception {
|
||||
URI uri = new URI(this.uriPrefix + "nested.jar");
|
||||
Path path = this.provider.getPath(uri);
|
||||
assertThatExceptionOfType(ReadOnlyFileSystemException.class).isThrownBy(() -> this.provider.copy(path, path));
|
||||
}
|
||||
|
||||
@Test
|
||||
void moveThrowsException() throws Exception {
|
||||
URI uri = new URI(this.uriPrefix + "nested.jar");
|
||||
Path path = this.provider.getPath(uri);
|
||||
assertThatExceptionOfType(ReadOnlyFileSystemException.class).isThrownBy(() -> this.provider.move(path, path));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isSameFileWhenSameReturnsTrue() throws Exception {
|
||||
Path p1 = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
Path p2 = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
assertThat(this.provider.isSameFile(p1, p1)).isTrue();
|
||||
assertThat(this.provider.isSameFile(p1, p2)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isSameFileWhenDifferentReturnsFalse() throws Exception {
|
||||
Path p1 = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
Path p2 = this.provider.getPath(new URI(this.uriPrefix + "other.jar"));
|
||||
assertThat(this.provider.isSameFile(p1, p2)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isHiddenReturnsFalse() throws Exception {
|
||||
Path path = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
assertThat(this.provider.isHidden(path)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileStoreWhenFileDoesNotExistThrowsException() throws Exception {
|
||||
Path path = this.provider.getPath(new URI(this.uriPrefix + "missing.jar"));
|
||||
assertThatExceptionOfType(NoSuchFileException.class).isThrownBy(() -> this.provider.getFileStore(path));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileStoreReturnsFileStore() throws Exception {
|
||||
Path path = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
assertThat(this.provider.getFileStore(path)).isInstanceOf(NestedFileStore.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void checkAccessDelegatesToJarPath() throws Exception {
|
||||
Path path = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
Path jarPath = mockJarPath();
|
||||
this.provider.setMockJarPath(jarPath);
|
||||
this.provider.checkAccess(path);
|
||||
then(jarPath.getFileSystem().provider()).should().checkAccess(jarPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileAttributeViewDelegatesToJarPath() throws Exception {
|
||||
Path path = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
Path jarPath = mockJarPath();
|
||||
this.provider.setMockJarPath(jarPath);
|
||||
this.provider.getFileAttributeView(path, BasicFileAttributeView.class);
|
||||
then(jarPath.getFileSystem().provider()).should().getFileAttributeView(jarPath, BasicFileAttributeView.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void readAttributesWithTypeDelegatesToJarPath() throws Exception {
|
||||
Path path = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
Path jarPath = mockJarPath();
|
||||
this.provider.setMockJarPath(jarPath);
|
||||
this.provider.readAttributes(path, BasicFileAttributes.class);
|
||||
then(jarPath.getFileSystem().provider()).should().readAttributes(jarPath, BasicFileAttributes.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void readAttributesWithNameDelegatesToJarPath() throws Exception {
|
||||
Path path = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
Path jarPath = mockJarPath();
|
||||
this.provider.setMockJarPath(jarPath);
|
||||
this.provider.readAttributes(path, "basic");
|
||||
then(jarPath.getFileSystem().provider()).should().readAttributes(jarPath, "basic");
|
||||
}
|
||||
|
||||
@Test
|
||||
void setAttributeThrowsException() throws Exception {
|
||||
Path path = this.provider.getPath(new URI(this.uriPrefix + "nested.jar"));
|
||||
assertThatExceptionOfType(ReadOnlyFileSystemException.class)
|
||||
.isThrownBy(() -> this.provider.setAttribute(path, "test", "test"));
|
||||
}
|
||||
|
||||
private Path mockJarPath() {
|
||||
Path path = mock(Path.class);
|
||||
FileSystem fileSystem = mock(FileSystem.class);
|
||||
given(path.getFileSystem()).willReturn(fileSystem);
|
||||
FileSystemProvider provider = mock(FileSystemProvider.class);
|
||||
given(fileSystem.provider()).willReturn(provider);
|
||||
return path;
|
||||
}
|
||||
|
||||
static class TestNestedFileSystemProvider extends NestedFileSystemProvider {
|
||||
|
||||
private Path mockJarPath;
|
||||
|
||||
@Override
|
||||
protected Path getJarPath(Path path) {
|
||||
return (this.mockJarPath != null) ? this.mockJarPath : super.getJarPath(path);
|
||||
}
|
||||
|
||||
void setMockJarPath(Path mockJarPath) {
|
||||
this.mockJarPath = mockJarPath;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.nio.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.ClosedFileSystemException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link NestedFileSystem}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class NestedFileSystemTests {
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
private NestedFileSystemProvider provider;
|
||||
|
||||
private Path jarPath;
|
||||
|
||||
private NestedFileSystem fileSystem;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.provider = new NestedFileSystemProvider();
|
||||
this.jarPath = new File(this.temp, "test.jar").toPath();
|
||||
this.fileSystem = new NestedFileSystem(this.provider, this.jarPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void providerReturnsProvider() {
|
||||
assertThat(this.fileSystem.provider()).isSameAs(this.provider);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getJarPathReturnsJarPath() {
|
||||
assertThat(this.fileSystem.getJarPath()).isSameAs(this.jarPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void closeClosesFileSystem() throws Exception {
|
||||
this.fileSystem.close();
|
||||
assertThat(this.fileSystem.isOpen()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void closeWhenAlreadyClosedDoesNothing() throws Exception {
|
||||
this.fileSystem.close();
|
||||
this.fileSystem.close();
|
||||
assertThat(this.fileSystem.isOpen()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isOpenWhenOpenReturnsTrue() {
|
||||
assertThat(this.fileSystem.isOpen()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isOpenWhenClosedReturnsFalse() throws Exception {
|
||||
this.fileSystem.close();
|
||||
assertThat(this.fileSystem.isOpen()).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isReadOnlyReturnsTrue() {
|
||||
assertThat(this.fileSystem.isReadOnly()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getSeparatorReturnsSeparator() {
|
||||
assertThat(this.fileSystem.getSeparator()).isEqualTo("/!");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRootDirectoryWhenOpenReturnsEmptyIterable() {
|
||||
assertThat(this.fileSystem.getRootDirectories()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRootDirectoryWhenClosedThrowsException() throws Exception {
|
||||
this.fileSystem.close();
|
||||
assertThatExceptionOfType(ClosedFileSystemException.class)
|
||||
.isThrownBy(() -> this.fileSystem.getRootDirectories());
|
||||
}
|
||||
|
||||
@Test
|
||||
void supportedFileAttributeViewsWhenOpenReturnsBasic() {
|
||||
assertThat(this.fileSystem.supportedFileAttributeViews()).containsExactly("basic");
|
||||
}
|
||||
|
||||
@Test
|
||||
void supportedFileAttributeViewsWhenClosedThrowsException() throws Exception {
|
||||
this.fileSystem.close();
|
||||
assertThatExceptionOfType(ClosedFileSystemException.class)
|
||||
.isThrownBy(() -> this.fileSystem.supportedFileAttributeViews());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPathWhenClosedThrowsException() throws Exception {
|
||||
this.fileSystem.close();
|
||||
assertThatExceptionOfType(ClosedFileSystemException.class)
|
||||
.isThrownBy(() -> this.fileSystem.getPath("nested.jar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPathWhenFirstIsNullThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.fileSystem.getPath(null))
|
||||
.withMessage("Nested paths must contain a single element");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPathWhenFirstIsBlankThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.fileSystem.getPath(""))
|
||||
.withMessage("Nested paths must contain a single element");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPathWhenMoreIsNotEmptyThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.fileSystem.getPath("nested.jar", "another.jar"))
|
||||
.withMessage("Nested paths must contain a single element");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPathReturnsPath() {
|
||||
assertThat(this.fileSystem.getPath("nested.jar")).isInstanceOf(NestedPath.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getPathMatchThrowsException() {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class)
|
||||
.isThrownBy(() -> this.fileSystem.getPathMatcher("*"))
|
||||
.withMessage("Nested paths do not support path matchers");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getUserPrincipalLookupServiceThrowsException() {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class)
|
||||
.isThrownBy(() -> this.fileSystem.getUserPrincipalLookupService())
|
||||
.withMessage("Nested paths do not have a user principal lookup service");
|
||||
}
|
||||
|
||||
@Test
|
||||
void newWatchServiceThrowsException() {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class)
|
||||
.isThrownBy(() -> this.fileSystem.newWatchService())
|
||||
.withMessage("Nested paths do not support the WacherService");
|
||||
}
|
||||
|
||||
@Test
|
||||
void toStringReturnsString() {
|
||||
assertThat(this.fileSystem).hasToString(this.jarPath.toAbsolutePath().toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void equalsAndHashCode() {
|
||||
Path jp1 = new File(this.temp, "test1.jar").toPath();
|
||||
Path jp2 = new File(this.temp, "test1.jar").toPath();
|
||||
Path jp3 = new File(this.temp, "test2.jar").toPath();
|
||||
NestedFileSystem f1 = new NestedFileSystem(this.provider, jp1);
|
||||
NestedFileSystem f2 = new NestedFileSystem(this.provider, jp1);
|
||||
NestedFileSystem f3 = new NestedFileSystem(this.provider, jp2);
|
||||
NestedFileSystem f4 = new NestedFileSystem(this.provider, jp3);
|
||||
assertThat(f1.hashCode()).isEqualTo(f2.hashCode());
|
||||
assertThat(f1).isEqualTo(f1).isEqualTo(f2).isEqualTo(f3).isNotEqualTo(f4);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.nio.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import org.springframework.boot.loader.net.protocol.jar.JarUrl;
|
||||
import org.springframework.boot.loader.testsupport.TestJar;
|
||||
import org.springframework.boot.loader.zip.AssertFileChannelDataBlocksClosed;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link NestedFileSystem} in combination with
|
||||
* {@code ZipFileSystem}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@AssertFileChannelDataBlocksClosed
|
||||
class NestedFileSystemZipFileSystemIntegrationTests {
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
@Test
|
||||
void zip() throws Exception {
|
||||
File file = new File(this.temp, "test.jar");
|
||||
TestJar.create(file);
|
||||
URI uri = JarUrl.create(file).toURI();
|
||||
try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) {
|
||||
assertThat(Files.readAllBytes(fs.getPath("1.dat"))).containsExactly(0x1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void nestedZip() throws Exception {
|
||||
File file = new File(this.temp, "test.jar");
|
||||
TestJar.create(file);
|
||||
URI uri = JarUrl.create(file, "nested.jar").toURI();
|
||||
try (FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap())) {
|
||||
assertThat(Files.readAllBytes(fs.getPath("3.dat"))).containsExactly(0x3);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void nestedZipWithoutNewFileSystem() throws Exception {
|
||||
File file = new File(this.temp, "test.jar");
|
||||
TestJar.create(file);
|
||||
URI uri = JarUrl.create(file, "nested.jar", "3.dat").toURI();
|
||||
Path path = Path.of(uri);
|
||||
assertThat(Files.readAllBytes(path)).containsExactly(0x3);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright 2012-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
|
||||
*
|
||||
* https://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 org.springframework.boot.loader.nio.file;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.ProviderMismatchException;
|
||||
import java.nio.file.WatchService;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import org.springframework.boot.loader.testsupport.TestJar;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link NestedPath}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class NestedPathTests {
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
private NestedFileSystem fileSystem;
|
||||
|
||||
private NestedFileSystemProvider provider;
|
||||
|
||||
private Path jarPath;
|
||||
|
||||
private NestedPath path;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.jarPath = new File(this.temp, "test.jar").toPath();
|
||||
this.provider = new NestedFileSystemProvider();
|
||||
this.fileSystem = new NestedFileSystem(this.provider, this.jarPath);
|
||||
this.path = new NestedPath(this.fileSystem, "nested.jar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getJarPathReturnsJarPath() {
|
||||
assertThat(this.path.getJarPath()).isEqualTo(this.jarPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getNestedEntryNameReturnsNestedEntryName() {
|
||||
assertThat(this.path.getNestedEntryName()).isEqualTo("nested.jar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileSystemReturnsFileSystem() {
|
||||
assertThat(this.path.getFileSystem()).isSameAs(this.fileSystem);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isAbsoluteRerturnsTrue() {
|
||||
assertThat(this.path.isAbsolute()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getRootReturnsNull() {
|
||||
assertThat(this.path.getRoot()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getFileNameReturnsPath() {
|
||||
assertThat(this.path.getFileName()).isSameAs(this.path);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getParentReturnsNull() {
|
||||
assertThat(this.path.getParent()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getNameCountReturnsOne() {
|
||||
assertThat(this.path.getNameCount()).isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void subPathWhenBeginZeroEndOneReturnsPath() {
|
||||
assertThat(this.path.subpath(0, 1)).isSameAs(this.path);
|
||||
}
|
||||
|
||||
@Test
|
||||
void subPathWhenBeginIndexNotZeroThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.path.subpath(1, 1))
|
||||
.withMessage("Nested paths only have a single element");
|
||||
}
|
||||
|
||||
@Test
|
||||
void subPathThenEndIndexNotOneThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> this.path.subpath(0, 2))
|
||||
.withMessage("Nested paths only have a single element");
|
||||
}
|
||||
|
||||
@Test
|
||||
void startsWithWhenStartsWithReturnsTrue() {
|
||||
NestedPath otherPath = new NestedPath(this.fileSystem, "nested.jar");
|
||||
assertThat(this.path.startsWith(otherPath)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void startsWithWhenNotStartsWithReturnsFalse() {
|
||||
NestedPath otherPath = new NestedPath(this.fileSystem, "other.jar");
|
||||
assertThat(this.path.startsWith(otherPath)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void endsWithWhenEndsWithReturnsTrue() {
|
||||
NestedPath otherPath = new NestedPath(this.fileSystem, "nested.jar");
|
||||
assertThat(this.path.endsWith(otherPath)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void endsWithWhenNotEndsWithReturnsFalse() {
|
||||
NestedPath otherPath = new NestedPath(this.fileSystem, "other.jar");
|
||||
assertThat(this.path.endsWith(otherPath)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalizeReturnsPath() {
|
||||
assertThat(this.path.normalize()).isSameAs(this.path);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveThrowsException() {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> this.path.resolve(this.path))
|
||||
.withMessage("Unable to resolve nested path");
|
||||
}
|
||||
|
||||
@Test
|
||||
void relativizeThrowsException() {
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> this.path.relativize(this.path))
|
||||
.withMessage("Unable to relativize nested path");
|
||||
}
|
||||
|
||||
@Test
|
||||
void toUriReturnsUri() throws Exception {
|
||||
assertThat(this.path.toUri()).isEqualTo(new URI("nested:" + this.jarPath.toUri().getPath() + "/!nested.jar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void toAbsolutePathReturnsPath() {
|
||||
assertThat(this.path.toAbsolutePath()).isSameAs(this.path);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toRealPathReturnsPath() throws Exception {
|
||||
assertThat(this.path.toRealPath()).isSameAs(this.path);
|
||||
}
|
||||
|
||||
@Test
|
||||
void registerThrowsException() {
|
||||
WatchService watcher = mock(WatchService.class);
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> this.path.register(watcher))
|
||||
.withMessage("Nested paths cannot be watched");
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareToComparesOnNestedEntryName() {
|
||||
NestedPath a = new NestedPath(this.fileSystem, "a.jar");
|
||||
NestedPath b = new NestedPath(this.fileSystem, "b.jar");
|
||||
NestedPath c = new NestedPath(this.fileSystem, "c.jar");
|
||||
assertThat(new TreeSet<>(Set.of(c, a, b))).containsExactly(a, b, c);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hashCodeAndEquals() {
|
||||
NestedFileSystem fs2 = new NestedFileSystem(this.provider, new File(this.temp, "test2.jar").toPath());
|
||||
NestedPath p1 = new NestedPath(this.fileSystem, "a.jar");
|
||||
NestedPath p2 = new NestedPath(this.fileSystem, "a.jar");
|
||||
NestedPath p3 = new NestedPath(this.fileSystem, "c.jar");
|
||||
NestedPath p4 = new NestedPath(fs2, "c.jar");
|
||||
assertThat(p1.hashCode()).isEqualTo(p2.hashCode());
|
||||
assertThat(p1).isEqualTo(p1).isEqualTo(p2).isNotEqualTo(p3).isNotEqualTo(p4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toStringReturnsString() {
|
||||
assertThat(this.path).hasToString(this.jarPath.toString() + "/!nested.jar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertExistsWhenExists() throws Exception {
|
||||
TestJar.create(this.jarPath.toFile());
|
||||
this.path.assertExists();
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertExistsWhenDoesNotExistThrowsException() {
|
||||
assertThatExceptionOfType(NoSuchFileException.class).isThrownBy(this.path::assertExists);
|
||||
}
|
||||
|
||||
@Test
|
||||
void castWhenNestedPathReturnsNestedPath() {
|
||||
assertThat(NestedPath.cast(this.path)).isSameAs(this.path);
|
||||
}
|
||||
|
||||
@Test
|
||||
void castWhenNullThrowsException() {
|
||||
assertThatExceptionOfType(ProviderMismatchException.class).isThrownBy(() -> NestedPath.cast(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void castWhenNotNestedPathThrowsException() {
|
||||
assertThatExceptionOfType(ProviderMismatchException.class).isThrownBy(() -> NestedPath.cast(this.jarPath));
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user