Browse Source

Ensure @ContextConfiguration & @TestPropertySource locations are cleaned

This commit ensures that locations to resources configured via
@ContextConfiguration & @TestPropertySource are consistently cleaned
using StringUtils.clean().

See gh-23544
pull/23545/head
Sam Brannen 7 years ago
parent
commit
22494ba231
  1. 24
      spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java
  2. 45
      spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java

24
spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -54,33 +54,41 @@ public abstract class TestContextResourceUtils { @@ -54,33 +54,41 @@ public abstract class TestContextResourceUtils {
* <ul>
* <li>A plain path &mdash; for example, {@code "context.xml"} &mdash; will
* be treated as a classpath resource that is relative to the package in
* which the specified class is defined.
* which the specified class is defined. Such a path will be prepended with
* the {@code classpath:} prefix and the path to the package for the class.
* <li>A path starting with a slash will be treated as an absolute path
* within the classpath, for example: {@code "/org/example/schema.sql"}.
* <li>A path which is prefixed with a URL protocol (e.g.,
* {@link ResourceUtils#CLASSPATH_URL_PREFIX classpath:},
* {@link ResourceUtils#FILE_URL_PREFIX file:}, {@code http:}, etc.) will be
* {@link StringUtils#cleanPath cleaned} but otherwise unmodified.
* Such a path will be prepended with the {@code classpath:} prefix.
* <li>A path which is already prefixed with a URL protocol (e.g.,
* {@code classpath:}, {@code file:}, {@code http:}, etc.) will not have its
* protocol modified.
* </ul>
* <p>Each path will then be {@linkplain StringUtils#cleanPath cleaned}.
* @param clazz the class with which the paths are associated
* @param paths the paths to be converted
* @return a new array of converted resource paths
* @see #convertToResources
* @see ResourceUtils#CLASSPATH_URL_PREFIX
* @see ResourceUtils#FILE_URL_PREFIX
*/
public static String[] convertToClasspathResourcePaths(Class<?> clazz, String... paths) {
String[] convertedPaths = new String[paths.length];
for (int i = 0; i < paths.length; i++) {
String path = paths[i];
// Absolute path
if (path.startsWith(SLASH)) {
convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + path;
}
// Relative path
else if (!ResourcePatternUtils.isUrl(path)) {
convertedPaths[i] = ResourceUtils.CLASSPATH_URL_PREFIX + SLASH +
StringUtils.cleanPath(ClassUtils.classPackageAsResourcePath(clazz) + SLASH + path);
ClassUtils.classPackageAsResourcePath(clazz) + SLASH + path;
}
// URL
else {
convertedPaths[i] = StringUtils.cleanPath(path);
convertedPaths[i] = path;
}
convertedPaths[i] = StringUtils.cleanPath(convertedPaths[i]);
}
return convertedPaths;
}

45
spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java

@ -27,6 +27,7 @@ import org.springframework.test.context.BootstrapTestUtils; @@ -27,6 +27,7 @@ import org.springframework.test.context.BootstrapTestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextLoader;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.web.WebDelegatingSmartContextLoader;
import org.springframework.test.context.web.WebMergedContextConfiguration;
@ -194,6 +195,29 @@ class BootstrapTestUtilsMergedConfigTests extends AbstractContextConfigurationUt @@ -194,6 +195,29 @@ class BootstrapTestUtilsMergedConfigTests extends AbstractContextConfigurationUt
AnnotationConfigContextLoader.class);
}
@Test
void buildMergedConfigAndVerifyLocationPathsAreCleanedEquivalently() {
assertMergedConfigForLocationPaths(AbsoluteFooXmlLocationWithoutClasspathPrefix.class);
assertMergedConfigForLocationPaths(AbsoluteFooXmlLocationWithInnerRelativePathWithoutClasspathPrefix.class);
assertMergedConfigForLocationPaths(AbsoluteFooXmlLocationWithClasspathPrefix.class);
assertMergedConfigForLocationPaths(RelativeFooXmlLocation.class);
}
private void assertMergedConfigForLocationPaths(Class<?> testClass) {
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
assertThat(mergedConfig).isNotNull();
assertThat(mergedConfig.getTestClass()).isEqualTo(testClass);
assertThat(mergedConfig.getContextLoader()).isInstanceOf(DelegatingSmartContextLoader.class);
assertThat(mergedConfig.getLocations()).containsExactly("classpath:/example/foo.xml");
assertThat(mergedConfig.getPropertySourceLocations()).containsExactly("classpath:/example/foo.properties");
assertThat(mergedConfig.getClasses()).isEmpty();
assertThat(mergedConfig.getActiveProfiles()).isEmpty();
assertThat(mergedConfig.getContextInitializerClasses()).isEmpty();
assertThat(mergedConfig.getPropertySourceProperties()).isEmpty();
}
@ContextConfiguration
@Retention(RetentionPolicy.RUNTIME)
@ -217,4 +241,25 @@ class BootstrapTestUtilsMergedConfigTests extends AbstractContextConfigurationUt @@ -217,4 +241,25 @@ class BootstrapTestUtilsMergedConfigTests extends AbstractContextConfigurationUt
static class MissingContextAttributesTestCase {
}
@ContextConfiguration(locations = "/example/foo.xml")
@TestPropertySource("/example/foo.properties")
static class AbsoluteFooXmlLocationWithoutClasspathPrefix {
}
@ContextConfiguration(locations = "/example/../org/../example/foo.xml")
@TestPropertySource("/example/../org/../example/foo.properties")
static class AbsoluteFooXmlLocationWithInnerRelativePathWithoutClasspathPrefix {
}
@ContextConfiguration(locations = "classpath:/example/foo.xml")
@TestPropertySource("classpath:/example/foo.properties")
static class AbsoluteFooXmlLocationWithClasspathPrefix {
}
// org.springframework.test.context.support --> 5 levels up to the root of the classpath
@ContextConfiguration(locations = "../../../../../example/foo.xml")
@TestPropertySource("../../../../../example/foo.properties")
static class RelativeFooXmlLocation {
}
}

Loading…
Cancel
Save