|
|
|
|
@ -17,17 +17,18 @@
@@ -17,17 +17,18 @@
|
|
|
|
|
package org.springframework.core.io; |
|
|
|
|
|
|
|
|
|
import java.io.FileNotFoundException; |
|
|
|
|
import java.util.regex.Matcher; |
|
|
|
|
import java.util.regex.Pattern; |
|
|
|
|
|
|
|
|
|
import org.junit.jupiter.api.Nested; |
|
|
|
|
import org.junit.jupiter.api.Test; |
|
|
|
|
|
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat; |
|
|
|
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Unit tests that serve as regression tests for the bugs described in SPR-6888 |
|
|
|
|
* and SPR-9413. |
|
|
|
|
* Unit tests for {@link ClassPathResource}. |
|
|
|
|
* |
|
|
|
|
* <p>These also originally served as regression tests for the bugs described in |
|
|
|
|
* SPR-6888 and SPR-9413. |
|
|
|
|
* |
|
|
|
|
* @author Chris Beams |
|
|
|
|
* @author Sam Brannen |
|
|
|
|
@ -36,105 +37,110 @@ class ClassPathResourceTests {
@@ -36,105 +37,110 @@ class ClassPathResourceTests {
|
|
|
|
|
|
|
|
|
|
private static final String PACKAGE_PATH = "org/springframework/core/io"; |
|
|
|
|
private static final String NONEXISTENT_RESOURCE_NAME = "nonexistent.xml"; |
|
|
|
|
private static final String FQ_RESOURCE_PATH = PACKAGE_PATH + '/' + NONEXISTENT_RESOURCE_NAME; |
|
|
|
|
private static final String ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE = PACKAGE_PATH + '/' + NONEXISTENT_RESOURCE_NAME; |
|
|
|
|
private static final String ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE_WITH_LEADING_SLASH = '/' + ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Absolute path version of {@link #FQ_RESOURCE_PATH}. |
|
|
|
|
*/ |
|
|
|
|
private static final String FQ_RESOURCE_PATH_WITH_LEADING_SLASH = '/' + FQ_RESOURCE_PATH; |
|
|
|
|
|
|
|
|
|
private static final Pattern DESCRIPTION_PATTERN = Pattern.compile("^class path resource \\[(.+?)]$"); |
|
|
|
|
@Nested |
|
|
|
|
class GetInputStream { |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void withStringConstructorRaisesExceptionForNonexistentResource() { |
|
|
|
|
assertExceptionContainsAbsolutePath(new ClassPathResource(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void stringConstructorRaisesExceptionWithFullyQualifiedPath() { |
|
|
|
|
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(FQ_RESOURCE_PATH)); |
|
|
|
|
} |
|
|
|
|
@Test |
|
|
|
|
void withClassLoaderConstructorRaisesExceptionForNonexistentResource() { |
|
|
|
|
assertExceptionContainsAbsolutePath(new ClassPathResource(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE, getClass().getClassLoader())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void classLiteralConstructorRaisesExceptionWithFullyQualifiedPath() { |
|
|
|
|
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(NONEXISTENT_RESOURCE_NAME, getClass())); |
|
|
|
|
} |
|
|
|
|
@Test |
|
|
|
|
void withClassLiteralConstructorRaisesExceptionForNonexistentRelativeResource() { |
|
|
|
|
assertExceptionContainsAbsolutePath(new ClassPathResource(NONEXISTENT_RESOURCE_NAME, getClass())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void classLoaderConstructorRaisesExceptionWithFullyQualifiedPath() { |
|
|
|
|
assertExceptionContainsFullyQualifiedPath(new ClassPathResource(FQ_RESOURCE_PATH, getClass().getClassLoader())); |
|
|
|
|
} |
|
|
|
|
@Test |
|
|
|
|
void withClassLiteralConstructorRaisesExceptionForNonexistentAbsoluteResource() { |
|
|
|
|
assertExceptionContainsAbsolutePath(new ClassPathResource(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE, getClass())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void getDescriptionWithStringConstructor() { |
|
|
|
|
assertDescriptionContainsExpectedPath(new ClassPathResource(FQ_RESOURCE_PATH), FQ_RESOURCE_PATH); |
|
|
|
|
} |
|
|
|
|
private static void assertExceptionContainsAbsolutePath(ClassPathResource resource) { |
|
|
|
|
assertThatExceptionOfType(FileNotFoundException.class) |
|
|
|
|
.isThrownBy(resource::getInputStream) |
|
|
|
|
.withMessageContaining(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void getDescriptionWithStringConstructorAndLeadingSlash() { |
|
|
|
|
assertDescriptionContainsExpectedPath(new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH), |
|
|
|
|
FQ_RESOURCE_PATH); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void getDescriptionWithClassLiteralConstructor() { |
|
|
|
|
assertDescriptionContainsExpectedPath(new ClassPathResource(NONEXISTENT_RESOURCE_NAME, getClass()), |
|
|
|
|
FQ_RESOURCE_PATH); |
|
|
|
|
} |
|
|
|
|
@Nested |
|
|
|
|
class GetDescription { |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void getDescriptionWithClassLiteralConstructorAndLeadingSlash() { |
|
|
|
|
assertDescriptionContainsExpectedPath( |
|
|
|
|
new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH, getClass()), FQ_RESOURCE_PATH); |
|
|
|
|
} |
|
|
|
|
@Test |
|
|
|
|
void withStringConstructor() { |
|
|
|
|
assertDescription(new ClassPathResource(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void getDescriptionWithClassLoaderConstructor() { |
|
|
|
|
assertDescriptionContainsExpectedPath( |
|
|
|
|
new ClassPathResource(FQ_RESOURCE_PATH, getClass().getClassLoader()), FQ_RESOURCE_PATH); |
|
|
|
|
} |
|
|
|
|
@Test |
|
|
|
|
void withStringConstructorAndLeadingSlash() { |
|
|
|
|
assertDescription(new ClassPathResource(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE_WITH_LEADING_SLASH)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void getDescriptionWithClassLoaderConstructorAndLeadingSlash() { |
|
|
|
|
assertDescriptionContainsExpectedPath( |
|
|
|
|
new ClassPathResource(FQ_RESOURCE_PATH_WITH_LEADING_SLASH, getClass().getClassLoader()), FQ_RESOURCE_PATH); |
|
|
|
|
} |
|
|
|
|
@Test |
|
|
|
|
void withClassLiteralConstructor() { |
|
|
|
|
assertDescription(new ClassPathResource(NONEXISTENT_RESOURCE_NAME, getClass())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void withClassLiteralConstructorAndLeadingSlash() { |
|
|
|
|
assertDescription(new ClassPathResource(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE_WITH_LEADING_SLASH, getClass())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void withClassLoaderConstructor() { |
|
|
|
|
assertDescription(new ClassPathResource(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE, getClass().getClassLoader())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void withClassLoaderConstructorAndLeadingSlash() { |
|
|
|
|
assertDescription(new ClassPathResource(ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE_WITH_LEADING_SLASH, getClass().getClassLoader())); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static void assertDescription(ClassPathResource resource) { |
|
|
|
|
assertThat(resource.getDescription()).isEqualTo("class path resource [%s]", ABSOLUTE_PATH_TO_NONEXISTENT_RESOURCE); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void dropLeadingSlashForClassLoaderAccess() { |
|
|
|
|
assertThat(new ClassPathResource("/test.html").getPath()).isEqualTo("test.html"); |
|
|
|
|
assertThat(((ClassPathResource) new ClassPathResource("").createRelative("/test.html")).getPath()).isEqualTo("test.html"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void convertToAbsolutePathForClassRelativeAccess() { |
|
|
|
|
assertThat(new ClassPathResource("/test.html", getClass()).getPath()).isEqualTo("test.html"); |
|
|
|
|
assertThat(new ClassPathResource("", getClass()).getPath()).isEqualTo(PACKAGE_PATH + "/"); |
|
|
|
|
assertThat(((ClassPathResource) new ClassPathResource("", getClass()).createRelative("/test.html")).getPath()).isEqualTo("test.html"); |
|
|
|
|
assertThat(((ClassPathResource) new ClassPathResource("", getClass()).createRelative("test.html")).getPath()).isEqualTo(PACKAGE_PATH + "/test.html"); |
|
|
|
|
@Nested |
|
|
|
|
class GetPath { |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void dropsLeadingSlashForClassLoaderAccess() { |
|
|
|
|
assertThat(new ClassPathResource("/test.html").getPath()).isEqualTo("test.html"); |
|
|
|
|
assertThat(((ClassPathResource) new ClassPathResource("").createRelative("/test.html")).getPath()).isEqualTo("test.html"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void convertsToAbsolutePathForClassRelativeAccess() { |
|
|
|
|
assertThat(new ClassPathResource("/test.html", getClass()).getPath()).isEqualTo("test.html"); |
|
|
|
|
assertThat(new ClassPathResource("", getClass()).getPath()).isEqualTo(PACKAGE_PATH + "/"); |
|
|
|
|
assertThat(((ClassPathResource) new ClassPathResource("", getClass()).createRelative("/test.html")).getPath()).isEqualTo("test.html"); |
|
|
|
|
assertThat(((ClassPathResource) new ClassPathResource("", getClass()).createRelative("test.html")).getPath()).isEqualTo(PACKAGE_PATH + "/test.html"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
void directoryNotReadable() { |
|
|
|
|
void directoryNotReadable() throws Exception { |
|
|
|
|
Resource fileDir = new ClassPathResource("org/springframework/core"); |
|
|
|
|
assertThat(fileDir.getURL()).asString().startsWith("file:"); |
|
|
|
|
assertThat(fileDir.exists()).isTrue(); |
|
|
|
|
assertThat(fileDir.isReadable()).isFalse(); |
|
|
|
|
|
|
|
|
|
Resource jarDir = new ClassPathResource("reactor/core"); |
|
|
|
|
assertThat(jarDir.getURL()).asString().startsWith("jar:"); |
|
|
|
|
assertThat(jarDir.exists()).isTrue(); |
|
|
|
|
assertThat(jarDir.isReadable()).isFalse(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void assertDescriptionContainsExpectedPath(ClassPathResource resource, String expectedPath) { |
|
|
|
|
Matcher matcher = DESCRIPTION_PATTERN.matcher(resource.getDescription()); |
|
|
|
|
assertThat(matcher.matches()).isTrue(); |
|
|
|
|
assertThat(matcher.groupCount()).isEqualTo(1); |
|
|
|
|
String match = matcher.group(1); |
|
|
|
|
|
|
|
|
|
assertThat(match).isEqualTo(expectedPath); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void assertExceptionContainsFullyQualifiedPath(ClassPathResource resource) { |
|
|
|
|
assertThatExceptionOfType(FileNotFoundException.class).isThrownBy( |
|
|
|
|
resource::getInputStream) |
|
|
|
|
.withMessageContaining(FQ_RESOURCE_PATH); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|