diff --git a/spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java b/spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java index 170d2ba2c87..7258bb2de6f 100644 --- a/spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/util/TestContextResourceUtils.java @@ -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 { *
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; } diff --git a/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java b/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java index 04decf05954..21b2a8b3ba0 100644 --- a/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/support/BootstrapTestUtilsMergedConfigTests.java @@ -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 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 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 { + } + }