Minimize test resources and move remainder to appropriate packages
Closes gh-44397
This commit is contained in:
parent
8577718b22
commit
3de189a1df
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -23,6 +23,7 @@ import sampleconfig.MyComponentInPackageWithoutDot;
|
|||||||
|
|
||||||
import org.springframework.boot.sampleconfig.MyComponent;
|
import org.springframework.boot.sampleconfig.MyComponent;
|
||||||
import org.springframework.boot.sampleconfig.MyNamedComponent;
|
import org.springframework.boot.sampleconfig.MyNamedComponent;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.support.StaticApplicationContext;
|
import org.springframework.context.support.StaticApplicationContext;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
@ -72,8 +73,9 @@ class BeanDefinitionLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSampleBeansXmlResource
|
||||||
void loadXmlResource() {
|
void loadXmlResource() {
|
||||||
ClassPathResource resource = new ClassPathResource("sample-beans.xml", getClass());
|
ClassPathResource resource = new ClassPathResource("org/springframework/boot/sample-beans.xml");
|
||||||
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
|
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
|
||||||
assertThat(load(loader)).isOne();
|
assertThat(load(loader)).isOne();
|
||||||
assertThat(this.registry.containsBean("myXmlComponent")).isTrue();
|
assertThat(this.registry.containsBean("myXmlComponent")).isTrue();
|
||||||
@ -81,8 +83,15 @@ class BeanDefinitionLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "org/springframework/boot/sample-beans.groovy", content = """
|
||||||
|
import org.springframework.boot.sampleconfig.MyComponent;
|
||||||
|
|
||||||
|
beans {
|
||||||
|
myGroovyComponent(MyComponent) {}
|
||||||
|
}
|
||||||
|
""")
|
||||||
void loadGroovyResource() {
|
void loadGroovyResource() {
|
||||||
ClassPathResource resource = new ClassPathResource("sample-beans.groovy", getClass());
|
ClassPathResource resource = new ClassPathResource("org/springframework/boot/sample-beans.groovy");
|
||||||
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
|
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
|
||||||
assertThat(load(loader)).isOne();
|
assertThat(load(loader)).isOne();
|
||||||
assertThat(this.registry.containsBean("myGroovyComponent")).isTrue();
|
assertThat(this.registry.containsBean("myGroovyComponent")).isTrue();
|
||||||
@ -90,8 +99,17 @@ class BeanDefinitionLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "org/springframework/boot/sample-namespace.groovy", content = """
|
||||||
|
import org.springframework.boot.sampleconfig.MyComponent;
|
||||||
|
|
||||||
|
beans {
|
||||||
|
xmlns([ctx:'http://www.springframework.org/schema/context'])
|
||||||
|
ctx.'component-scan'('base-package':'nonexistent')
|
||||||
|
myGroovyComponent(MyComponent) {}
|
||||||
|
}
|
||||||
|
""")
|
||||||
void loadGroovyResourceWithNamespace() {
|
void loadGroovyResourceWithNamespace() {
|
||||||
ClassPathResource resource = new ClassPathResource("sample-namespace.groovy", getClass());
|
ClassPathResource resource = new ClassPathResource("org/springframework/boot/sample-namespace.groovy");
|
||||||
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
|
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry, resource);
|
||||||
assertThat(load(loader)).isOne();
|
assertThat(load(loader)).isOne();
|
||||||
assertThat(this.registry.containsBean("myGroovyComponent")).isTrue();
|
assertThat(this.registry.containsBean("myGroovyComponent")).isTrue();
|
||||||
@ -114,7 +132,8 @@ class BeanDefinitionLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loadResourceName() {
|
@WithSampleBeansXmlResource
|
||||||
|
void loadXmlName() {
|
||||||
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry,
|
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry,
|
||||||
"classpath:org/springframework/boot/sample-beans.xml");
|
"classpath:org/springframework/boot/sample-beans.xml");
|
||||||
assertThat(load(loader)).isOne();
|
assertThat(load(loader)).isOne();
|
||||||
@ -122,6 +141,13 @@ class BeanDefinitionLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "org/springframework/boot/sample-beans.groovy", content = """
|
||||||
|
import org.springframework.boot.sampleconfig.MyComponent;
|
||||||
|
|
||||||
|
beans {
|
||||||
|
myGroovyComponent(MyComponent) {}
|
||||||
|
}
|
||||||
|
""")
|
||||||
void loadGroovyName() {
|
void loadGroovyName() {
|
||||||
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry,
|
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry,
|
||||||
"classpath:org/springframework/boot/sample-beans.groovy");
|
"classpath:org/springframework/boot/sample-beans.groovy");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2021 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -61,12 +61,14 @@ class SimpleMainTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSampleBeansXmlResource
|
||||||
void xmlContext(CapturedOutput output) throws Exception {
|
void xmlContext(CapturedOutput output) throws Exception {
|
||||||
SpringApplication.main(getArgs("org/springframework/boot/sample-beans.xml"));
|
SpringApplication.main(getArgs("org/springframework/boot/sample-beans.xml"));
|
||||||
assertThat(output).contains(SPRING_STARTUP);
|
assertThat(output).contains(SPRING_STARTUP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSampleBeansXmlResource
|
||||||
void mixedContext(CapturedOutput output) throws Exception {
|
void mixedContext(CapturedOutput output) throws Exception {
|
||||||
SpringApplication.main(getArgs(getClass().getName(), "org/springframework/boot/sample-beans.xml"));
|
SpringApplication.main(getArgs(getClass().getName(), "org/springframework/boot/sample-beans.xml"));
|
||||||
assertThat(output).contains(SPRING_STARTUP);
|
assertThat(output).contains(SPRING_STARTUP);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,6 +22,7 @@ import org.mockito.ArgumentCaptor;
|
|||||||
|
|
||||||
import org.springframework.aot.hint.RuntimeHints;
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
|
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.support.GenericApplicationContext;
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@ -47,9 +48,10 @@ class SpringApplicationBannerPrinterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "banner.txt", content = "\uD83D\uDE0D Spring Boot! \uD83D\uDE0D")
|
||||||
void shouldUseUtf8() {
|
void shouldUseUtf8() {
|
||||||
ResourceLoader resourceLoader = new GenericApplicationContext();
|
ResourceLoader resourceLoader = new GenericApplicationContext();
|
||||||
Resource resource = resourceLoader.getResource("classpath:/banner-utf8.txt");
|
Resource resource = resourceLoader.getResource("classpath:banner.txt");
|
||||||
SpringApplicationBannerPrinter printer = new SpringApplicationBannerPrinter(resourceLoader,
|
SpringApplicationBannerPrinter printer = new SpringApplicationBannerPrinter(resourceLoader,
|
||||||
new ResourceBanner(resource));
|
new ResourceBanner(resource));
|
||||||
Log log = mock(Log.class);
|
Log log = mock(Log.class);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -74,6 +74,7 @@ import org.springframework.boot.context.event.ApplicationStartingEvent;
|
|||||||
import org.springframework.boot.context.event.SpringApplicationEvent;
|
import org.springframework.boot.context.event.SpringApplicationEvent;
|
||||||
import org.springframework.boot.convert.ApplicationConversionService;
|
import org.springframework.boot.convert.ApplicationConversionService;
|
||||||
import org.springframework.boot.testsupport.classpath.ForkedClassPath;
|
import org.springframework.boot.testsupport.classpath.ForkedClassPath;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
|
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
|
||||||
@ -226,19 +227,24 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "banner.txt", content = "Running a Test!")
|
||||||
void customBanner(CapturedOutput output) {
|
void customBanner(CapturedOutput output) {
|
||||||
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
|
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
this.context = application.run("--spring.banner.location=classpath:test-banner.txt");
|
this.context = application.run();
|
||||||
assertThat(output).startsWith("Running a Test!");
|
assertThat(output).startsWith("Running a Test!");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "banner.txt", content = """
|
||||||
|
Running a Test!
|
||||||
|
|
||||||
|
${test.property}""")
|
||||||
void customBannerWithProperties(CapturedOutput output) {
|
void customBannerWithProperties(CapturedOutput output) {
|
||||||
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
|
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
this.context = application.run("--spring.banner.location=classpath:test-banner-with-placeholder.txt",
|
this.context = application.run("--test.property=123456");
|
||||||
"--test.property=123456");
|
|
||||||
assertThat(output).containsPattern("Running a Test!\\s+123456");
|
assertThat(output).containsPattern("Running a Test!\\s+123456");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +295,7 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "bindtoapplication.properties", content = "spring.main.banner-mode=off")
|
||||||
void triggersConfigFileApplicationListenerBeforeBinding() {
|
void triggersConfigFileApplicationListenerBeforeBinding() {
|
||||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
@ -540,6 +547,7 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "foo=bucket")
|
||||||
void propertiesFileEnhancesEnvironment() {
|
void propertiesFileEnhancesEnvironment() {
|
||||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
@ -572,6 +580,8 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "my.property=fromapplicationproperties")
|
||||||
|
@WithResource(name = "application-other.properties", content = "my.property=fromotherpropertiesfile")
|
||||||
void addProfilesOrderWithProperties() {
|
void addProfilesOrderWithProperties() {
|
||||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
@ -584,6 +594,7 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "foo=bucket")
|
||||||
void emptyCommandLinePropertySourceNotAdded() {
|
void emptyCommandLinePropertySourceNotAdded() {
|
||||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
@ -814,11 +825,13 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSampleBeansXmlResource
|
||||||
|
@WithResource(name = "application.properties", content = "sample.app.test.prop=*")
|
||||||
void wildcardSources() {
|
void wildcardSources() {
|
||||||
TestSpringApplication application = new TestSpringApplication();
|
TestSpringApplication application = new TestSpringApplication();
|
||||||
application.getSources().add("classpath*:org/springframework/boot/sample-${sample.app.test.prop}.xml");
|
application.getSources().add("classpath*:org/springframework/boot/sample-${sample.app.test.prop}.xml");
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
this.context = application.run();
|
this.context = application.run("--spring.config.location=classpath:/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -1139,6 +1152,8 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application-withwebapplicationtype.yml",
|
||||||
|
content = "spring.main.web-application-type: reactive")
|
||||||
void environmentIsConvertedIfTypeDoesNotMatch() {
|
void environmentIsConvertedIfTypeDoesNotMatch() {
|
||||||
ConfigurableApplicationContext context = new SpringApplication(ExampleReactiveWebConfig.class)
|
ConfigurableApplicationContext context = new SpringApplication(ExampleReactiveWebConfig.class)
|
||||||
.run("--spring.profiles.active=withwebapplicationtype");
|
.run("--spring.profiles.active=withwebapplicationtype");
|
||||||
@ -1195,6 +1210,7 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "custom-config/application.yml", content = "hello: world")
|
||||||
void relaxedBindingShouldWorkBeforeEnvironmentIsPrepared() {
|
void relaxedBindingShouldWorkBeforeEnvironmentIsPrepared() {
|
||||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
@ -1329,6 +1345,8 @@ class SpringApplicationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "spring-application-config-property-source.properties",
|
||||||
|
content = "test.name=spring-application-config-property-source")
|
||||||
void movesConfigClassPropertySourcesToEnd() {
|
void movesConfigClassPropertySourcesToEnd() {
|
||||||
SpringApplication application = new SpringApplication(PropertySourceConfig.class);
|
SpringApplication application = new SpringApplication(PropertySourceConfig.class);
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012-2025 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;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes an {@code org/springframework/boot/sample-beans.xml} resource available from the
|
||||||
|
* thread context classloader.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@WithResource(name = "org/springframework/boot/sample-beans.xml",
|
||||||
|
content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:context="http://www.springframework.org/schema/context"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
|
||||||
|
<bean id="myXmlComponent" class="org.springframework.boot.sampleconfig.MyComponent"/>
|
||||||
|
</beans>
|
||||||
|
""")
|
||||||
|
@interface WithSampleBeansXmlResource {
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -29,6 +29,7 @@ import org.springframework.boot.ApplicationContextFactory;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.SpringApplicationShutdownHookInstance;
|
import org.springframework.boot.SpringApplicationShutdownHookInstance;
|
||||||
import org.springframework.boot.WebApplicationType;
|
import org.springframework.boot.WebApplicationType;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
@ -72,14 +73,21 @@ class SpringApplicationBuilderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = """
|
||||||
|
b=file
|
||||||
|
c=file
|
||||||
|
""")
|
||||||
|
@WithResource(name = "application-foo.properties", content = "b=profile-specific-file")
|
||||||
void profileAndProperties() {
|
void profileAndProperties() {
|
||||||
SpringApplicationBuilder application = new SpringApplicationBuilder().sources(ExampleConfig.class)
|
SpringApplicationBuilder application = new SpringApplicationBuilder().sources(ExampleConfig.class)
|
||||||
.contextFactory(ApplicationContextFactory.ofContextClass(StaticApplicationContext.class))
|
.contextFactory(ApplicationContextFactory.ofContextClass(StaticApplicationContext.class))
|
||||||
.profiles("foo")
|
.profiles("foo")
|
||||||
.properties("foo=bar");
|
.properties("a=default");
|
||||||
this.context = application.run();
|
this.context = application.run();
|
||||||
assertThat(this.context).isInstanceOf(StaticApplicationContext.class);
|
assertThat(this.context).isInstanceOf(StaticApplicationContext.class);
|
||||||
assertThat(this.context.getEnvironment().getProperty("foo")).isEqualTo("bucket");
|
assertThat(this.context.getEnvironment().getProperty("a")).isEqualTo("default");
|
||||||
|
assertThat(this.context.getEnvironment().getProperty("b")).isEqualTo("profile-specific-file");
|
||||||
|
assertThat(this.context.getEnvironment().getProperty("c")).isEqualTo("file");
|
||||||
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("foo"))).isTrue();
|
assertThat(this.context.getEnvironment().acceptsProfiles(Profiles.of("foo"))).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,6 +202,7 @@ class SpringApplicationBuilderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application-node.properties", content = "bar=spam")
|
||||||
void parentFirstCreationWithProfileAndDefaultArgs() {
|
void parentFirstCreationWithProfileAndDefaultArgs() {
|
||||||
SpringApplicationBuilder application = new SpringApplicationBuilder(ExampleConfig.class).profiles("node")
|
SpringApplicationBuilder application = new SpringApplicationBuilder(ExampleConfig.class).profiles("node")
|
||||||
.properties("transport=redis")
|
.properties("transport=redis")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -23,6 +23,8 @@ import java.lang.annotation.Target;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +34,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*/
|
*/
|
||||||
class ImportCandidatesTests {
|
class ImportCandidatesTests {
|
||||||
|
|
||||||
|
private static final String IMPORTS_FILE = "META-INF/spring/org.springframework.boot.context.annotation.ImportCandidatesTests$TestAnnotation.imports";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = IMPORTS_FILE, content = """
|
||||||
|
# A comment spanning a complete line
|
||||||
|
class1
|
||||||
|
|
||||||
|
class2 # with comment at the end
|
||||||
|
# Comment with some whitespace in front
|
||||||
|
class3
|
||||||
|
|
||||||
|
""")
|
||||||
void loadReadsFromClasspathFile() {
|
void loadReadsFromClasspathFile() {
|
||||||
ImportCandidates candidates = ImportCandidates.load(TestAnnotation.class, null);
|
ImportCandidates candidates = ImportCandidates.load(TestAnnotation.class, null);
|
||||||
assertThat(candidates).containsExactly("class1", "class2", "class3");
|
assertThat(candidates).containsExactly("class1", "class2", "class3");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2019 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -28,11 +28,9 @@ import org.springframework.boot.WebApplicationType;
|
|||||||
import org.springframework.boot.ansi.AnsiOutput;
|
import org.springframework.boot.ansi.AnsiOutput;
|
||||||
import org.springframework.boot.ansi.AnsiOutput.Enabled;
|
import org.springframework.boot.ansi.AnsiOutput.Enabled;
|
||||||
import org.springframework.boot.ansi.AnsiOutputEnabledValue;
|
import org.springframework.boot.ansi.AnsiOutputEnabledValue;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
|
||||||
import org.springframework.test.context.support.TestPropertySourceUtils;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@ -81,11 +79,9 @@ class AnsiOutputApplicationListenerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "spring.output.ansi.enabled=never")
|
||||||
void disabledViaApplicationProperties() {
|
void disabledViaApplicationProperties() {
|
||||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
|
||||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(environment, "spring.config.name=ansi");
|
|
||||||
SpringApplication application = new SpringApplication(Config.class);
|
SpringApplication application = new SpringApplication(Config.class);
|
||||||
application.setEnvironment(environment);
|
|
||||||
application.setWebApplicationType(WebApplicationType.NONE);
|
application.setWebApplicationType(WebApplicationType.NONE);
|
||||||
this.context = application.run();
|
this.context = application.run();
|
||||||
assertThat(AnsiOutputEnabledValue.get()).isEqualTo(Enabled.NEVER);
|
assertThat(AnsiOutputEnabledValue.get()).isEqualTo(Enabled.NEVER);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -23,6 +23,7 @@ import org.springframework.boot.BootstrapRegistry;
|
|||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.WebApplicationType;
|
import org.springframework.boot.WebApplicationType;
|
||||||
import org.springframework.boot.context.config.TestConfigDataBootstrap.LoaderHelper;
|
import org.springframework.boot.context.config.TestConfigDataBootstrap.LoaderHelper;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
@ -45,9 +46,24 @@ class ConfigDataEnvironmentPostProcessorBootstrapContextIntegrationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "imported.properties", content = """
|
||||||
|
spring.config.import=testbootstrap:test
|
||||||
|
spring.profiles.active=test
|
||||||
|
myprop=igotbound
|
||||||
|
#---
|
||||||
|
spring.config.activate.on-profile=test
|
||||||
|
myprofileprop=igotprofilebound
|
||||||
|
|
||||||
|
""")
|
||||||
|
@WithResource(name = "META-INF/spring.factories", content = """
|
||||||
|
org.springframework.boot.context.config.ConfigDataLoader=\
|
||||||
|
org.springframework.boot.context.config.TestConfigDataBootstrap.Loader
|
||||||
|
org.springframework.boot.context.config.ConfigDataLocationResolver=\
|
||||||
|
org.springframework.boot.context.config.TestConfigDataBootstrap.LocationResolver
|
||||||
|
""")
|
||||||
void bootstrapsApplicationContext() {
|
void bootstrapsApplicationContext() {
|
||||||
try (ConfigurableApplicationContext context = this.application
|
try (ConfigurableApplicationContext context = this.application
|
||||||
.run("--spring.config.import=classpath:application-bootstrap-registry-integration-tests.properties")) {
|
.run("--spring.config.import=classpath:imported.properties")) {
|
||||||
LoaderHelper bean = context.getBean(TestConfigDataBootstrap.LoaderHelper.class);
|
LoaderHelper bean = context.getBean(TestConfigDataBootstrap.LoaderHelper.class);
|
||||||
assertThat(bean).isNotNull();
|
assertThat(bean).isNotNull();
|
||||||
assertThat(bean.getBound()).isEqualTo("igotbound");
|
assertThat(bean.getBound()).isEqualTo("igotbound");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -33,6 +33,7 @@ import org.springframework.boot.WebApplicationType;
|
|||||||
import org.springframework.boot.context.config.ConfigData.Option;
|
import org.springframework.boot.context.config.ConfigData.Option;
|
||||||
import org.springframework.boot.context.config.ConfigData.Options;
|
import org.springframework.boot.context.config.ConfigData.Options;
|
||||||
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorIntegrationTests.Config;
|
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorIntegrationTests.Config;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.core.env.MapPropertySource;
|
import org.springframework.core.env.MapPropertySource;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
@ -45,6 +46,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*
|
*
|
||||||
* @author Phillip Webb
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
|
@WithResource(name = "application.properties", content = """
|
||||||
|
spring.config.import=icwps:
|
||||||
|
prop=fromfile
|
||||||
|
""")
|
||||||
|
@WithResource(name = "application-prod.properties", content = "prop=fromprofilefile")
|
||||||
|
@WithResource(name = "META-INF/spring.factories",
|
||||||
|
content = """
|
||||||
|
org.springframework.boot.context.config.ConfigDataLoader=\
|
||||||
|
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegrationTests.Loader
|
||||||
|
org.springframework.boot.context.config.ConfigDataLocationResolver=\
|
||||||
|
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegrationTests.LocationResolver
|
||||||
|
""")
|
||||||
class ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegrationTests {
|
class ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegrationTests {
|
||||||
|
|
||||||
private SpringApplication application;
|
private SpringApplication application;
|
||||||
@ -60,16 +73,14 @@ class ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegra
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWithoutProfile() {
|
void testWithoutProfile() {
|
||||||
ConfigurableApplicationContext context = this.application
|
ConfigurableApplicationContext context = this.application.run();
|
||||||
.run("--spring.config.name=configimportwithprofilespecific");
|
|
||||||
String value = context.getEnvironment().getProperty("prop");
|
String value = context.getEnvironment().getProperty("prop");
|
||||||
assertThat(value).isEqualTo("fromicwps1");
|
assertThat(value).isEqualTo("fromicwps1");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWithProfile() {
|
void testWithProfile() {
|
||||||
ConfigurableApplicationContext context = this.application
|
ConfigurableApplicationContext context = this.application.run("--spring.profiles.active=prod");
|
||||||
.run("--spring.config.name=configimportwithprofilespecific", "--spring.profiles.active=prod");
|
|
||||||
String value = context.getEnvironment().getProperty("prop");
|
String value = context.getEnvironment().getProperty("prop");
|
||||||
assertThat(value).isEqualTo("fromicwps2");
|
assertThat(value).isEqualTo("fromicwps2");
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -27,6 +27,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
|
|
||||||
import org.springframework.boot.DefaultBootstrapContext;
|
import org.springframework.boot.DefaultBootstrapContext;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.env.StandardEnvironment;
|
import org.springframework.core.env.StandardEnvironment;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@ -103,6 +104,8 @@ class ConfigDataEnvironmentPostProcessorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "property=value")
|
||||||
|
@WithResource(name = "application-dev.properties", content = "property=dev-value")
|
||||||
void applyToAppliesPostProcessing() {
|
void applyToAppliesPostProcessing() {
|
||||||
int before = this.environment.getPropertySources().size();
|
int before = this.environment.getPropertySources().size();
|
||||||
TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener();
|
TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.boot.context.config;
|
package org.springframework.boot.context.config;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -28,7 +27,6 @@ import java.util.Map;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.TestInfo;
|
import org.junit.jupiter.api.TestInfo;
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
@ -42,6 +40,7 @@ import org.springframework.boot.context.config.ConfigDataEnvironmentContributor.
|
|||||||
import org.springframework.boot.context.config.TestConfigDataEnvironmentUpdateListener.AddedPropertySource;
|
import org.springframework.boot.context.config.TestConfigDataEnvironmentUpdateListener.AddedPropertySource;
|
||||||
import org.springframework.boot.context.properties.bind.Binder;
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
import org.springframework.boot.logging.DeferredLogFactory;
|
import org.springframework.boot.logging.DeferredLogFactory;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
import org.springframework.core.env.ConfigurableEnvironment;
|
import org.springframework.core.env.ConfigurableEnvironment;
|
||||||
@ -149,8 +148,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void processAndApplyAddsImportedSourceToEnvironment(TestInfo info) {
|
@WithResource(name = "application.properties", content = "spring=boot")
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
void processAndApplyAddsImportedSourceToEnvironment() {
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
@ -158,8 +157,14 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void processAndApplyOnlyAddsActiveContributors(TestInfo info) {
|
@WithResource(name = "application.properties", content = """
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
spring=boot
|
||||||
|
#---
|
||||||
|
spring.config.activate.on-profile=missing
|
||||||
|
other=value
|
||||||
|
No newline at end of file
|
||||||
|
""")
|
||||||
|
void processAndApplyOnlyAddsActiveContributors() {
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
@ -180,8 +185,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "spring.profiles.default=one,two,three")
|
||||||
void processAndApplySetsDefaultProfiles(TestInfo info) {
|
void processAndApplySetsDefaultProfiles(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
@ -189,8 +194,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void processAndApplySetsActiveProfiles(TestInfo info) {
|
@WithResource(name = "application.properties", content = "spring.profiles.active=one,two,three")
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
void processAndApplySetsActiveProfiles() {
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
@ -198,8 +203,11 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void processAndApplySetsActiveProfilesAndProfileGroups(TestInfo info) {
|
@WithResource(name = "application.properties", content = """
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
spring.profiles.active=one,two,three
|
||||||
|
spring.profiles.group.one=four,five
|
||||||
|
""")
|
||||||
|
void processAndApplySetsActiveProfilesAndProfileGroups() {
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||||
configDataEnvironment.processAndApply();
|
configDataEnvironment.processAndApply();
|
||||||
@ -207,8 +215,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "spring.profiles.active=test")
|
||||||
void processAndApplyDoesNotSetProfilesFromIgnoreProfilesContributors(TestInfo info) {
|
void processAndApplyDoesNotSetProfilesFromIgnoreProfilesContributors(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, null) {
|
this.environment, this.resourceLoader, this.additionalProfiles, null) {
|
||||||
|
|
||||||
@ -281,8 +289,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "spring=boot")
|
||||||
void processAndApplyDoesNotSetProfilesFromIgnoreProfilesContributorsWhenNoProfilesActive(TestInfo info) {
|
void processAndApplyDoesNotSetProfilesFromIgnoreProfilesContributorsWhenNoProfilesActive(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, null) {
|
this.environment, this.resourceLoader, this.additionalProfiles, null) {
|
||||||
|
|
||||||
@ -307,9 +315,8 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled("Disabled until spring.profiles support is dropped")
|
|
||||||
void processAndApplyWhenHasInvalidPropertyThrowsException() {
|
void processAndApplyWhenHasInvalidPropertyThrowsException() {
|
||||||
this.environment.setProperty("spring.profile", "a");
|
this.environment.setProperty("spring.profiles", "a");
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||||
assertThatExceptionOfType(InvalidConfigDataPropertyException.class)
|
assertThatExceptionOfType(InvalidConfigDataPropertyException.class)
|
||||||
@ -317,8 +324,9 @@ class ConfigDataEnvironmentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "custom/config.properties", content = "spring=boot")
|
||||||
void processAndApplyWhenHasListenerCallsOnPropertySourceAdded(TestInfo info) {
|
void processAndApplyWhenHasListenerCallsOnPropertySourceAdded(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
this.environment.setProperty("spring.config.location", "classpath:custom/config.properties");
|
||||||
TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener();
|
TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener();
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, listener);
|
this.environment, this.resourceLoader, this.additionalProfiles, listener);
|
||||||
@ -326,14 +334,14 @@ class ConfigDataEnvironmentTests {
|
|||||||
assertThat(listener.getAddedPropertySources()).hasSize(1);
|
assertThat(listener.getAddedPropertySources()).hasSize(1);
|
||||||
AddedPropertySource addedPropertySource = listener.getAddedPropertySources().get(0);
|
AddedPropertySource addedPropertySource = listener.getAddedPropertySources().get(0);
|
||||||
assertThat(addedPropertySource.getPropertySource().getProperty("spring")).isEqualTo("boot");
|
assertThat(addedPropertySource.getPropertySource().getProperty("spring")).isEqualTo("boot");
|
||||||
assertThat(addedPropertySource.getLocation()).hasToString(getConfigLocation(info));
|
assertThat(addedPropertySource.getLocation()).hasToString("classpath:custom/config.properties");
|
||||||
assertThat(addedPropertySource.getResource().toString()).contains("class path resource")
|
assertThat(addedPropertySource.getResource().toString()).contains("class path resource")
|
||||||
.contains(info.getTestMethod().get().getName());
|
.contains("custom/config.properties");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "spring.profiles.active=one,two,three")
|
||||||
void processAndApplyWhenHasListenerCallsOnSetProfiles(TestInfo info) {
|
void processAndApplyWhenHasListenerCallsOnSetProfiles(TestInfo info) {
|
||||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
|
||||||
TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener();
|
TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener();
|
||||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||||
this.environment, this.resourceLoader, this.additionalProfiles, listener);
|
this.environment, this.resourceLoader, this.additionalProfiles, listener);
|
||||||
@ -343,17 +351,18 @@ class ConfigDataEnvironmentTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@WithResource(name = "separate-class-loader-spring.factories", content = """
|
||||||
|
org.springframework.boot.context.config.ConfigDataLoader=\
|
||||||
|
org.springframework.boot.context.config.ConfigDataEnvironmentTests$SeparateClassLoaderConfigDataLoader
|
||||||
|
""")
|
||||||
void configDataLoadersAreLoadedUsingClassLoaderFromResourceLoader() {
|
void configDataLoadersAreLoadedUsingClassLoaderFromResourceLoader() {
|
||||||
ResourceLoader resourceLoader = mock(ResourceLoader.class);
|
ResourceLoader resourceLoader = mock(ResourceLoader.class);
|
||||||
ClassLoader classLoader = new ClassLoader() {
|
ClassLoader classLoader = new ClassLoader(Thread.currentThread().getContextClassLoader()) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Enumeration<URL> getResources(String name) throws IOException {
|
public Enumeration<URL> getResources(String name) throws IOException {
|
||||||
if (SpringFactoriesLoader.FACTORIES_RESOURCE_LOCATION.equals(name)) {
|
if (SpringFactoriesLoader.FACTORIES_RESOURCE_LOCATION.equals(name)) {
|
||||||
return Collections.enumeration(List.of(new File(
|
return super.getResources("separate-class-loader-spring.factories");
|
||||||
"src/test/resources/org/springframework/boot/context/config/separate-class-loader-spring.factories")
|
|
||||||
.toURI()
|
|
||||||
.toURL()));
|
|
||||||
}
|
}
|
||||||
return super.getResources(name);
|
return super.getResources(name);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -28,6 +28,7 @@ import org.springframework.aot.hint.RuntimeHints;
|
|||||||
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
||||||
import org.springframework.boot.env.PropertySourceLoader;
|
import org.springframework.boot.env.PropertySourceLoader;
|
||||||
import org.springframework.boot.env.YamlPropertySourceLoader;
|
import org.springframework.boot.env.YamlPropertySourceLoader;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||||
import org.springframework.core.test.io.support.MockSpringFactoriesLoader;
|
import org.springframework.core.test.io.support.MockSpringFactoriesLoader;
|
||||||
|
|
||||||
@ -41,9 +42,11 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
class ConfigDataLocationRuntimeHintsTests {
|
class ConfigDataLocationRuntimeHintsTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties", content = "")
|
||||||
|
@WithResource(name = "config/application.properties", content = "")
|
||||||
void registerWithDefaultSettings() {
|
void registerWithDefaultSettings() {
|
||||||
RuntimeHints hints = new RuntimeHints();
|
RuntimeHints hints = new RuntimeHints();
|
||||||
new TestConfigDataLocationRuntimeHints().registerHints(hints, null);
|
new TestConfigDataLocationRuntimeHints().registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||||
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
||||||
.satisfies(includes("application*.properties", "application*.xml", "application*.yaml", "application*.yml",
|
.satisfies(includes("application*.properties", "application*.xml", "application*.yaml", "application*.yml",
|
||||||
"config/application*.properties", "config/application*.xml", "config/application*.yaml",
|
"config/application*.properties", "config/application*.xml", "config/application*.yaml",
|
||||||
@ -51,6 +54,8 @@ class ConfigDataLocationRuntimeHintsTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "test.properties")
|
||||||
|
@WithResource(name = "config/test.properties")
|
||||||
void registerWithCustomName() {
|
void registerWithCustomName() {
|
||||||
RuntimeHints hints = new RuntimeHints();
|
RuntimeHints hints = new RuntimeHints();
|
||||||
new TestConfigDataLocationRuntimeHints() {
|
new TestConfigDataLocationRuntimeHints() {
|
||||||
@ -59,13 +64,15 @@ class ConfigDataLocationRuntimeHintsTests {
|
|||||||
return List.of("test");
|
return List.of("test");
|
||||||
}
|
}
|
||||||
|
|
||||||
}.registerHints(hints, null);
|
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||||
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
||||||
.satisfies(includes("test*.properties", "test*.xml", "test*.yaml", "test*.yml", "config/test*.properties",
|
.satisfies(includes("test*.properties", "test*.xml", "test*.yaml", "test*.yml", "config/test*.properties",
|
||||||
"config/test*.xml", "config/test*.yaml", "config/test*.yml"));
|
"config/test*.xml", "config/test*.yaml", "config/test*.yml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties")
|
||||||
|
@WithResource(name = "config/application.properties")
|
||||||
void registerWithCustomLocation() {
|
void registerWithCustomLocation() {
|
||||||
RuntimeHints hints = new RuntimeHints();
|
RuntimeHints hints = new RuntimeHints();
|
||||||
new TestConfigDataLocationRuntimeHints() {
|
new TestConfigDataLocationRuntimeHints() {
|
||||||
@ -73,13 +80,15 @@ class ConfigDataLocationRuntimeHintsTests {
|
|||||||
protected List<String> getLocations(ClassLoader classLoader) {
|
protected List<String> getLocations(ClassLoader classLoader) {
|
||||||
return List.of("config/");
|
return List.of("config/");
|
||||||
}
|
}
|
||||||
}.registerHints(hints, null);
|
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||||
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
||||||
.satisfies(includes("config/application*.properties", "config/application*.xml", "config/application*.yaml",
|
.satisfies(includes("config/application*.properties", "config/application*.xml", "config/application*.yaml",
|
||||||
"config/application*.yml"));
|
"config/application*.yml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.conf")
|
||||||
|
@WithResource(name = "config/application.conf")
|
||||||
void registerWithCustomExtension() {
|
void registerWithCustomExtension() {
|
||||||
RuntimeHints hints = new RuntimeHints();
|
RuntimeHints hints = new RuntimeHints();
|
||||||
new ConfigDataLocationRuntimeHints() {
|
new ConfigDataLocationRuntimeHints() {
|
||||||
@ -87,7 +96,7 @@ class ConfigDataLocationRuntimeHintsTests {
|
|||||||
protected List<String> getExtensions(ClassLoader classLoader) {
|
protected List<String> getExtensions(ClassLoader classLoader) {
|
||||||
return List.of(".conf");
|
return List.of(".conf");
|
||||||
}
|
}
|
||||||
}.registerHints(hints, null);
|
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||||
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
||||||
.satisfies(includes("application*.conf", "config/application*.conf"));
|
.satisfies(includes("application*.conf", "config/application*.conf"));
|
||||||
}
|
}
|
||||||
@ -100,7 +109,7 @@ class ConfigDataLocationRuntimeHintsTests {
|
|||||||
protected List<String> getLocations(ClassLoader classLoader) {
|
protected List<String> getLocations(ClassLoader classLoader) {
|
||||||
return List.of(UUID.randomUUID().toString());
|
return List.of(UUID.randomUUID().toString());
|
||||||
}
|
}
|
||||||
}.registerHints(hints, null);
|
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||||
assertThat(hints.resources().resourcePatternHints()).isEmpty();
|
assertThat(hints.resources().resourcePatternHints()).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
||||||
import org.springframework.boot.env.YamlPropertySourceLoader;
|
import org.springframework.boot.env.YamlPropertySourceLoader;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
@ -41,32 +42,36 @@ class StandardConfigDataLoaderTests {
|
|||||||
private final ConfigDataLoaderContext loaderContext = mock(ConfigDataLoaderContext.class);
|
private final ConfigDataLoaderContext loaderContext = mock(ConfigDataLoaderContext.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.yml", content = """
|
||||||
|
foo: bar
|
||||||
|
---
|
||||||
|
hello: world
|
||||||
|
""")
|
||||||
void loadWhenLocationResultsInMultiplePropertySourcesAddsAllToConfigData() throws IOException {
|
void loadWhenLocationResultsInMultiplePropertySourcesAddsAllToConfigData() throws IOException {
|
||||||
ClassPathResource resource = new ClassPathResource("configdata/yaml/application.yml");
|
ClassPathResource resource = new ClassPathResource("application.yml");
|
||||||
StandardConfigDataReference reference = new StandardConfigDataReference(
|
StandardConfigDataReference reference = new StandardConfigDataReference(
|
||||||
ConfigDataLocation.of("classpath:configdata/yaml/application.yml"), null,
|
ConfigDataLocation.of("classpath:application.yml"), null, "classpath:application", null, "yml",
|
||||||
"classpath:configdata/yaml/application", null, "yml", new YamlPropertySourceLoader());
|
new YamlPropertySourceLoader());
|
||||||
StandardConfigDataResource location = new StandardConfigDataResource(reference, resource);
|
StandardConfigDataResource location = new StandardConfigDataResource(reference, resource);
|
||||||
ConfigData configData = this.loader.load(this.loaderContext, location);
|
ConfigData configData = this.loader.load(this.loaderContext, location);
|
||||||
assertThat(configData.getPropertySources()).hasSize(2);
|
assertThat(configData.getPropertySources()).hasSize(2);
|
||||||
PropertySource<?> source1 = configData.getPropertySources().get(0);
|
PropertySource<?> source1 = configData.getPropertySources().get(0);
|
||||||
PropertySource<?> source2 = configData.getPropertySources().get(1);
|
PropertySource<?> source2 = configData.getPropertySources().get(1);
|
||||||
assertThat(source1.getName())
|
assertThat(source1.getName()).isEqualTo("Config resource 'class path resource [application.yml]' "
|
||||||
.isEqualTo("Config resource 'class path resource [configdata/yaml/application.yml]' "
|
+ "via location 'classpath:application.yml' (document #0)");
|
||||||
+ "via location 'classpath:configdata/yaml/application.yml' (document #0)");
|
|
||||||
assertThat(source1.getProperty("foo")).isEqualTo("bar");
|
assertThat(source1.getProperty("foo")).isEqualTo("bar");
|
||||||
assertThat(source2.getName())
|
assertThat(source2.getName()).isEqualTo("Config resource 'class path resource [application.yml]' "
|
||||||
.isEqualTo("Config resource 'class path resource [configdata/yaml/application.yml]' "
|
+ "via location 'classpath:application.yml' (document #1)");
|
||||||
+ "via location 'classpath:configdata/yaml/application.yml' (document #1)");
|
|
||||||
assertThat(source2.getProperty("hello")).isEqualTo("world");
|
assertThat(source2.getProperty("hello")).isEqualTo("world");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "empty.properties")
|
||||||
void loadWhenPropertySourceIsEmptyAddsNothingToConfigData() throws IOException {
|
void loadWhenPropertySourceIsEmptyAddsNothingToConfigData() throws IOException {
|
||||||
ClassPathResource resource = new ClassPathResource("config/0-empty/testproperties.properties");
|
ClassPathResource resource = new ClassPathResource("empty.properties");
|
||||||
StandardConfigDataReference reference = new StandardConfigDataReference(
|
StandardConfigDataReference reference = new StandardConfigDataReference(
|
||||||
ConfigDataLocation.of("classpath:config/0-empty/testproperties.properties"), null,
|
ConfigDataLocation.of("empty.properties"), null, "empty", null, "properties",
|
||||||
"config/0-empty/testproperties", null, "properties", new PropertiesPropertySourceLoader());
|
new PropertiesPropertySourceLoader());
|
||||||
StandardConfigDataResource location = new StandardConfigDataResource(reference, resource);
|
StandardConfigDataResource location = new StandardConfigDataResource(reference, resource);
|
||||||
ConfigData configData = this.loader.load(this.loaderContext, location);
|
ConfigData configData = this.loader.load(this.loaderContext, location);
|
||||||
assertThat(configData.getPropertySources()).isEmpty();
|
assertThat(configData.getPropertySources()).isEmpty();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -17,6 +17,7 @@
|
|||||||
package org.springframework.boot.context.config;
|
package org.springframework.boot.context.config;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -26,6 +27,8 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.springframework.boot.context.properties.bind.Binder;
|
import org.springframework.boot.context.properties.bind.Binder;
|
||||||
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
import org.springframework.boot.env.PropertiesPropertySourceLoader;
|
||||||
import org.springframework.boot.logging.DeferredLogs;
|
import org.springframework.boot.logging.DeferredLogs;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.ResourcesRoot;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
@ -71,23 +74,22 @@ class StandardConfigDataLocationResolverTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "configdata/application.properties")
|
||||||
void resolveWhenLocationIsDirectoryResolvesAllMatchingFilesInDirectory() {
|
void resolveWhenLocationIsDirectoryResolvesAllMatchingFilesInDirectory() {
|
||||||
ConfigDataLocation location = ConfigDataLocation.of("classpath:/configdata/properties/");
|
ConfigDataLocation location = ConfigDataLocation.of("classpath:/configdata/");
|
||||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||||
assertThat(locations).hasSize(1);
|
assertThat(locations).hasSize(1);
|
||||||
assertThat(locations).extracting(Object::toString)
|
assertThat(locations).extracting(Object::toString)
|
||||||
.containsExactly("class path resource [configdata/properties/application.properties]");
|
.containsExactly("class path resource [configdata/application.properties]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void resolveWhenLocationIsFileResolvesFile() {
|
void resolveWhenLocationIsFileResolvesFile() {
|
||||||
ConfigDataLocation location = ConfigDataLocation
|
ConfigDataLocation location = ConfigDataLocation.of("file:configdata/application.properties");
|
||||||
.of("file:src/test/resources/configdata/properties/application.properties");
|
|
||||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||||
assertThat(locations).hasSize(1);
|
assertThat(locations).hasSize(1);
|
||||||
assertThat(locations).extracting(Object::toString)
|
assertThat(locations).extracting(Object::toString)
|
||||||
.containsExactly(
|
.containsExactly(filePath("configdata", "application.properties"));
|
||||||
filePath("src", "test", "resources", "configdata", "properties", "application.properties"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -143,49 +145,55 @@ class StandardConfigDataLocationResolverTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void resolveWhenLocationIsWildcardDirectoriesRestrictsToOneLevelDeep() {
|
@WithResource(name = "config/0-empty/testproperties.properties")
|
||||||
ConfigDataLocation location = ConfigDataLocation.of("file:src/test/resources/config/*/");
|
@WithResource(name = "config/1-first/testproperties.properties", content = "first.property=apple")
|
||||||
|
@WithResource(name = "config/2-second/testproperties.properties", content = "second.property=ball")
|
||||||
|
@WithResource(name = "config/nested/3-third/testproperties.properties", content = "third.property=shouldnotbefound")
|
||||||
|
void resolveWhenLocationIsWildcardDirectoriesRestrictsToOneLevelDeep(@ResourcesRoot Path resourcesRoot) {
|
||||||
|
ConfigDataLocation location = ConfigDataLocation.of("file:" + resourcesRoot + "/config/*/");
|
||||||
this.environment.setProperty("spring.config.name", "testproperties");
|
this.environment.setProperty("spring.config.name", "testproperties");
|
||||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||||
this.resourceLoader);
|
this.resourceLoader);
|
||||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||||
assertThat(locations).hasSize(3);
|
assertThat(locations).hasSize(3);
|
||||||
assertThat(locations).extracting(Object::toString)
|
assertThat(locations).extracting(Object::toString)
|
||||||
.contains(filePath("src", "test", "resources", "config", "1-first", "testproperties.properties"))
|
.contains(filePath(resourcesRoot.resolve("config/1-first/testproperties.properties")))
|
||||||
.contains(filePath("src", "test", "resources", "config", "2-second", "testproperties.properties"))
|
.contains(filePath(resourcesRoot.resolve("config/2-second/testproperties.properties")))
|
||||||
.doesNotContain(filePath("src", "test", "resources", "config", "3-third", "testproperties.properties"));
|
.doesNotContain(filePath(resourcesRoot.resolve("config/nested/3-third/testproperties.properties")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void resolveWhenLocationIsWildcardDirectoriesSortsAlphabeticallyBasedOnAbsolutePath() {
|
@WithResource(name = "config/0-empty/testproperties.properties")
|
||||||
ConfigDataLocation location = ConfigDataLocation.of("file:src/test/resources/config/*/");
|
@WithResource(name = "config/1-first/testproperties.properties", content = "first.property=apple")
|
||||||
|
@WithResource(name = "config/2-second/testproperties.properties", content = "second.property=ball")
|
||||||
|
@WithResource(name = "config/nested/3-third/testproperties.properties", content = "third.property=shouldnotbefound")
|
||||||
|
void resolveWhenLocationIsWildcardDirectoriesSortsAlphabeticallyBasedOnAbsolutePath(
|
||||||
|
@ResourcesRoot Path resourcesRoot) {
|
||||||
|
ConfigDataLocation location = ConfigDataLocation.of("file:" + resourcesRoot + "/config/*/");
|
||||||
this.environment.setProperty("spring.config.name", "testproperties");
|
this.environment.setProperty("spring.config.name", "testproperties");
|
||||||
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
this.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||||
this.resourceLoader);
|
this.resourceLoader);
|
||||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||||
assertThat(locations).extracting(Object::toString)
|
assertThat(locations).extracting(Object::toString)
|
||||||
.containsExactly(filePath("src", "test", "resources", "config", "0-empty", "testproperties.properties"),
|
.containsExactly(filePath(resourcesRoot.resolve("config/0-empty/testproperties.properties")),
|
||||||
filePath("src", "test", "resources", "config", "1-first", "testproperties.properties"),
|
filePath(resourcesRoot.resolve("config/1-first/testproperties.properties")),
|
||||||
filePath("src", "test", "resources", "config", "2-second", "testproperties.properties"));
|
filePath(resourcesRoot.resolve("config/2-second/testproperties.properties")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void resolveWhenLocationIsWildcardAndMatchingFilePresentShouldNotFail() {
|
@WithResource(name = "config/0-empty/testproperties.properties")
|
||||||
ConfigDataLocation location = ConfigDataLocation.of("optional:file:src/test/resources/a-file/*/");
|
@WithResource(name = "config/1-first/testproperties.properties", content = "first.property=apple")
|
||||||
assertThatNoException().isThrownBy(() -> this.resolver.resolve(this.context, location));
|
@WithResource(name = "config/2-second/testproperties.properties", content = "second.property=ball")
|
||||||
}
|
@WithResource(name = "config/nested/3-third/testproperties.properties", content = "third.property=shouldnotbefound")
|
||||||
|
void resolveWhenLocationIsWildcardFilesLoadsAllFilesThatMatch(@ResourcesRoot Path resourcesRoot) {
|
||||||
@Test
|
|
||||||
void resolveWhenLocationIsWildcardFilesLoadsAllFilesThatMatch() {
|
|
||||||
ConfigDataLocation location = ConfigDataLocation
|
ConfigDataLocation location = ConfigDataLocation
|
||||||
.of("file:src/test/resources/config/*/testproperties.properties");
|
.of("file:" + resourcesRoot + "/config/*/testproperties.properties");
|
||||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||||
assertThat(locations).hasSize(3);
|
assertThat(locations).hasSize(3);
|
||||||
assertThat(locations).extracting(Object::toString)
|
assertThat(locations).extracting(Object::toString)
|
||||||
.contains(filePath("src", "test", "resources", "config", "1-first", "testproperties.properties"))
|
.contains(filePath(resourcesRoot.resolve("config/1-first/testproperties.properties")))
|
||||||
.contains(filePath("src", "test", "resources", "config", "2-second", "testproperties.properties"))
|
.contains(filePath(resourcesRoot.resolve("config/2-second/testproperties.properties")))
|
||||||
.doesNotContain(
|
.doesNotContain(filePath(resourcesRoot.resolve("config/nested/3-third/testproperties.properties")));
|
||||||
filePath("src", "test", "resources", "config", "nested", "3-third", "testproperties.properties"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -208,6 +216,8 @@ class StandardConfigDataLocationResolverTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "config/specific.properties")
|
||||||
|
@WithResource(name = "config/nested/3-third/testproperties.properties")
|
||||||
void resolveWhenLocationIsRelativeAndDirectoryResolves() {
|
void resolveWhenLocationIsRelativeAndDirectoryResolves() {
|
||||||
this.environment.setProperty("spring.config.name", "testproperties");
|
this.environment.setProperty("spring.config.name", "testproperties");
|
||||||
ConfigDataLocation location = ConfigDataLocation.of("nested/3-third/");
|
ConfigDataLocation location = ConfigDataLocation.of("nested/3-third/");
|
||||||
@ -240,6 +250,7 @@ class StandardConfigDataLocationResolverTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application-props-no-extension", content = "withnoextension=test")
|
||||||
void resolveWhenLocationUsesOptionalExtensionSyntaxResolves() throws Exception {
|
void resolveWhenLocationUsesOptionalExtensionSyntaxResolves() throws Exception {
|
||||||
ConfigDataLocation location = ConfigDataLocation.of("classpath:/application-props-no-extension[.properties]");
|
ConfigDataLocation location = ConfigDataLocation.of("classpath:/application-props-no-extension[.properties]");
|
||||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||||
@ -248,19 +259,20 @@ class StandardConfigDataLocationResolverTests {
|
|||||||
assertThat(resolved.getResource().getFilename()).endsWith("application-props-no-extension");
|
assertThat(resolved.getResource().getFilename()).endsWith("application-props-no-extension");
|
||||||
ConfigData loaded = new StandardConfigDataLoader().load(null, resolved);
|
ConfigData loaded = new StandardConfigDataLoader().load(null, resolved);
|
||||||
PropertySource<?> propertySource = loaded.getPropertySources().get(0);
|
PropertySource<?> propertySource = loaded.getPropertySources().get(0);
|
||||||
assertThat(propertySource.getProperty("withnotext")).isEqualTo("test");
|
assertThat(propertySource.getProperty("withnoextension")).isEqualTo("test");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application-dev.properties")
|
||||||
void resolveProfileSpecificReturnsProfileSpecificFiles() {
|
void resolveProfileSpecificReturnsProfileSpecificFiles() {
|
||||||
ConfigDataLocation location = ConfigDataLocation.of("classpath:/configdata/properties/");
|
ConfigDataLocation location = ConfigDataLocation.of("classpath:/");
|
||||||
Profiles profiles = mock(Profiles.class);
|
Profiles profiles = mock(Profiles.class);
|
||||||
given(profiles.iterator()).willReturn(Collections.singletonList("dev").iterator());
|
given(profiles.iterator()).willReturn(Collections.singletonList("dev").iterator());
|
||||||
List<StandardConfigDataResource> locations = this.resolver.resolveProfileSpecific(this.context, location,
|
List<StandardConfigDataResource> locations = this.resolver.resolveProfileSpecific(this.context, location,
|
||||||
profiles);
|
profiles);
|
||||||
assertThat(locations).hasSize(1);
|
assertThat(locations).hasSize(1);
|
||||||
assertThat(locations).extracting(Object::toString)
|
assertThat(locations).extracting(Object::toString)
|
||||||
.containsExactly("class path resource [configdata/properties/application-dev.properties]");
|
.containsExactly("class path resource [application-dev.properties]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -297,4 +309,8 @@ class StandardConfigDataLocationResolverTests {
|
|||||||
return "file [" + String.join(File.separator, components) + "]";
|
return "file [" + String.join(File.separator, components) + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String filePath(Path path) {
|
||||||
|
return "file [%s]".formatted(path);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,10 @@ package org.springframework.boot.context.logging;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -62,6 +66,7 @@ import org.springframework.boot.logging.LoggingSystemProperty;
|
|||||||
import org.springframework.boot.logging.java.JavaLoggingSystem;
|
import org.springframework.boot.logging.java.JavaLoggingSystem;
|
||||||
import org.springframework.boot.system.ApplicationPid;
|
import org.springframework.boot.system.ApplicationPid;
|
||||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
import org.springframework.context.ApplicationEvent;
|
import org.springframework.context.ApplicationEvent;
|
||||||
@ -160,8 +165,9 @@ class LoggingApplicationListenerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
void overrideConfigLocation() {
|
void overrideConfigLocation() {
|
||||||
addPropertiesToEnvironment(this.context, "logging.config=classpath:logback-nondefault.xml");
|
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml");
|
||||||
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(this.output).contains("Hello world").doesNotContain("???").startsWith("null ").endsWith("BOOTBOOT");
|
assertThat(this.output).contains("Hello world").doesNotContain("???").startsWith("null ").endsWith("BOOTBOOT");
|
||||||
@ -178,8 +184,9 @@ class LoggingApplicationListenerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
void trailingWhitespaceInLoggingConfigShouldBeTrimmed() {
|
void trailingWhitespaceInLoggingConfigShouldBeTrimmed() {
|
||||||
addPropertiesToEnvironment(this.context, "logging.config=classpath:logback-nondefault.xml ");
|
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml ");
|
||||||
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(this.output).contains("Hello world").doesNotContain("???").startsWith("null ").endsWith("BOOTBOOT");
|
assertThat(this.output).contains("Hello world").doesNotContain("???").startsWith("null ").endsWith("BOOTBOOT");
|
||||||
@ -226,8 +233,9 @@ class LoggingApplicationListenerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
void addLogFileProperty() {
|
void addLogFileProperty() {
|
||||||
addPropertiesToEnvironment(this.context, "logging.config=classpath:logback-nondefault.xml",
|
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml",
|
||||||
"logging.file.name=" + this.logFile);
|
"logging.file.name=" + this.logFile);
|
||||||
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
||||||
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
|
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
|
||||||
@ -248,8 +256,9 @@ class LoggingApplicationListenerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
void addLogPathProperty() {
|
void addLogPathProperty() {
|
||||||
addPropertiesToEnvironment(this.context, "logging.config=classpath:logback-nondefault.xml",
|
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml",
|
||||||
"logging.file.path=" + this.tempDir);
|
"logging.file.path=" + this.tempDir);
|
||||||
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
||||||
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
|
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
|
||||||
@ -779,4 +788,22 @@ class LoggingApplicationListenerTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "nondefault.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%property{LOG_FILE} [%t] ${PID:-????} %c{1}: %m%n BOOTBOOT</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithNonDefaultXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -69,6 +69,7 @@ import org.springframework.boot.convert.PeriodFormat;
|
|||||||
import org.springframework.boot.convert.PeriodStyle;
|
import org.springframework.boot.convert.PeriodStyle;
|
||||||
import org.springframework.boot.convert.PeriodUnit;
|
import org.springframework.boot.convert.PeriodUnit;
|
||||||
import org.springframework.boot.env.RandomValuePropertySource;
|
import org.springframework.boot.env.RandomValuePropertySource;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
@ -260,6 +261,21 @@ class ConfigurationPropertiesTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "testProperties.xml",
|
||||||
|
content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<bean
|
||||||
|
id="org.springframework.boot.context.properties.ConfigurationPropertiesTests$BasicProperties"
|
||||||
|
class="org.springframework.boot.context.properties.ConfigurationPropertiesTests$BasicProperties">
|
||||||
|
<property name="name" value="bar"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
</beans>
|
||||||
|
""")
|
||||||
void loadWhenBindingWithDefaultsInXmlShouldBind() {
|
void loadWhenBindingWithDefaultsInXmlShouldBind() {
|
||||||
removeSystemProperties();
|
removeSystemProperties();
|
||||||
load(new Class<?>[] { DefaultsInXmlConfiguration.class });
|
load(new Class<?>[] { DefaultsInXmlConfiguration.class });
|
||||||
@ -633,6 +649,7 @@ class ConfigurationPropertiesTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "application.properties")
|
||||||
void customProtocolResolver() {
|
void customProtocolResolver() {
|
||||||
this.context = new AnnotationConfigApplicationContext();
|
this.context = new AnnotationConfigApplicationContext();
|
||||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
|
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
|
||||||
@ -1356,7 +1373,7 @@ class ConfigurationPropertiesTests {
|
|||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@EnableConfigurationProperties
|
@EnableConfigurationProperties
|
||||||
@ImportResource("org/springframework/boot/context/properties/testProperties.xml")
|
@ImportResource("testProperties.xml")
|
||||||
static class DefaultsInXmlConfiguration {
|
static class DefaultsInXmlConfiguration {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -23,6 +23,7 @@ import java.util.stream.Stream;
|
|||||||
import org.junit.jupiter.api.io.TempDir;
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
import org.junit.jupiter.params.provider.Arguments;
|
import org.junit.jupiter.params.provider.Arguments;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
@ -52,9 +53,10 @@ class StringToFileConverterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConversionServiceTest
|
@ConversionServiceTest
|
||||||
|
@WithResource(name = "com/example/test-file.txt", content = "test content")
|
||||||
void convertWhenClasspathPrefixedReturnsFile(ConversionService conversionService) throws IOException {
|
void convertWhenClasspathPrefixedReturnsFile(ConversionService conversionService) throws IOException {
|
||||||
String resource = new ClassPathResource("test-banner.txt", this.getClass().getClassLoader()).getURL().getFile();
|
String resource = new ClassPathResource("com/example/test-file.txt").getURL().getFile();
|
||||||
assertThat(convert(conversionService, "classpath:test-banner.txt").getAbsoluteFile())
|
assertThat(convert(conversionService, "classpath:com/example/test-file.txt").getAbsoluteFile())
|
||||||
.isEqualTo(new File(resource).getAbsoluteFile());
|
.isEqualTo(new File(resource).getAbsoluteFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.boot.diagnostics.FailureAnalysis;
|
import org.springframework.boot.diagnostics.FailureAnalysis;
|
||||||
import org.springframework.boot.diagnostics.analyzer.nounique.TestBean;
|
import org.springframework.boot.diagnostics.analyzer.nounique.TestBean;
|
||||||
import org.springframework.boot.diagnostics.analyzer.nounique.TestBeanConsumer;
|
import org.springframework.boot.diagnostics.analyzer.nounique.TestBeanConsumer;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
@ -38,6 +39,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
* @author Andy Wilkinson
|
* @author Andy Wilkinson
|
||||||
* @author Scott Frederick
|
* @author Scott Frederick
|
||||||
*/
|
*/
|
||||||
|
@WithResource(name = "producer.xml",
|
||||||
|
content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<bean class="org.springframework.boot.diagnostics.analyzer.nounique.TestBean" name="xmlTestBean"/>
|
||||||
|
|
||||||
|
</beans>
|
||||||
|
""")
|
||||||
class NoUniqueBeanDefinitionFailureAnalyzerTests {
|
class NoUniqueBeanDefinitionFailureAnalyzerTests {
|
||||||
|
|
||||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||||
@ -78,6 +90,17 @@ class NoUniqueBeanDefinitionFailureAnalyzerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "consumer.xml",
|
||||||
|
content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<bean class="org.springframework.boot.diagnostics.analyzer.nounique.TestBeanConsumer"/>
|
||||||
|
|
||||||
|
</beans>
|
||||||
|
""")
|
||||||
void failureAnalysisForXmlConsumer() {
|
void failureAnalysisForXmlConsumer() {
|
||||||
FailureAnalysis failureAnalysis = analyzeFailure(createFailure(XmlConsumer.class));
|
FailureAnalysis failureAnalysis = analyzeFailure(createFailure(XmlConsumer.class));
|
||||||
assertThat(failureAnalysis.getDescription()).startsWith("Parameter 0 of constructor in "
|
assertThat(failureAnalysis.getDescription()).startsWith("Parameter 0 of constructor in "
|
||||||
@ -131,7 +154,7 @@ class NoUniqueBeanDefinitionFailureAnalyzerTests {
|
|||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ComponentScan(basePackageClasses = TestBean.class)
|
@ComponentScan(basePackageClasses = TestBean.class)
|
||||||
@ImportResource("/org/springframework/boot/diagnostics/analyzer/nounique/producer.xml")
|
@ImportResource("classpath:producer.xml")
|
||||||
static class DuplicateBeansProducer {
|
static class DuplicateBeansProducer {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@ -200,7 +223,7 @@ class NoUniqueBeanDefinitionFailureAnalyzerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@ImportResource("/org/springframework/boot/diagnostics/analyzer/nounique/consumer.xml")
|
@ImportResource("classpath:consumer.xml")
|
||||||
static class XmlConsumer {
|
static class XmlConsumer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -26,6 +26,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.springframework.boot.env.OriginTrackedPropertiesLoader.Document;
|
import org.springframework.boot.env.OriginTrackedPropertiesLoader.Document;
|
||||||
import org.springframework.boot.origin.OriginTrackedValue;
|
import org.springframework.boot.origin.OriginTrackedValue;
|
||||||
import org.springframework.boot.origin.TextResourceOrigin;
|
import org.springframework.boot.origin.TextResourceOrigin;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||||
@ -92,9 +93,10 @@ class OriginTrackedPropertiesLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "malformed-unicode.properties", content = "test-malformed-unicode=properties\\u(026test")
|
||||||
void getMalformedUnicodeProperty() {
|
void getMalformedUnicodeProperty() {
|
||||||
// gh-12716
|
// gh-12716
|
||||||
ClassPathResource resource = new ClassPathResource("test-properties-malformed-unicode.properties", getClass());
|
ClassPathResource resource = new ClassPathResource("malformed-unicode.properties");
|
||||||
assertThatIllegalStateException().isThrownBy(() -> new OriginTrackedPropertiesLoader(resource).load())
|
assertThatIllegalStateException().isThrownBy(() -> new OriginTrackedPropertiesLoader(resource).load())
|
||||||
.withMessageContaining("Malformed \\uxxxx encoding");
|
.withMessageContaining("Malformed \\uxxxx encoding");
|
||||||
}
|
}
|
||||||
@ -326,8 +328,43 @@ class OriginTrackedPropertiesLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "existing-non-multi-document.properties", content = """
|
||||||
|
#---
|
||||||
|
# Test
|
||||||
|
#---
|
||||||
|
|
||||||
|
spring=boot
|
||||||
|
|
||||||
|
#---
|
||||||
|
# Test
|
||||||
|
|
||||||
|
boot=bar
|
||||||
|
|
||||||
|
|
||||||
|
# Test
|
||||||
|
#---
|
||||||
|
|
||||||
|
bar=ok
|
||||||
|
|
||||||
|
!---
|
||||||
|
! Test
|
||||||
|
!---
|
||||||
|
|
||||||
|
ok=well
|
||||||
|
|
||||||
|
!---
|
||||||
|
! Test
|
||||||
|
|
||||||
|
well=hello
|
||||||
|
|
||||||
|
! Test
|
||||||
|
!---
|
||||||
|
|
||||||
|
hello=world
|
||||||
|
|
||||||
|
""")
|
||||||
void existingCommentsAreNotTreatedAsMultiDoc() throws Exception {
|
void existingCommentsAreNotTreatedAsMultiDoc() throws Exception {
|
||||||
this.resource = new ClassPathResource("existing-non-multi-document.properties", getClass());
|
this.resource = new ClassPathResource("existing-non-multi-document.properties");
|
||||||
this.documents = new OriginTrackedPropertiesLoader(this.resource).load();
|
this.documents = new OriginTrackedPropertiesLoader(this.resource).load();
|
||||||
assertThat(this.documents).hasSize(1);
|
assertThat(this.documents).hasSize(1);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package org.springframework.boot.env;
|
package org.springframework.boot.env;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -27,6 +31,7 @@ import org.yaml.snakeyaml.composer.ComposerException;
|
|||||||
|
|
||||||
import org.springframework.boot.origin.OriginTrackedValue;
|
import org.springframework.boot.origin.OriginTrackedValue;
|
||||||
import org.springframework.boot.origin.TextResourceOrigin;
|
import org.springframework.boot.origin.TextResourceOrigin;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
@ -48,11 +53,12 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void setUp() {
|
void setUp() {
|
||||||
Resource resource = new ClassPathResource("test-yaml.yml", getClass());
|
Resource resource = new ClassPathResource("test-yaml.yml");
|
||||||
this.loader = new OriginTrackedYamlLoader(resource);
|
this.loader = new OriginTrackedYamlLoader(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithTestYamlResource
|
||||||
void processSimpleKey() {
|
void processSimpleKey() {
|
||||||
OriginTrackedValue value = getValue("name");
|
OriginTrackedValue value = getValue("name");
|
||||||
assertThat(value).hasToString("Martin D'vloper");
|
assertThat(value).hasToString("Martin D'vloper");
|
||||||
@ -60,6 +66,7 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithTestYamlResource
|
||||||
void processMap() {
|
void processMap() {
|
||||||
OriginTrackedValue perl = getValue("languages.perl");
|
OriginTrackedValue perl = getValue("languages.perl");
|
||||||
OriginTrackedValue python = getValue("languages.python");
|
OriginTrackedValue python = getValue("languages.python");
|
||||||
@ -73,6 +80,7 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithTestYamlResource
|
||||||
void processCollection() {
|
void processCollection() {
|
||||||
OriginTrackedValue apple = getValue("foods[0]");
|
OriginTrackedValue apple = getValue("foods[0]");
|
||||||
OriginTrackedValue orange = getValue("foods[1]");
|
OriginTrackedValue orange = getValue("foods[1]");
|
||||||
@ -89,6 +97,7 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithTestYamlResource
|
||||||
void processMultiline() {
|
void processMultiline() {
|
||||||
OriginTrackedValue education = getValue("education");
|
OriginTrackedValue education = getValue("education");
|
||||||
assertThat(education).hasToString("4 GCSEs\n3 A-Levels\nBSc in the Internet of Things\n");
|
assertThat(education).hasToString("4 GCSEs\n3 A-Levels\nBSc in the Internet of Things\n");
|
||||||
@ -96,6 +105,7 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithTestYamlResource
|
||||||
void processListOfMaps() {
|
void processListOfMaps() {
|
||||||
OriginTrackedValue name = getValue("example.foo[0].name");
|
OriginTrackedValue name = getValue("example.foo[0].name");
|
||||||
OriginTrackedValue url = getValue("example.foo[0].url");
|
OriginTrackedValue url = getValue("example.foo[0].url");
|
||||||
@ -112,6 +122,7 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithTestYamlResource
|
||||||
void processEmptyAndNullValues() {
|
void processEmptyAndNullValues() {
|
||||||
OriginTrackedValue empty = getValue("empty");
|
OriginTrackedValue empty = getValue("empty");
|
||||||
OriginTrackedValue nullValue = getValue("null-value");
|
OriginTrackedValue nullValue = getValue("null-value");
|
||||||
@ -122,6 +133,7 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithTestYamlResource
|
||||||
void processEmptyListAndMap() {
|
void processEmptyListAndMap() {
|
||||||
OriginTrackedValue emptymap = getValue("emptymap");
|
OriginTrackedValue emptymap = getValue("emptymap");
|
||||||
OriginTrackedValue emptylist = getValue("emptylist");
|
OriginTrackedValue emptylist = getValue("emptylist");
|
||||||
@ -138,8 +150,15 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "test-empty-yaml.yml", content = """
|
||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
---
|
||||||
|
""")
|
||||||
void emptyDocuments() {
|
void emptyDocuments() {
|
||||||
this.loader = new OriginTrackedYamlLoader(new ClassPathResource("test-empty-yaml.yml", getClass()));
|
this.loader = new OriginTrackedYamlLoader(new ClassPathResource("test-empty-yaml.yml"));
|
||||||
List<Map<String, Object>> loaded = this.loader.load();
|
List<Map<String, Object>> loaded = this.loader.load();
|
||||||
assertThat(loaded).isEmpty();
|
assertThat(loaded).isEmpty();
|
||||||
}
|
}
|
||||||
@ -165,8 +184,17 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "recursive.yml", content = """
|
||||||
|
&def1
|
||||||
|
*def1: a
|
||||||
|
test:
|
||||||
|
a:
|
||||||
|
spring: 'a'
|
||||||
|
b:
|
||||||
|
boot: 'b'
|
||||||
|
""")
|
||||||
void loadWhenRecursiveLoadsYaml() {
|
void loadWhenRecursiveLoadsYaml() {
|
||||||
Resource resource = new ClassPathResource("recursive.yml", getClass());
|
Resource resource = new ClassPathResource("recursive.yml");
|
||||||
this.loader = new OriginTrackedYamlLoader(resource);
|
this.loader = new OriginTrackedYamlLoader(resource);
|
||||||
Map<String, Object> loaded = this.loader.load().get(0);
|
Map<String, Object> loaded = this.loader.load().get(0);
|
||||||
assertThat(loaded.get("test.a.spring")).hasToString("a");
|
assertThat(loaded.get("test.a.spring")).hasToString("a");
|
||||||
@ -174,8 +202,16 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "anchors.yml", content = """
|
||||||
|
some:
|
||||||
|
path: &anchor
|
||||||
|
config:
|
||||||
|
key: value
|
||||||
|
anotherpath:
|
||||||
|
<<: *anchor
|
||||||
|
""")
|
||||||
void loadWhenUsingAnchors() {
|
void loadWhenUsingAnchors() {
|
||||||
Resource resource = new ClassPathResource("anchors.yml", getClass());
|
Resource resource = new ClassPathResource("anchors.yml");
|
||||||
this.loader = new OriginTrackedYamlLoader(resource);
|
this.loader = new OriginTrackedYamlLoader(resource);
|
||||||
Map<String, Object> loaded = this.loader.load().get(0);
|
Map<String, Object> loaded = this.loader.load().get(0);
|
||||||
assertThat(loaded.get("some.path.config.key")).hasToString("value");
|
assertThat(loaded.get("some.path.config.key")).hasToString("value");
|
||||||
@ -205,4 +241,49 @@ class OriginTrackedYamlLoaderTests {
|
|||||||
return ((TextResourceOrigin) value.getOrigin()).getLocation().toString();
|
return ((TextResourceOrigin) value.getOrigin()).getLocation().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@WithResource(name = "test-yaml.yml", content = """
|
||||||
|
# https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html
|
||||||
|
|
||||||
|
name: Martin D'vloper
|
||||||
|
job: Developer
|
||||||
|
skill: Elite
|
||||||
|
employed: True
|
||||||
|
foods:
|
||||||
|
- Apple
|
||||||
|
- Orange
|
||||||
|
- Strawberry
|
||||||
|
- Mango
|
||||||
|
languages:
|
||||||
|
perl: Elite
|
||||||
|
python: Elite
|
||||||
|
pascal: Lame
|
||||||
|
education: |
|
||||||
|
4 GCSEs
|
||||||
|
3 A-Levels
|
||||||
|
BSc in the Internet of Things
|
||||||
|
example:
|
||||||
|
foo:
|
||||||
|
- name: springboot
|
||||||
|
url: https://springboot.example.com/
|
||||||
|
bar:
|
||||||
|
- bar1: baz
|
||||||
|
- bar2: bling
|
||||||
|
empty: ""
|
||||||
|
null-value: null
|
||||||
|
emptylist: []
|
||||||
|
emptymap: {}
|
||||||
|
---
|
||||||
|
|
||||||
|
spring:
|
||||||
|
profiles: development
|
||||||
|
name: Test Name
|
||||||
|
|
||||||
|
---
|
||||||
|
""")
|
||||||
|
private @interface WithTestYamlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -20,6 +20,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
@ -41,17 +42,28 @@ class PropertiesPropertySourceLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "test.properties", content = "test=properties")
|
||||||
void loadProperties() throws Exception {
|
void loadProperties() throws Exception {
|
||||||
List<PropertySource<?>> loaded = this.loader.load("test.properties",
|
List<PropertySource<?>> loaded = this.loader.load("test.properties", new ClassPathResource("test.properties"));
|
||||||
new ClassPathResource("test-properties.properties", getClass()));
|
|
||||||
PropertySource<?> source = loaded.get(0);
|
PropertySource<?> source = loaded.get(0);
|
||||||
assertThat(source.getProperty("test")).isEqualTo("properties");
|
assertThat(source.getProperty("test")).isEqualTo("properties");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "test.properties", content = """
|
||||||
|
#---
|
||||||
|
#test
|
||||||
|
blah=hello world
|
||||||
|
bar=baz
|
||||||
|
hello=world
|
||||||
|
#---
|
||||||
|
foo=bar
|
||||||
|
bling=biz
|
||||||
|
#comment1
|
||||||
|
#comment2
|
||||||
|
""")
|
||||||
void loadMultiDocumentPropertiesWithSeparatorAtTheBeginningOfFile() throws Exception {
|
void loadMultiDocumentPropertiesWithSeparatorAtTheBeginningOfFile() throws Exception {
|
||||||
List<PropertySource<?>> loaded = this.loader.load("test.properties",
|
List<PropertySource<?>> loaded = this.loader.load("test.properties", new ClassPathResource("test.properties"));
|
||||||
new ClassPathResource("multi-document-properties-2.properties", getClass()));
|
|
||||||
assertThat(loaded).hasSize(2);
|
assertThat(loaded).hasSize(2);
|
||||||
PropertySource<?> source1 = loaded.get(0);
|
PropertySource<?> source1 = loaded.get(0);
|
||||||
PropertySource<?> source2 = loaded.get(1);
|
PropertySource<?> source2 = loaded.get(1);
|
||||||
@ -60,9 +72,20 @@ class PropertiesPropertySourceLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "test.properties", content = """
|
||||||
|
#test
|
||||||
|
blah=hello world
|
||||||
|
bar=baz
|
||||||
|
hello=world
|
||||||
|
#---
|
||||||
|
foo=bar
|
||||||
|
bling=biz
|
||||||
|
#comment1
|
||||||
|
#comment2
|
||||||
|
#---
|
||||||
|
""")
|
||||||
void loadMultiDocumentProperties() throws Exception {
|
void loadMultiDocumentProperties() throws Exception {
|
||||||
List<PropertySource<?>> loaded = this.loader.load("test.properties",
|
List<PropertySource<?>> loaded = this.loader.load("test.properties", new ClassPathResource("test.properties"));
|
||||||
new ClassPathResource("multi-document-properties.properties", getClass()));
|
|
||||||
assertThat(loaded).hasSize(2);
|
assertThat(loaded).hasSize(2);
|
||||||
PropertySource<?> source1 = loaded.get(0);
|
PropertySource<?> source1 = loaded.get(0);
|
||||||
PropertySource<?> source2 = loaded.get(1);
|
PropertySource<?> source2 = loaded.get(1);
|
||||||
@ -71,9 +94,22 @@ class PropertiesPropertySourceLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "test.properties", content = """
|
||||||
|
|
||||||
|
#---
|
||||||
|
#test
|
||||||
|
blah=hello world
|
||||||
|
bar=baz
|
||||||
|
hello=world
|
||||||
|
#---
|
||||||
|
#---
|
||||||
|
foo=bar
|
||||||
|
bling=biz
|
||||||
|
#comment1
|
||||||
|
#comment2
|
||||||
|
""")
|
||||||
void loadMultiDocumentPropertiesWithEmptyDocument() throws Exception {
|
void loadMultiDocumentPropertiesWithEmptyDocument() throws Exception {
|
||||||
List<PropertySource<?>> loaded = this.loader.load("test.properties",
|
List<PropertySource<?>> loaded = this.loader.load("test.properties", new ClassPathResource("test.properties"));
|
||||||
new ClassPathResource("multi-document-properties-empty.properties", getClass()));
|
|
||||||
assertThat(loaded).hasSize(2);
|
assertThat(loaded).hasSize(2);
|
||||||
PropertySource<?> source1 = loaded.get(0);
|
PropertySource<?> source1 = loaded.get(0);
|
||||||
PropertySource<?> source2 = loaded.get(1);
|
PropertySource<?> source2 = loaded.get(1);
|
||||||
@ -82,9 +118,15 @@ class PropertiesPropertySourceLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "test.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
|
||||||
|
<properties>
|
||||||
|
<entry key="test">xml</entry>
|
||||||
|
</properties>
|
||||||
|
""")
|
||||||
void loadXml() throws Exception {
|
void loadXml() throws Exception {
|
||||||
List<PropertySource<?>> loaded = this.loader.load("test.xml",
|
List<PropertySource<?>> loaded = this.loader.load("test.xml", new ClassPathResource("test.xml"));
|
||||||
new ClassPathResource("test-xml.xml", getClass()));
|
|
||||||
PropertySource<?> source = loaded.get(0);
|
PropertySource<?> source = loaded.get(0);
|
||||||
assertThat(source.getProperty("test")).isEqualTo("xml");
|
assertThat(source.getProperty("test")).isEqualTo("xml");
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -21,6 +21,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.core.env.EnumerablePropertySource;
|
import org.springframework.core.env.EnumerablePropertySource;
|
||||||
import org.springframework.core.env.PropertySource;
|
import org.springframework.core.env.PropertySource;
|
||||||
import org.springframework.core.io.ByteArrayResource;
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
@ -86,8 +87,14 @@ class YamlPropertySourceLoaderTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "test-yaml.yml", content = """
|
||||||
|
a: b
|
||||||
|
---
|
||||||
|
c: d
|
||||||
|
e: f
|
||||||
|
""")
|
||||||
void loadOriginAware() throws Exception {
|
void loadOriginAware() throws Exception {
|
||||||
Resource resource = new ClassPathResource("test-yaml.yml", getClass());
|
Resource resource = new ClassPathResource("test-yaml.yml");
|
||||||
List<PropertySource<?>> loaded = this.loader.load("resource", resource);
|
List<PropertySource<?>> loaded = this.loader.load("resource", resource);
|
||||||
for (PropertySource<?> source : loaded) {
|
for (PropertySource<?> source : loaded) {
|
||||||
EnumerablePropertySource<?> enumerableSource = (EnumerablePropertySource<?>) source;
|
EnumerablePropertySource<?> enumerableSource = (EnumerablePropertySource<?>) source;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -70,6 +70,7 @@ class DataSourceScriptDatabaseInitializerTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithDataSqlResource
|
||||||
void whenCustomizeIsOverriddenThenDatabasePopulatorIsConfiguredAccordingly() {
|
void whenCustomizeIsOverriddenThenDatabasePopulatorIsConfiguredAccordingly() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setContinueOnError(true);
|
settings.setContinueOnError(true);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,15 +16,14 @@
|
|||||||
|
|
||||||
package org.springframework.boot.json;
|
package org.springframework.boot.json;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.boot.testsupport.classpath.resources.ResourceContent;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
@ -192,26 +191,22 @@ abstract class AbstractJsonParserTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test // gh-31868
|
@Test // gh-31868
|
||||||
void listWithRepeatedOpenArray() throws IOException {
|
@WithPackageResources("repeated-open-array.txt")
|
||||||
String input = StreamUtils.copyToString(
|
void listWithRepeatedOpenArray(@ResourceContent("repeated-open-array.txt") String input) {
|
||||||
AbstractJsonParserTests.class.getResourceAsStream("repeated-open-array.txt"), StandardCharsets.UTF_8);
|
|
||||||
assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input))
|
assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input))
|
||||||
.havingCause()
|
.havingCause()
|
||||||
.withMessageContaining("too deeply nested");
|
.withMessageContaining("too deeply nested");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // gh-31869
|
@Test // gh-31869
|
||||||
void largeMalformed() throws IOException {
|
@WithPackageResources("large-malformed-json.txt")
|
||||||
String input = StreamUtils.copyToString(
|
void largeMalformed(@ResourceContent("large-malformed-json.txt") String input) {
|
||||||
AbstractJsonParserTests.class.getResourceAsStream("large-malformed-json.txt"), StandardCharsets.UTF_8);
|
|
||||||
assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input));
|
assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test // gh-32029
|
@Test // gh-32029
|
||||||
void deeplyNestedMap() throws IOException {
|
@WithPackageResources("deeply-nested-map-json.txt")
|
||||||
String input = StreamUtils.copyToString(
|
void deeplyNestedMap(@ResourceContent("deeply-nested-map-json.txt") String input) {
|
||||||
AbstractJsonParserTests.class.getResourceAsStream("deeply-nested-map-json.txt"),
|
|
||||||
StandardCharsets.UTF_8);
|
|
||||||
assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input));
|
assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2022 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.boot.json;
|
package org.springframework.boot.json;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests for {@link GsonJsonParser}.
|
* Tests for {@link GsonJsonParser}.
|
||||||
*
|
*
|
||||||
@ -31,7 +29,7 @@ class GsonJsonParserTests extends AbstractJsonParserTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void listWithRepeatedOpenArray() throws IOException {
|
void listWithRepeatedOpenArray(String input) {
|
||||||
// Gson does not protect against deeply nested JSON
|
// Gson does not protect against deeply nested JSON
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2022 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -52,7 +52,7 @@ class JacksonJsonParserTests extends AbstractJsonParserTests {
|
|||||||
@Override
|
@Override
|
||||||
@Disabled("Jackson's array handling is no longer stack bound so protection has been removed.")
|
@Disabled("Jackson's array handling is no longer stack bound so protection has been removed.")
|
||||||
// https://github.com/FasterXML/jackson-databind/commit/8238ab41d0350fb915797c89d46777b4496b74fd
|
// https://github.com/FasterXML/jackson-databind/commit/8238ab41d0350fb915797c89d46777b4496b74fd
|
||||||
void listWithRepeatedOpenArray() throws IOException {
|
void listWithRepeatedOpenArray(String input) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -34,6 +34,7 @@ import org.springframework.boot.logging.LogLevel;
|
|||||||
import org.springframework.boot.logging.LoggerConfiguration;
|
import org.springframework.boot.logging.LoggerConfiguration;
|
||||||
import org.springframework.boot.logging.LoggingSystem;
|
import org.springframework.boot.logging.LoggingSystem;
|
||||||
import org.springframework.boot.logging.LoggingSystemProperty;
|
import org.springframework.boot.logging.LoggingSystemProperty;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
@ -123,6 +124,10 @@ class JavaLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "logging-nondefault.properties", content = """
|
||||||
|
handlers = java.util.logging.ConsoleHandler
|
||||||
|
.level = INFO
|
||||||
|
""")
|
||||||
void testNonDefaultConfigLocation(CapturedOutput output) {
|
void testNonDefaultConfigLocation(CapturedOutput output) {
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
this.loggingSystem.initialize(null, "classpath:logging-nondefault.properties", null);
|
this.loggingSystem.initialize(null, "classpath:logging-nondefault.properties", null);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -19,6 +19,10 @@ package org.springframework.boot.logging.log4j2;
|
|||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
@ -59,6 +63,7 @@ import org.springframework.boot.logging.LoggingSystem;
|
|||||||
import org.springframework.boot.logging.LoggingSystemProperties;
|
import org.springframework.boot.logging.LoggingSystemProperties;
|
||||||
import org.springframework.boot.logging.LoggingSystemProperty;
|
import org.springframework.boot.logging.LoggingSystemProperty;
|
||||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.logging.ConfigureClasspathToPreferLog4j2;
|
import org.springframework.boot.testsupport.logging.ConfigureClasspathToPreferLog4j2;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
@ -158,16 +163,16 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
void testNonDefaultConfigLocation(CapturedOutput output) {
|
void testNonDefaultConfigLocation(CapturedOutput output) {
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
this.loggingSystem.initialize(this.initializationContext, "classpath:log4j2-nondefault.xml",
|
this.loggingSystem.initialize(this.initializationContext, "classpath:nondefault.xml",
|
||||||
getLogFile(tmpDir() + "/tmp.log", null));
|
getLogFile(tmpDir() + "/tmp.log", null));
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
Configuration configuration = this.loggingSystem.getConfiguration();
|
Configuration configuration = this.loggingSystem.getConfiguration();
|
||||||
assertThat(output).contains("Hello world").contains(tmpDir() + "/tmp.log");
|
assertThat(output).contains("Hello world").contains(tmpDir() + "/tmp.log");
|
||||||
assertThat(new File(tmpDir() + "/tmp.log")).doesNotExist();
|
assertThat(new File(tmpDir() + "/tmp.log")).doesNotExist();
|
||||||
assertThat(configuration.getConfigurationSource().getFile().getAbsolutePath())
|
assertThat(configuration.getConfigurationSource().getFile().getAbsolutePath()).contains("nondefault.xml");
|
||||||
.contains("log4j2-nondefault.xml");
|
|
||||||
assertThat(configuration.getWatchManager().getIntervalSeconds()).isEqualTo(30);
|
assertThat(configuration.getWatchManager().getIntervalSeconds()).isEqualTo(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,15 +466,18 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
|
@WithOverrideXmlResource
|
||||||
void compositeConfigurationWithCustomBaseConfiguration() {
|
void compositeConfigurationWithCustomBaseConfiguration() {
|
||||||
this.environment.setProperty("logging.log4j2.config.override", "src/test/resources/log4j2-override.xml");
|
this.environment.setProperty("logging.log4j2.config.override", "classpath:override.xml");
|
||||||
this.loggingSystem.initialize(this.initializationContext, "src/test/resources/log4j2-nondefault.xml", null);
|
this.loggingSystem.initialize(this.initializationContext, "classpath:nondefault.xml", null);
|
||||||
assertThat(this.loggingSystem.getConfiguration()).isInstanceOf(CompositeConfiguration.class);
|
assertThat(this.loggingSystem.getConfiguration()).isInstanceOf(CompositeConfiguration.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithOverrideXmlResource
|
||||||
void compositeConfigurationWithStandardConfigLocationConfiguration() {
|
void compositeConfigurationWithStandardConfigLocationConfiguration() {
|
||||||
this.environment.setProperty("logging.log4j2.config.override", "src/test/resources/log4j2-override.xml");
|
this.environment.setProperty("logging.log4j2.config.override", "classpath:override.xml");
|
||||||
this.loggingSystem.initialize(this.initializationContext, null, null);
|
this.loggingSystem.initialize(this.initializationContext, null, null);
|
||||||
assertThat(this.loggingSystem.getConfiguration()).isInstanceOf(CompositeConfiguration.class);
|
assertThat(this.loggingSystem.getConfiguration()).isInstanceOf(CompositeConfiguration.class);
|
||||||
}
|
}
|
||||||
@ -678,4 +686,45 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "nondefault.xml",
|
||||||
|
content = """
|
||||||
|
<Configuration status="WARN" monitorInterval="30">
|
||||||
|
<Properties>
|
||||||
|
<Property name="PID">????</Property>
|
||||||
|
<Property name="LOG_PATTERN">${sys:LOG_FILE} %d{yyyy-MM-dd HH:mm:ss.SSS}] service%X{context} - ${sys:PID} %5p [%t] --- %c{1}: %m%n</Property>
|
||||||
|
</Properties>
|
||||||
|
<Appenders>
|
||||||
|
<Console name="Console" target="SYSTEM_OUT" follow="true">
|
||||||
|
<PatternLayout pattern="${LOG_PATTERN}"/>
|
||||||
|
</Console>
|
||||||
|
</Appenders>
|
||||||
|
<Loggers>
|
||||||
|
<Root level="info">
|
||||||
|
<AppenderRef ref="Console"/>
|
||||||
|
</Root>
|
||||||
|
</Loggers>
|
||||||
|
</Configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithNonDefaultXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "override.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration status="WARN" monitorInterval="30">
|
||||||
|
<Appenders>
|
||||||
|
<Console name="Console" target="SYSTEM_OUT" follow="true">
|
||||||
|
<PatternLayout pattern="${LOG_PATTERN}"/>
|
||||||
|
</Console>
|
||||||
|
</Appenders>
|
||||||
|
</Configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithOverrideXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2022 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package org.springframework.boot.logging.log4j2;
|
package org.springframework.boot.logging.log4j2;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
@ -32,12 +36,12 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
|||||||
|
|
||||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.logging.ConfigureClasspathToPreferLog4j2;
|
import org.springframework.boot.testsupport.logging.ConfigureClasspathToPreferLog4j2;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
import org.springframework.mock.env.MockEnvironment;
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@ -93,6 +97,7 @@ class SpringProfileArbiterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProductionProfileXmlResource
|
||||||
void profileActive() {
|
void profileActive() {
|
||||||
this.environment.setActiveProfiles("production");
|
this.environment.setActiveProfiles("production");
|
||||||
initialize("production-profile.xml");
|
initialize("production-profile.xml");
|
||||||
@ -101,6 +106,7 @@ class SpringProfileArbiterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithMultiProfileNamesXmlResource
|
||||||
void multipleNamesFirstProfileActive() {
|
void multipleNamesFirstProfileActive() {
|
||||||
this.environment.setActiveProfiles("production");
|
this.environment.setActiveProfiles("production");
|
||||||
initialize("multi-profile-names.xml");
|
initialize("multi-profile-names.xml");
|
||||||
@ -109,6 +115,7 @@ class SpringProfileArbiterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithMultiProfileNamesXmlResource
|
||||||
void multipleNamesSecondProfileActive() {
|
void multipleNamesSecondProfileActive() {
|
||||||
this.environment.setActiveProfiles("test");
|
this.environment.setActiveProfiles("test");
|
||||||
initialize("multi-profile-names.xml");
|
initialize("multi-profile-names.xml");
|
||||||
@ -117,6 +124,7 @@ class SpringProfileArbiterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProductionProfileXmlResource
|
||||||
void profileNotActive() {
|
void profileNotActive() {
|
||||||
initialize("production-profile.xml");
|
initialize("production-profile.xml");
|
||||||
this.logger.trace("Hello");
|
this.logger.trace("Hello");
|
||||||
@ -124,6 +132,7 @@ class SpringProfileArbiterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProfileExpressionXmlResource
|
||||||
void profileExpressionMatchFirst() {
|
void profileExpressionMatchFirst() {
|
||||||
this.environment.setActiveProfiles("production");
|
this.environment.setActiveProfiles("production");
|
||||||
initialize("profile-expression.xml");
|
initialize("profile-expression.xml");
|
||||||
@ -132,6 +141,7 @@ class SpringProfileArbiterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProfileExpressionXmlResource
|
||||||
void profileExpressionMatchSecond() {
|
void profileExpressionMatchSecond() {
|
||||||
this.environment.setActiveProfiles("test");
|
this.environment.setActiveProfiles("test");
|
||||||
initialize("profile-expression.xml");
|
initialize("profile-expression.xml");
|
||||||
@ -140,6 +150,7 @@ class SpringProfileArbiterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProfileExpressionXmlResource
|
||||||
void profileExpressionNoMatch() {
|
void profileExpressionNoMatch() {
|
||||||
this.environment.setActiveProfiles("development");
|
this.environment.setActiveProfiles("development");
|
||||||
initialize("profile-expression.xml");
|
initialize("profile-expression.xml");
|
||||||
@ -148,13 +159,56 @@ class SpringProfileArbiterTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initialize(String config) {
|
private void initialize(String config) {
|
||||||
this.environment.setProperty("logging.log4j2.config.override", getPackageResource(config));
|
this.environment.setProperty("logging.log4j2.config.override", "classpath:" + config);
|
||||||
this.loggingSystem.initialize(this.initializationContext, null, null);
|
this.loggingSystem.initialize(this.initializationContext, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPackageResource(String fileName) {
|
@Target(ElementType.METHOD)
|
||||||
String path = ClassUtils.getPackageName(getClass());
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
return "src/test/resources/" + path.replace('.', '/') + "/" + fileName;
|
@WithResource(name = "multi-profile-names.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration>
|
||||||
|
<SpringProfile name="production, test">
|
||||||
|
<Loggers>
|
||||||
|
<Logger name="org.springframework.boot.logging.log4j2" level="TRACE" />
|
||||||
|
</Loggers>
|
||||||
|
</SpringProfile>
|
||||||
|
</Configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithMultiProfileNamesXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "profile-expression.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration>
|
||||||
|
<SpringProfile name="production | test">
|
||||||
|
<Loggers>
|
||||||
|
<Logger name="org.springframework.boot.logging.log4j2" level="TRACE" />
|
||||||
|
</Loggers>
|
||||||
|
</SpringProfile>
|
||||||
|
</Configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithProfileExpressionXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "production-profile.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Configuration>
|
||||||
|
<SpringProfile name="production">
|
||||||
|
<Loggers>
|
||||||
|
<Logger name="org.springframework.boot.logging.log4j2" level="TRACE" />
|
||||||
|
</Loggers>
|
||||||
|
</SpringProfile>
|
||||||
|
</Configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithProductionProfileXmlResource {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2020 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -32,6 +32,9 @@ import ch.qos.logback.core.rolling.RollingPolicy;
|
|||||||
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
|
import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.ResourcesRoot;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,11 +46,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
class LogbackConfigurationTests {
|
class LogbackConfigurationTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void consolePatternCanBeOverridden() throws JoranException {
|
@WithResource(name = "custom-console-log-pattern.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<property name="CONSOLE_LOG_PATTERN" value="foo" />
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
void consolePatternCanBeOverridden(@ResourcesRoot File resourcesRoot) throws JoranException {
|
||||||
JoranConfigurator configurator = new JoranConfigurator();
|
JoranConfigurator configurator = new JoranConfigurator();
|
||||||
LoggerContext context = new LoggerContext();
|
LoggerContext context = new LoggerContext();
|
||||||
configurator.setContext(context);
|
configurator.setContext(context);
|
||||||
configurator.doConfigure(new File("src/test/resources/custom-console-log-pattern.xml"));
|
configurator.doConfigure(new File(resourcesRoot, "custom-console-log-pattern.xml"));
|
||||||
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("CONSOLE");
|
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("CONSOLE");
|
||||||
assertThat(appender).isInstanceOf(ConsoleAppender.class);
|
assertThat(appender).isInstanceOf(ConsoleAppender.class);
|
||||||
Encoder<?> encoder = ((ConsoleAppender<?>) appender).getEncoder();
|
Encoder<?> encoder = ((ConsoleAppender<?>) appender).getEncoder();
|
||||||
@ -56,11 +65,17 @@ class LogbackConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void filePatternCanBeOverridden() throws JoranException {
|
@WithResource(name = "custom-file-log-pattern.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<property name="FILE_LOG_PATTERN" value="bar" />
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
void filePatternCanBeOverridden(@ResourcesRoot File resourcesRoot) throws JoranException {
|
||||||
JoranConfigurator configurator = new JoranConfigurator();
|
JoranConfigurator configurator = new JoranConfigurator();
|
||||||
LoggerContext context = new LoggerContext();
|
LoggerContext context = new LoggerContext();
|
||||||
configurator.setContext(context);
|
configurator.setContext(context);
|
||||||
configurator.doConfigure(new File("src/test/resources/custom-file-log-pattern.xml"));
|
configurator.doConfigure(new File(resourcesRoot, "custom-file-log-pattern.xml"));
|
||||||
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("FILE");
|
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("FILE");
|
||||||
assertThat(appender).isInstanceOf(FileAppender.class);
|
assertThat(appender).isInstanceOf(FileAppender.class);
|
||||||
Encoder<?> encoder = ((FileAppender<?>) appender).getEncoder();
|
Encoder<?> encoder = ((FileAppender<?>) appender).getEncoder();
|
||||||
@ -69,11 +84,17 @@ class LogbackConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void defaultRollingFileNamePattern() throws JoranException {
|
@WithResource(name = "custom-file-log-pattern.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<property name="FILE_LOG_PATTERN" value="bar" />
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
void defaultRollingFileNamePattern(@ResourcesRoot File resourcesRoot) throws JoranException {
|
||||||
JoranConfigurator configurator = new JoranConfigurator();
|
JoranConfigurator configurator = new JoranConfigurator();
|
||||||
LoggerContext context = new LoggerContext();
|
LoggerContext context = new LoggerContext();
|
||||||
configurator.setContext(context);
|
configurator.setContext(context);
|
||||||
configurator.doConfigure(new File("src/test/resources/custom-file-log-pattern.xml"));
|
configurator.doConfigure(new File(resourcesRoot, "custom-file-log-pattern.xml"));
|
||||||
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("FILE");
|
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("FILE");
|
||||||
assertThat(appender).isInstanceOf(RollingFileAppender.class);
|
assertThat(appender).isInstanceOf(RollingFileAppender.class);
|
||||||
RollingPolicy rollingPolicy = ((RollingFileAppender<?>) appender).getRollingPolicy();
|
RollingPolicy rollingPolicy = ((RollingFileAppender<?>) appender).getRollingPolicy();
|
||||||
@ -82,11 +103,17 @@ class LogbackConfigurationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void customRollingFileNamePattern() throws JoranException {
|
@WithResource(name = "custom-file-log-pattern-with-fileNamePattern.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<property name="LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN" value="my.log.%d{yyyyMMdd}.%i.gz"/>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml" />
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
void customRollingFileNamePattern(@ResourcesRoot File resourcesRoot) throws JoranException {
|
||||||
JoranConfigurator configurator = new JoranConfigurator();
|
JoranConfigurator configurator = new JoranConfigurator();
|
||||||
LoggerContext context = new LoggerContext();
|
LoggerContext context = new LoggerContext();
|
||||||
configurator.setContext(context);
|
configurator.setContext(context);
|
||||||
configurator.doConfigure(new File("src/test/resources/custom-file-log-pattern-with-fileNamePattern.xml"));
|
configurator.doConfigure(new File(resourcesRoot, "custom-file-log-pattern-with-fileNamePattern.xml"));
|
||||||
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("FILE");
|
Appender<ILoggingEvent> appender = context.getLogger("ROOT").getAppender("FILE");
|
||||||
assertThat(appender).isInstanceOf(RollingFileAppender.class);
|
assertThat(appender).isInstanceOf(RollingFileAppender.class);
|
||||||
RollingPolicy rollingPolicy = ((RollingFileAppender<?>) appender).getRollingPolicy();
|
RollingPolicy rollingPolicy = ((RollingFileAppender<?>) appender).getRollingPolicy();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -17,6 +17,10 @@
|
|||||||
package org.springframework.boot.logging.logback;
|
package org.springframework.boot.logging.logback;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
@ -62,6 +66,7 @@ import org.springframework.boot.logging.LoggingSystemProperties;
|
|||||||
import org.springframework.boot.logging.LoggingSystemProperty;
|
import org.springframework.boot.logging.LoggingSystemProperty;
|
||||||
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||||
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
|
import org.springframework.boot.testsupport.classpath.ClassPathOverrides;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
@ -132,16 +137,30 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "include-defaults.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>[%p] - %m%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
void logbackDefaultsConfigurationDoesNotTriggerDeprecation(CapturedOutput output) {
|
void logbackDefaultsConfigurationDoesNotTriggerDeprecation(CapturedOutput output) {
|
||||||
initialize(this.initializationContext, "classpath:logback-include-defaults.xml", null);
|
initialize(this.initializationContext, "classpath:include-defaults.xml", null);
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(getLineWithText(output, "Hello world")).isEqualTo("[INFO] - Hello world");
|
assertThat(getLineWithText(output, "Hello world")).isEqualTo("[INFO] - Hello world");
|
||||||
assertThat(output.toString()).doesNotContain("WARN").doesNotContain("deprecated");
|
assertThat(output.toString()).doesNotContain("WARN").doesNotContain("deprecated");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithIncludeBaseXmlResource
|
||||||
void logbackBaseConfigurationDoesNotTriggerDeprecation(CapturedOutput output) {
|
void logbackBaseConfigurationDoesNotTriggerDeprecation(CapturedOutput output) {
|
||||||
initialize(this.initializationContext, "classpath:logback-include-base.xml", null);
|
initialize(this.initializationContext, "classpath:include-base.xml", null);
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(getLineWithText(output, "Hello world")).contains(" INFO ").endsWith(": Hello world");
|
assertThat(getLineWithText(output, "Hello world")).contains(" INFO ").endsWith(": Hello world");
|
||||||
assertThat(output.toString()).doesNotContain("WARN").doesNotContain("deprecated");
|
assertThat(output.toString()).doesNotContain("WARN").doesNotContain("deprecated");
|
||||||
@ -199,10 +218,10 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
void testNonDefaultConfigLocation(CapturedOutput output) {
|
void testNonDefaultConfigLocation(CapturedOutput output) {
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
initialize(this.initializationContext, "classpath:logback-nondefault.xml",
|
initialize(this.initializationContext, "classpath:nondefault.xml", getLogFile(tmpDir() + "/tmp.log", null));
|
||||||
getLogFile(tmpDir() + "/tmp.log", null));
|
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(output).doesNotContain("DEBUG")
|
assertThat(output).doesNotContain("DEBUG")
|
||||||
.contains("Hello world")
|
.contains("Hello world")
|
||||||
@ -406,12 +425,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithIncludeBaseXmlResource
|
||||||
void testCleanHistoryOnStartPropertyWithXmlConfiguration() {
|
void testCleanHistoryOnStartPropertyWithXmlConfiguration() {
|
||||||
this.environment.setProperty("logging.file.clean-history-on-start", "true");
|
this.environment.setProperty("logging.file.clean-history-on-start", "true");
|
||||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||||
File file = new File(tmpDir(), "logback-test.log");
|
File file = new File(tmpDir(), "logback-test.log");
|
||||||
LogFile logFile = getLogFile(file.getPath(), null);
|
LogFile logFile = getLogFile(file.getPath(), null);
|
||||||
initialize(loggingInitializationContext, "classpath:logback-include-base.xml", logFile);
|
initialize(loggingInitializationContext, "classpath:include-base.xml", logFile);
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
||||||
assertThat(getRollingPolicy().isCleanHistoryOnStart()).isTrue();
|
assertThat(getRollingPolicy().isCleanHistoryOnStart()).isTrue();
|
||||||
@ -444,12 +464,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithIncludeBaseXmlResource
|
||||||
void testMaxFileSizePropertyWithXmlConfiguration() {
|
void testMaxFileSizePropertyWithXmlConfiguration() {
|
||||||
this.environment.setProperty("logging.file.max-size", "100MB");
|
this.environment.setProperty("logging.file.max-size", "100MB");
|
||||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||||
File file = new File(tmpDir(), "logback-test.log");
|
File file = new File(tmpDir(), "logback-test.log");
|
||||||
LogFile logFile = getLogFile(file.getPath(), null);
|
LogFile logFile = getLogFile(file.getPath(), null);
|
||||||
initialize(loggingInitializationContext, "classpath:logback-include-base.xml", logFile);
|
initialize(loggingInitializationContext, "classpath:include-base.xml", logFile);
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
||||||
assertThat(ReflectionTestUtils.getField(getRollingPolicy(), "maxFileSize")).hasToString("100 MB");
|
assertThat(ReflectionTestUtils.getField(getRollingPolicy(), "maxFileSize")).hasToString("100 MB");
|
||||||
@ -468,12 +489,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithIncludeBaseXmlResource
|
||||||
void testMaxHistoryPropertyWithXmlConfiguration() {
|
void testMaxHistoryPropertyWithXmlConfiguration() {
|
||||||
this.environment.setProperty("logging.file.max-history", "30");
|
this.environment.setProperty("logging.file.max-history", "30");
|
||||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||||
File file = new File(tmpDir(), "logback-test.log");
|
File file = new File(tmpDir(), "logback-test.log");
|
||||||
LogFile logFile = getLogFile(file.getPath(), null);
|
LogFile logFile = getLogFile(file.getPath(), null);
|
||||||
initialize(loggingInitializationContext, "classpath:logback-include-base.xml", logFile);
|
initialize(loggingInitializationContext, "classpath:include-base.xml", logFile);
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
||||||
assertThat(getRollingPolicy().getMaxHistory()).isEqualTo(30);
|
assertThat(getRollingPolicy().getMaxHistory()).isEqualTo(30);
|
||||||
@ -506,13 +528,14 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithIncludeBaseXmlResource
|
||||||
void testTotalSizeCapPropertyWithXmlConfiguration() {
|
void testTotalSizeCapPropertyWithXmlConfiguration() {
|
||||||
String expectedSize = "101 MB";
|
String expectedSize = "101 MB";
|
||||||
this.environment.setProperty("logging.file.total-size-cap", expectedSize);
|
this.environment.setProperty("logging.file.total-size-cap", expectedSize);
|
||||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||||
File file = new File(tmpDir(), "logback-test.log");
|
File file = new File(tmpDir(), "logback-test.log");
|
||||||
LogFile logFile = getLogFile(file.getPath(), null);
|
LogFile logFile = getLogFile(file.getPath(), null);
|
||||||
initialize(loggingInitializationContext, "classpath:logback-include-base.xml", logFile);
|
initialize(loggingInitializationContext, "classpath:include-base.xml", logFile);
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
||||||
assertThat(ReflectionTestUtils.getField(getRollingPolicy(), "totalSizeCap")).hasToString(expectedSize);
|
assertThat(ReflectionTestUtils.getField(getRollingPolicy(), "totalSizeCap")).hasToString(expectedSize);
|
||||||
@ -546,12 +569,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
void initializeShouldSetSystemProperty() {
|
void initializeShouldSetSystemProperty() {
|
||||||
// gh-5491
|
// gh-5491
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
this.logger.info("Hidden");
|
this.logger.info("Hidden");
|
||||||
LogFile logFile = getLogFile(tmpDir() + "/example.log", null, false);
|
LogFile logFile = getLogFile(tmpDir() + "/example.log", null, false);
|
||||||
initialize(this.initializationContext, "classpath:logback-nondefault.xml", logFile);
|
initialize(this.initializationContext, "classpath:nondefault.xml", logFile);
|
||||||
assertThat(System.getProperty(LoggingSystemProperty.LOG_FILE.getEnvironmentVariableName()))
|
assertThat(System.getProperty(LoggingSystemProperty.LOG_FILE.getEnvironmentVariableName()))
|
||||||
.endsWith("example.log");
|
.endsWith("example.log");
|
||||||
}
|
}
|
||||||
@ -698,9 +722,23 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test // gh-33610
|
@Test // gh-33610
|
||||||
|
@WithResource(name = "springprofile-in-root.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%property{LOG_FILE} [%t] ${PID:-????} %c{1}: %m%n BOOTBOOT</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="INFO">
|
||||||
|
<springProfile name="profile">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</springProfile>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
void springProfileIfNestedWithinSecondPhaseElementSanityChecker(CapturedOutput output) {
|
void springProfileIfNestedWithinSecondPhaseElementSanityChecker(CapturedOutput output) {
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
initialize(this.initializationContext, "classpath:logback-springprofile-in-root.xml", null);
|
initialize(this.initializationContext, "classpath:springprofile-in-root.xml", null);
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(output).contains("<springProfile> elements cannot be nested within an");
|
assertThat(output).contains("<springProfile> elements cannot be nested within an");
|
||||||
}
|
}
|
||||||
@ -756,9 +794,10 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithIncludeBaseXmlResource
|
||||||
void correlationLoggingToConsoleWhenUsingXmlConfiguration(CapturedOutput output) {
|
void correlationLoggingToConsoleWhenUsingXmlConfiguration(CapturedOutput output) {
|
||||||
this.environment.setProperty(LoggingSystem.EXPECT_CORRELATION_ID_PROPERTY, "true");
|
this.environment.setProperty(LoggingSystem.EXPECT_CORRELATION_ID_PROPERTY, "true");
|
||||||
initialize(this.initializationContext, "classpath:logback-include-base.xml", null);
|
initialize(this.initializationContext, "classpath:include-base.xml", null);
|
||||||
MDC.setContextMap(Map.of("traceId", "01234567890123456789012345678901", "spanId", "0123456789012345"));
|
MDC.setContextMap(Map.of("traceId", "01234567890123456789012345678901", "spanId", "0123456789012345"));
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(getLineWithText(output, "Hello world"))
|
assertThat(getLineWithText(output, "Hello world"))
|
||||||
@ -766,11 +805,12 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithIncludeBaseXmlResource
|
||||||
void correlationLoggingToFileWhenUsingFileConfiguration() {
|
void correlationLoggingToFileWhenUsingFileConfiguration() {
|
||||||
this.environment.setProperty(LoggingSystem.EXPECT_CORRELATION_ID_PROPERTY, "true");
|
this.environment.setProperty(LoggingSystem.EXPECT_CORRELATION_ID_PROPERTY, "true");
|
||||||
File file = new File(tmpDir(), "logback-test.log");
|
File file = new File(tmpDir(), "logback-test.log");
|
||||||
LogFile logFile = getLogFile(file.getPath(), null);
|
LogFile logFile = getLogFile(file.getPath(), null);
|
||||||
initialize(this.initializationContext, "classpath:logback-include-base.xml", logFile);
|
initialize(this.initializationContext, "classpath:include-base.xml", logFile);
|
||||||
MDC.setContextMap(Map.of("traceId", "01234567890123456789012345678901", "spanId", "0123456789012345"));
|
MDC.setContextMap(Map.of("traceId", "01234567890123456789012345678901", "spanId", "0123456789012345"));
|
||||||
this.logger.info("Hello world");
|
this.logger.info("Hello world");
|
||||||
assertThat(getLineWithText(file, "Hello world"))
|
assertThat(getLineWithText(file, "Hello world"))
|
||||||
@ -834,30 +874,55 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "broken.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsolAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>${LOG_FILE} [%t] ${PID:-????} %c{1}: %m%n BOOTBOOT</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
void whenConfigurationErrorIsDetectedUnderlyingCausesAreIncludedAsSuppressedExceptions() {
|
void whenConfigurationErrorIsDetectedUnderlyingCausesAreIncludedAsSuppressedExceptions() {
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(() -> initialize(this.initializationContext, "classpath:logback-broken.xml",
|
.isThrownBy(() -> initialize(this.initializationContext, "classpath:broken.xml",
|
||||||
getLogFile(tmpDir() + "/tmp.log", null)))
|
getLogFile(tmpDir() + "/tmp.log", null)))
|
||||||
.satisfies((ex) -> assertThat(ex.getSuppressed())
|
.satisfies((ex) -> assertThat(ex.getSuppressed())
|
||||||
.hasAtLeastOneElementOfType(DynamicClassLoadingException.class));
|
.hasAtLeastOneElementOfType(DynamicClassLoadingException.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "invalid-format.txt", content = "Not XML")
|
||||||
void whenConfigLocationIsNotXmlThenIllegalArgumentExceptionShouldBeThrown() {
|
void whenConfigLocationIsNotXmlThenIllegalArgumentExceptionShouldBeThrown() {
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(() -> initialize(this.initializationContext, "classpath:logback-invalid-format.txt",
|
.isThrownBy(() -> initialize(this.initializationContext, "classpath:invalid-format.txt",
|
||||||
getLogFile(tmpDir() + "/tmp.log", null)))
|
getLogFile(tmpDir() + "/tmp.log", null)))
|
||||||
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(JoranException.class)
|
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(JoranException.class)
|
||||||
.hasMessageStartingWith("Problem parsing XML document. See previously reported errors"));
|
.hasMessageStartingWith("Problem parsing XML document. See previously reported errors"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "without-extension", content = """
|
||||||
|
<configuration>
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%msg</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
void whenConfigLocationIsXmlFileWithoutExtensionShouldWork(CapturedOutput output) {
|
void whenConfigLocationIsXmlFileWithoutExtensionShouldWork(CapturedOutput output) {
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
initialize(this.initializationContext, "classpath:logback-without-extension",
|
initialize(this.initializationContext, "classpath:without-extension", getLogFile(tmpDir() + "/tmp.log", null));
|
||||||
getLogFile(tmpDir() + "/tmp.log", null));
|
|
||||||
this.logger.info("No extension and works!");
|
this.logger.info("No extension and works!");
|
||||||
assertThat(output.toString()).contains("No extension and works!");
|
assertThat(output.toString()).contains("No extension and works!");
|
||||||
}
|
}
|
||||||
@ -895,11 +960,12 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNonDefaultXmlResource
|
||||||
void applyingSystemPropertiesDoesNotCauseUnwantedStatusWarnings(CapturedOutput output) {
|
void applyingSystemPropertiesDoesNotCauseUnwantedStatusWarnings(CapturedOutput output) {
|
||||||
this.loggingSystem.beforeInitialize();
|
this.loggingSystem.beforeInitialize();
|
||||||
this.environment.getPropertySources()
|
this.environment.getPropertySources()
|
||||||
.addFirst(new MapPropertySource("test", Map.of("logging.pattern.console", "[CONSOLE]%m")));
|
.addFirst(new MapPropertySource("test", Map.of("logging.pattern.console", "[CONSOLE]%m")));
|
||||||
this.loggingSystem.initialize(this.initializationContext, "classpath:logback-nondefault.xml", null);
|
this.loggingSystem.initialize(this.initializationContext, "classpath:nondefault.xml", null);
|
||||||
assertThat(output).doesNotContain("WARN");
|
assertThat(output).doesNotContain("WARN");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -935,4 +1001,33 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
|||||||
return (SizeAndTimeBasedRollingPolicy<?>) getFileAppender().getRollingPolicy();
|
return (SizeAndTimeBasedRollingPolicy<?>) getFileAppender().getRollingPolicy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "include-base.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithIncludeBaseXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "nondefault.xml", content = """
|
||||||
|
<configuration>
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%property{LOG_FILE} [%t] ${PID:-????} %c{1}: %m%n BOOTBOOT</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="CONSOLE"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithNonDefaultXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,6 +16,11 @@
|
|||||||
|
|
||||||
package org.springframework.boot.logging.logback;
|
package org.springframework.boot.logging.logback;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import ch.qos.logback.classic.BasicConfigurator;
|
import ch.qos.logback.classic.BasicConfigurator;
|
||||||
import ch.qos.logback.classic.LoggerContext;
|
import ch.qos.logback.classic.LoggerContext;
|
||||||
import ch.qos.logback.classic.joran.JoranConfigurator;
|
import ch.qos.logback.classic.joran.JoranConfigurator;
|
||||||
@ -30,6 +35,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
|
import org.springframework.beans.factory.aot.BeanFactoryInitializationAotContribution;
|
||||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||||
import org.springframework.boot.logging.LoggingInitializationContext;
|
import org.springframework.boot.logging.LoggingInitializationContext;
|
||||||
|
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
import org.springframework.mock.env.MockEnvironment;
|
import org.springframework.mock.env.MockEnvironment;
|
||||||
@ -77,6 +84,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProductionProfileXmlResource
|
||||||
void profileActive() throws Exception {
|
void profileActive() throws Exception {
|
||||||
this.environment.setActiveProfiles("production");
|
this.environment.setActiveProfiles("production");
|
||||||
initialize("production-profile.xml");
|
initialize("production-profile.xml");
|
||||||
@ -85,6 +93,20 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "profile-in-include.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<include file="${resourceRoot}/include-with-profile.xml"/>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
@WithResource(name = "include-with-profile.xml", content = """
|
||||||
|
<included>
|
||||||
|
<springProfile name="production">
|
||||||
|
<logger name="org.springframework.boot.logging.logback" level="TRACE"/>
|
||||||
|
</springProfile>
|
||||||
|
</included>
|
||||||
|
""")
|
||||||
void profileInIncludeActive() throws Exception {
|
void profileInIncludeActive() throws Exception {
|
||||||
this.environment.setActiveProfiles("production");
|
this.environment.setActiveProfiles("production");
|
||||||
initialize("profile-in-include.xml");
|
initialize("profile-in-include.xml");
|
||||||
@ -93,6 +115,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithMultiProfileNamesXmlResource
|
||||||
void multipleNamesFirstProfileActive() throws Exception {
|
void multipleNamesFirstProfileActive() throws Exception {
|
||||||
this.environment.setActiveProfiles("production");
|
this.environment.setActiveProfiles("production");
|
||||||
initialize("multi-profile-names.xml");
|
initialize("multi-profile-names.xml");
|
||||||
@ -101,6 +124,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithMultiProfileNamesXmlResource
|
||||||
void multipleNamesSecondProfileActive() throws Exception {
|
void multipleNamesSecondProfileActive() throws Exception {
|
||||||
this.environment.setActiveProfiles("test");
|
this.environment.setActiveProfiles("test");
|
||||||
initialize("multi-profile-names.xml");
|
initialize("multi-profile-names.xml");
|
||||||
@ -109,6 +133,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProductionProfileXmlResource
|
||||||
void profileNotActive() throws Exception {
|
void profileNotActive() throws Exception {
|
||||||
initialize("production-profile.xml");
|
initialize("production-profile.xml");
|
||||||
this.logger.trace("Hello");
|
this.logger.trace("Hello");
|
||||||
@ -116,6 +141,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProfileExpressionXmlResource
|
||||||
void profileExpressionMatchFirst() throws Exception {
|
void profileExpressionMatchFirst() throws Exception {
|
||||||
this.environment.setActiveProfiles("production");
|
this.environment.setActiveProfiles("production");
|
||||||
initialize("profile-expression.xml");
|
initialize("profile-expression.xml");
|
||||||
@ -124,6 +150,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProfileExpressionXmlResource
|
||||||
void profileExpressionMatchSecond() throws Exception {
|
void profileExpressionMatchSecond() throws Exception {
|
||||||
this.environment.setActiveProfiles("test");
|
this.environment.setActiveProfiles("test");
|
||||||
initialize("profile-expression.xml");
|
initialize("profile-expression.xml");
|
||||||
@ -132,6 +159,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithProfileExpressionXmlResource
|
||||||
void profileExpressionNoMatch() throws Exception {
|
void profileExpressionNoMatch() throws Exception {
|
||||||
this.environment.setActiveProfiles("development");
|
this.environment.setActiveProfiles("development");
|
||||||
initialize("profile-expression.xml");
|
initialize("profile-expression.xml");
|
||||||
@ -140,26 +168,31 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNestedXmlResource
|
||||||
void profileNestedActiveActive() throws Exception {
|
void profileNestedActiveActive() throws Exception {
|
||||||
doTestNestedProfile(true, "outer", "inner");
|
doTestNestedProfile(true, "outer", "inner");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNestedXmlResource
|
||||||
void profileNestedActiveNotActive() throws Exception {
|
void profileNestedActiveNotActive() throws Exception {
|
||||||
doTestNestedProfile(false, "outer");
|
doTestNestedProfile(false, "outer");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNestedXmlResource
|
||||||
void profileNestedNotActiveActive() throws Exception {
|
void profileNestedNotActiveActive() throws Exception {
|
||||||
doTestNestedProfile(false, "inner");
|
doTestNestedProfile(false, "inner");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithNestedXmlResource
|
||||||
void profileNestedNotActiveNotActive() throws Exception {
|
void profileNestedNotActiveNotActive() throws Exception {
|
||||||
doTestNestedProfile(false);
|
doTestNestedProfile(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyXmlResource
|
||||||
void springProperty() throws Exception {
|
void springProperty() throws Exception {
|
||||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=test");
|
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=test");
|
||||||
initialize("property.xml");
|
initialize("property.xml");
|
||||||
@ -167,6 +200,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyXmlResource
|
||||||
void relaxedSpringProperty() throws Exception {
|
void relaxedSpringProperty() throws Exception {
|
||||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.EXAMPLE_PROPERTY=test");
|
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.EXAMPLE_PROPERTY=test");
|
||||||
ConfigurationPropertySources.attach(this.environment);
|
ConfigurationPropertySources.attach(this.environment);
|
||||||
@ -175,30 +209,35 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyXmlResource
|
||||||
void springPropertyNoValue() throws Exception {
|
void springPropertyNoValue() throws Exception {
|
||||||
initialize("property.xml");
|
initialize("property.xml");
|
||||||
assertThat(this.context.getProperty("SIMPLE")).isNull();
|
assertThat(this.context.getProperty("SIMPLE")).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyXmlResource
|
||||||
void relaxedSpringPropertyNoValue() throws Exception {
|
void relaxedSpringPropertyNoValue() throws Exception {
|
||||||
initialize("property.xml");
|
initialize("property.xml");
|
||||||
assertThat(this.context.getProperty("MINE")).isNull();
|
assertThat(this.context.getProperty("MINE")).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyDefaultValueXmlResource
|
||||||
void springPropertyWithDefaultValue() throws Exception {
|
void springPropertyWithDefaultValue() throws Exception {
|
||||||
initialize("property-default-value.xml");
|
initialize("property-default-value.xml");
|
||||||
assertThat(this.context.getProperty("SIMPLE")).isEqualTo("foo");
|
assertThat(this.context.getProperty("SIMPLE")).isEqualTo("foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyDefaultValueXmlResource
|
||||||
void relaxedSpringPropertyWithDefaultValue() throws Exception {
|
void relaxedSpringPropertyWithDefaultValue() throws Exception {
|
||||||
initialize("property-default-value.xml");
|
initialize("property-default-value.xml");
|
||||||
assertThat(this.context.getProperty("MINE")).isEqualTo("bar");
|
assertThat(this.context.getProperty("MINE")).isEqualTo("bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyInIfXmlResource
|
||||||
void springPropertyInIfWhenTrue() throws Exception {
|
void springPropertyInIfWhenTrue() throws Exception {
|
||||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=true");
|
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=true");
|
||||||
initialize("property-in-if.xml");
|
initialize("property-in-if.xml");
|
||||||
@ -206,6 +245,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyInIfXmlResource
|
||||||
void springPropertyInIfWhenFalse() throws Exception {
|
void springPropertyInIfWhenFalse() throws Exception {
|
||||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=false");
|
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=false");
|
||||||
initialize("property-in-if.xml");
|
initialize("property-in-if.xml");
|
||||||
@ -213,6 +253,19 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "property-in-include.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<include file="${resourceRoot}/include-with-property.xml"/>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
@WithResource(name = "include-with-property.xml", content = """
|
||||||
|
<included>
|
||||||
|
<springProperty scope="context" name="MINE" source="my.example-property" defaultValue="default-test"/>
|
||||||
|
</included>
|
||||||
|
""")
|
||||||
|
@ClassPathExclusions
|
||||||
void springPropertyInInclude() throws Exception {
|
void springPropertyInInclude() throws Exception {
|
||||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=test");
|
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=test");
|
||||||
initialize("property-in-include.xml");
|
initialize("property-in-include.xml");
|
||||||
@ -220,6 +273,7 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPropertyXmlResource
|
||||||
void addsAotContributionToContextDuringAotProcessing() throws Exception {
|
void addsAotContributionToContextDuringAotProcessing() throws Exception {
|
||||||
withSystemProperty("spring.aot.processing", "true", () -> {
|
withSystemProperty("spring.aot.processing", "true", () -> {
|
||||||
initialize("property.xml");
|
initialize("property.xml");
|
||||||
@ -253,7 +307,8 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
|
|
||||||
private void initialize(String config) throws JoranException {
|
private void initialize(String config) throws JoranException {
|
||||||
this.configurator.setContext(this.context);
|
this.configurator.setContext(this.context);
|
||||||
this.configurator.doConfigure(getClass().getResourceAsStream(config));
|
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
this.configurator.doConfigure(contextClassLoader.getResource(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface Action {
|
private interface Action {
|
||||||
@ -262,4 +317,112 @@ class SpringBootJoranConfiguratorTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "property-default-value.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<springProperty scope="context" name="SIMPLE" source="testpropertyfoobar" defaultValue="foo"/>
|
||||||
|
<springProperty scope="context" name="MINE" source="my.example-property" defaultValue="bar"/>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithPropertyDefaultValueXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "property-in-if.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<springProperty scope="context" name="MINE" source="my.example-property"/>
|
||||||
|
<if condition='property("MINE").contains("true")'>
|
||||||
|
<then>
|
||||||
|
<variable scope="context" name="MYCHECK" value="i-was-included"/>
|
||||||
|
</then>
|
||||||
|
</if>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithPropertyInIfXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "property.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<springProperty scope="context" name="SIMPLE" source="testpropertyfoobar"/>
|
||||||
|
<springProperty scope="context" name="MINE" source="my.example-property"/>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithPropertyXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "profile-expression.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<springProfile name="production | test">
|
||||||
|
<logger name="org.springframework.boot.logging.logback" level="TRACE"/>
|
||||||
|
</springProfile>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithProfileExpressionXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "production-profile.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<springProfile name="production">
|
||||||
|
<logger name="org.springframework.boot.logging.logback" level="TRACE"/>
|
||||||
|
</springProfile>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithProductionProfileXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "nested.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<springProfile name="outer">
|
||||||
|
<springProfile name="inner">
|
||||||
|
<logger name="org.springframework.boot.logging.logback" level="TRACE"/>
|
||||||
|
</springProfile>
|
||||||
|
</springProfile>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithNestedXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@WithResource(name = "multi-profile-names.xml", content = """
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||||
|
<springProfile name="production, test">
|
||||||
|
<logger name="org.springframework.boot.logging.logback" level="TRACE"/>
|
||||||
|
</springProfile>
|
||||||
|
</configuration>
|
||||||
|
""")
|
||||||
|
private @interface WithMultiProfileNamesXmlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -52,6 +52,8 @@ import org.springframework.boot.ssl.jks.JksSslStoreBundle;
|
|||||||
import org.springframework.boot.ssl.jks.JksSslStoreDetails;
|
import org.springframework.boot.ssl.jks.JksSslStoreDetails;
|
||||||
import org.springframework.boot.ssl.pem.PemSslStoreBundle;
|
import org.springframework.boot.ssl.pem.PemSslStoreBundle;
|
||||||
import org.springframework.boot.ssl.pem.PemSslStoreDetails;
|
import org.springframework.boot.ssl.pem.PemSslStoreDetails;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.ResourcePath;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.web.server.Ssl;
|
import org.springframework.boot.web.server.Ssl;
|
||||||
import org.springframework.core.codec.CharSequenceEncoder;
|
import org.springframework.core.codec.CharSequenceEncoder;
|
||||||
import org.springframework.core.codec.StringDecoder;
|
import org.springframework.core.codec.StringDecoder;
|
||||||
@ -156,91 +158,107 @@ class NettyRSocketServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void tcpTransportBasicSslFromClassPath() {
|
void tcpTransportBasicSslFromClassPath() {
|
||||||
testBasicSslWithKeyStore("classpath:test.jks", "password", Transport.TCP);
|
testBasicSslWithKeyStore("classpath:test.jks", "password", Transport.TCP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void tcpTransportBasicSslFromFileSystem() {
|
@WithPackageResources("test.jks")
|
||||||
testBasicSslWithKeyStore("src/test/resources/test.jks", "password", Transport.TCP);
|
void tcpTransportBasicSslFromFileSystem(@ResourcePath("test.jks") String keyStore) {
|
||||||
|
testBasicSslWithKeyStore(keyStore, "password", Transport.TCP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void websocketTransportBasicSslFromClassPath() {
|
void websocketTransportBasicSslFromClassPath() {
|
||||||
testBasicSslWithKeyStore("classpath:test.jks", "password", Transport.WEBSOCKET);
|
testBasicSslWithKeyStore("classpath:test.jks", "password", Transport.WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void websocketTransportBasicSslFromFileSystem() {
|
@WithPackageResources("test.jks")
|
||||||
testBasicSslWithKeyStore("src/test/resources/test.jks", "password", Transport.WEBSOCKET);
|
void websocketTransportBasicSslFromFileSystem(@ResourcePath("test.jks") String keyStore) {
|
||||||
|
testBasicSslWithKeyStore(keyStore, "password", Transport.WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void tcpTransportBasicSslCertificateFromClassPath() {
|
void tcpTransportBasicSslCertificateFromClassPath() {
|
||||||
testBasicSslWithPemCertificate("classpath:test-cert.pem", "classpath:test-key.pem", "classpath:test-cert.pem",
|
testBasicSslWithPemCertificate("classpath:test-cert.pem", "classpath:test-key.pem", "classpath:test-cert.pem",
|
||||||
Transport.TCP);
|
Transport.TCP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void tcpTransportBasicSslCertificateFromFileSystem() {
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
testBasicSslWithPemCertificate("src/test/resources/test-cert.pem", "src/test/resources/test-key.pem",
|
void tcpTransportBasicSslCertificateFromFileSystem(@ResourcePath("test-cert.pem") String testCert,
|
||||||
"src/test/resources/test-cert.pem", Transport.TCP);
|
@ResourcePath("test-key.pem") String testKey) {
|
||||||
|
testBasicSslWithPemCertificate(testCert, testKey, testCert, Transport.TCP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void websocketTransportBasicSslCertificateFromClassPath() {
|
void websocketTransportBasicSslCertificateFromClassPath() {
|
||||||
testBasicSslWithPemCertificate("classpath:test-cert.pem", "classpath:test-key.pem", "classpath:test-cert.pem",
|
testBasicSslWithPemCertificate("classpath:test-cert.pem", "classpath:test-key.pem", "classpath:test-cert.pem",
|
||||||
Transport.WEBSOCKET);
|
Transport.WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void websocketTransportBasicSslCertificateFromFileSystem() {
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
testBasicSslWithPemCertificate("src/test/resources/test-cert.pem", "src/test/resources/test-key.pem",
|
void websocketTransportBasicSslCertificateFromFileSystem(@ResourcePath("test-cert.pem") String testCert,
|
||||||
"src/test/resources/test-cert.pem", Transport.WEBSOCKET);
|
@ResourcePath("test-key.pem") String testKey) {
|
||||||
|
testBasicSslWithPemCertificate(testCert, testKey, testCert, Transport.WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void tcpTransportBasicSslFromClassPathWithBundle() {
|
void tcpTransportBasicSslFromClassPathWithBundle() {
|
||||||
testBasicSslWithKeyStoreFromBundle("classpath:test.jks", "password", Transport.TCP);
|
testBasicSslWithKeyStoreFromBundle("classpath:test.jks", "password", Transport.TCP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void tcpTransportBasicSslFromFileSystemWithBundle() {
|
@WithPackageResources("test.jks")
|
||||||
testBasicSslWithKeyStoreFromBundle("src/test/resources/test.jks", "password", Transport.TCP);
|
void tcpTransportBasicSslFromFileSystemWithBundle(@ResourcePath("test.jks") String keyStore) {
|
||||||
|
testBasicSslWithKeyStoreFromBundle(keyStore, "password", Transport.TCP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void websocketTransportBasicSslFromClassPathWithBundle() {
|
void websocketTransportBasicSslFromClassPathWithBundle() {
|
||||||
testBasicSslWithKeyStoreFromBundle("classpath:test.jks", "password", Transport.WEBSOCKET);
|
testBasicSslWithKeyStoreFromBundle("classpath:test.jks", "password", Transport.WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void websocketTransportBasicSslFromFileSystemWithBundle() {
|
@WithPackageResources("test.jks")
|
||||||
testBasicSslWithKeyStoreFromBundle("src/test/resources/test.jks", "password", Transport.WEBSOCKET);
|
void websocketTransportBasicSslFromFileSystemWithBundle(@ResourcePath("test.jks") String keyStore) {
|
||||||
|
testBasicSslWithKeyStoreFromBundle(keyStore, "password", Transport.WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void tcpTransportBasicSslCertificateFromClassPathWithBundle() {
|
void tcpTransportBasicSslCertificateFromClassPathWithBundle() {
|
||||||
testBasicSslWithPemCertificateFromBundle("classpath:test-cert.pem", "classpath:test-key.pem",
|
testBasicSslWithPemCertificateFromBundle("classpath:test-cert.pem", "classpath:test-key.pem",
|
||||||
"classpath:test-cert.pem", Transport.TCP);
|
"classpath:test-cert.pem", Transport.TCP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void tcpTransportBasicSslCertificateFromFileSystemWithBundle() {
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
testBasicSslWithPemCertificateFromBundle("src/test/resources/test-cert.pem", "src/test/resources/test-key.pem",
|
void tcpTransportBasicSslCertificateFromFileSystemWithBundle(@ResourcePath("test-cert.pem") String testCert,
|
||||||
"src/test/resources/test-cert.pem", Transport.TCP);
|
@ResourcePath("test-key.pem") String testKey) {
|
||||||
|
testBasicSslWithPemCertificateFromBundle(testCert, testKey, testCert, Transport.TCP);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void websocketTransportBasicSslCertificateFromClassPathWithBundle() {
|
void websocketTransportBasicSslCertificateFromClassPathWithBundle() {
|
||||||
testBasicSslWithPemCertificateFromBundle("classpath:test-cert.pem", "classpath:test-key.pem",
|
testBasicSslWithPemCertificateFromBundle("classpath:test-cert.pem", "classpath:test-key.pem",
|
||||||
"classpath:test-cert.pem", Transport.WEBSOCKET);
|
"classpath:test-cert.pem", Transport.WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void websocketTransportBasicSslCertificateFromFileSystemWithBundle() {
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
testBasicSslWithPemCertificateFromBundle("src/test/resources/test-cert.pem", "src/test/resources/test-key.pem",
|
void websocketTransportBasicSslCertificateFromFileSystemWithBundle(@ResourcePath("test-cert.pem") String testCert,
|
||||||
"src/test/resources/test-cert.pem", Transport.WEBSOCKET);
|
@ResourcePath("test-key.pem") String testKey) {
|
||||||
|
testBasicSslWithPemCertificateFromBundle(testCert, testKey, testCert, Transport.WEBSOCKET);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkEchoRequest() {
|
private void checkEchoRequest() {
|
||||||
@ -318,7 +336,7 @@ class NettyRSocketServerFactoryTests {
|
|||||||
NettyRSocketServerFactory factory = getFactory();
|
NettyRSocketServerFactory factory = getFactory();
|
||||||
factory.setTransport(Transport.TCP);
|
factory.setTransport(Transport.TCP);
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStore("classpath:test.jks");
|
ssl.setKeyStore("classpath:org/springframework/boot/rsocket/netty/test.jks");
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
factory.setSsl(ssl);
|
factory.setSsl(ssl);
|
||||||
this.server = factory.create(new EchoRequestResponseAcceptor());
|
this.server = factory.create(new EchoRequestResponseAcceptor());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,10 +16,15 @@
|
|||||||
|
|
||||||
package org.springframework.boot.sql.init;
|
package org.springframework.boot.sql.init;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -35,6 +40,8 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
|||||||
public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractScriptDatabaseInitializer> {
|
public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractScriptDatabaseInitializer> {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSchemaSqlResource
|
||||||
|
@WithDataSqlResource
|
||||||
void whenDatabaseIsInitializedThenSchemaAndDataScriptsAreApplied() {
|
void whenDatabaseIsInitializedThenSchemaAndDataScriptsAreApplied() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||||
@ -55,6 +62,7 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithDataSqlResource
|
||||||
void whenContinueOnErrorIsFalseThenInitializationFailsOnError() {
|
void whenContinueOnErrorIsFalseThenInitializationFailsOnError() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setDataLocations(Arrays.asList("data.sql"));
|
settings.setDataLocations(Arrays.asList("data.sql"));
|
||||||
@ -64,6 +72,7 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithDataSqlResource
|
||||||
void whenContinueOnErrorIsTrueThenInitializationDoesNotFailOnError() {
|
void whenContinueOnErrorIsTrueThenInitializationDoesNotFailOnError() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setContinueOnError(true);
|
settings.setContinueOnError(true);
|
||||||
@ -112,6 +121,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSchemaSqlResource
|
||||||
|
@WithDataSqlResource
|
||||||
void whenModeIsNeverThenEmbeddedDatabaseIsNotInitialized() {
|
void whenModeIsNeverThenEmbeddedDatabaseIsNotInitialized() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||||
@ -123,6 +134,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSchemaSqlResource
|
||||||
|
@WithDataSqlResource
|
||||||
void whenModeIsNeverThenStandaloneDatabaseIsNotInitialized() {
|
void whenModeIsNeverThenStandaloneDatabaseIsNotInitialized() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||||
@ -134,6 +147,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSchemaSqlResource
|
||||||
|
@WithDataSqlResource
|
||||||
void whenModeIsEmbeddedThenEmbeddedDatabaseIsInitialized() {
|
void whenModeIsEmbeddedThenEmbeddedDatabaseIsInitialized() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||||
@ -145,6 +160,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSchemaSqlResource
|
||||||
|
@WithDataSqlResource
|
||||||
void whenModeIsEmbeddedThenStandaloneDatabaseIsNotInitialized() {
|
void whenModeIsEmbeddedThenStandaloneDatabaseIsNotInitialized() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||||
@ -156,6 +173,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSchemaSqlResource
|
||||||
|
@WithDataSqlResource
|
||||||
void whenModeIsAlwaysThenEmbeddedDatabaseIsInitialized() {
|
void whenModeIsAlwaysThenEmbeddedDatabaseIsInitialized() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||||
@ -167,6 +186,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithSchemaSqlResource
|
||||||
|
@WithDataSqlResource
|
||||||
void whenModeIsAlwaysThenStandaloneDatabaseIsInitialized() {
|
void whenModeIsAlwaysThenStandaloneDatabaseIsInitialized() {
|
||||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||||
@ -195,4 +216,23 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
|||||||
|
|
||||||
protected abstract void assertDatabaseAccessed(boolean accessed, T initializer);
|
protected abstract void assertDatabaseAccessed(boolean accessed, T initializer);
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@WithResource(name = "schema.sql", content = """
|
||||||
|
CREATE TABLE EXAMPLE (
|
||||||
|
id INTEGER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||||||
|
name VARCHAR(30)
|
||||||
|
);
|
||||||
|
""")
|
||||||
|
protected @interface WithSchemaSqlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
@WithResource(name = "data.sql", content = "INSERT INTO EXAMPLE VALUES (1, 'Andy');")
|
||||||
|
protected @interface WithDataSqlResource {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import java.util.function.Consumer;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.io.ApplicationResourceLoader;
|
import org.springframework.boot.io.ApplicationResourceLoader;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
@ -77,6 +78,7 @@ class JksSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void whenHasKeyStoreLocation() {
|
void whenHasKeyStoreLocation() {
|
||||||
JksSslStoreDetails keyStoreDetails = JksSslStoreDetails.forLocation("classpath:test.jks")
|
JksSslStoreDetails keyStoreDetails = JksSslStoreDetails.forLocation("classpath:test.jks")
|
||||||
.withPassword("secret");
|
.withPassword("secret");
|
||||||
@ -86,6 +88,7 @@ class JksSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void getTrustStoreWithLocations() {
|
void getTrustStoreWithLocations() {
|
||||||
JksSslStoreDetails keyStoreDetails = null;
|
JksSslStoreDetails keyStoreDetails = null;
|
||||||
JksSslStoreDetails trustStoreDetails = JksSslStoreDetails.forLocation("classpath:test.jks")
|
JksSslStoreDetails trustStoreDetails = JksSslStoreDetails.forLocation("classpath:test.jks")
|
||||||
@ -95,6 +98,7 @@ class JksSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void whenHasKeyStoreType() {
|
void whenHasKeyStoreType() {
|
||||||
JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails("jks", null, "classpath:test.jks", "secret");
|
JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails("jks", null, "classpath:test.jks", "secret");
|
||||||
JksSslStoreDetails trustStoreDetails = null;
|
JksSslStoreDetails trustStoreDetails = null;
|
||||||
@ -103,6 +107,7 @@ class JksSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void whenHasTrustStoreType() {
|
void whenHasTrustStoreType() {
|
||||||
JksSslStoreDetails keyStoreDetails = null;
|
JksSslStoreDetails keyStoreDetails = null;
|
||||||
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails("jks", null, "classpath:test.jks", "secret");
|
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails("jks", null, "classpath:test.jks", "secret");
|
||||||
@ -111,6 +116,7 @@ class JksSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void whenHasKeyStoreProvider() {
|
void whenHasKeyStoreProvider() {
|
||||||
JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails(null, "com.example.KeyStoreProvider",
|
JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails(null, "com.example.KeyStoreProvider",
|
||||||
"classpath:test.jks", "secret");
|
"classpath:test.jks", "secret");
|
||||||
@ -120,6 +126,7 @@ class JksSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void whenHasTrustStoreProvider() {
|
void whenHasTrustStoreProvider() {
|
||||||
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails(null, "com.example.KeyStoreProvider",
|
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails(null, "com.example.KeyStoreProvider",
|
||||||
"classpath:test.jks", "secret");
|
"classpath:test.jks", "secret");
|
||||||
@ -137,6 +144,7 @@ class JksSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test.p12", "test.jks" })
|
||||||
void whenLocationsAreBase64Encoded() throws IOException {
|
void whenLocationsAreBase64Encoded() throws IOException {
|
||||||
JksSslStoreDetails keyStoreDetails = JksSslStoreDetails.forLocation(encodeFileContent("classpath:test.p12"))
|
JksSslStoreDetails keyStoreDetails = JksSslStoreDetails.forLocation(encodeFileContent("classpath:test.p12"))
|
||||||
.withPassword("secret");
|
.withPassword("secret");
|
||||||
@ -169,6 +177,7 @@ class JksSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void usesResourceLoader() {
|
void usesResourceLoader() {
|
||||||
JksSslStoreDetails keyStoreDetails = null;
|
JksSslStoreDetails keyStoreDetails = null;
|
||||||
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails("jks", null, "classpath:test.jks", "secret");
|
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails("jks", null, "classpath:test.jks", "secret");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -21,6 +21,7 @@ import java.io.UncheckedIOException;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.io.ApplicationResourceLoader;
|
import org.springframework.boot.io.ApplicationResourceLoader;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ import static org.mockito.Mockito.spy;
|
|||||||
class LoadedPemSslStoreTests {
|
class LoadedPemSslStoreTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-key.pem")
|
||||||
void certificatesAreLoadedLazily() {
|
void certificatesAreLoadedLazily() {
|
||||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
||||||
.withPrivateKey("classpath:test-key.pem");
|
.withPrivateKey("classpath:test-key.pem");
|
||||||
@ -45,6 +47,7 @@ class LoadedPemSslStoreTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-cert.pem")
|
||||||
void privateKeyIsLoadedLazily() {
|
void privateKeyIsLoadedLazily() {
|
||||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||||
.withPrivateKey("classpath:missing-test-key.pem");
|
.withPrivateKey("classpath:missing-test-key.pem");
|
||||||
@ -53,6 +56,7 @@ class LoadedPemSslStoreTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-key.pem")
|
||||||
void withAliasIsLazy() {
|
void withAliasIsLazy() {
|
||||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
||||||
.withPrivateKey("classpath:test-key.pem");
|
.withPrivateKey("classpath:test-key.pem");
|
||||||
@ -61,6 +65,7 @@ class LoadedPemSslStoreTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-key.pem")
|
||||||
void withPasswordIsLazy() {
|
void withPasswordIsLazy() {
|
||||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
||||||
.withPrivateKey("classpath:test-key.pem");
|
.withPrivateKey("classpath:test-key.pem");
|
||||||
@ -69,6 +74,7 @@ class LoadedPemSslStoreTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-cert.pem")
|
||||||
void usesResourceLoader() {
|
void usesResourceLoader() {
|
||||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:test-cert.pem");
|
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:test-cert.pem");
|
||||||
ResourceLoader resourceLoader = spy(new DefaultResourceLoader());
|
ResourceLoader resourceLoader = spy(new DefaultResourceLoader());
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -23,6 +23,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -35,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
class PemCertificateParserTests {
|
class PemCertificateParserTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-cert.pem")
|
||||||
void parseCertificate() throws Exception {
|
void parseCertificate() throws Exception {
|
||||||
List<X509Certificate> certificates = PemCertificateParser.parse(read("test-cert.pem"));
|
List<X509Certificate> certificates = PemCertificateParser.parse(read("test-cert.pem"));
|
||||||
assertThat(certificates).isNotNull();
|
assertThat(certificates).isNotNull();
|
||||||
@ -43,6 +45,7 @@ class PemCertificateParserTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-cert-chain.pem")
|
||||||
void parseCertificateChain() throws Exception {
|
void parseCertificateChain() throws Exception {
|
||||||
List<X509Certificate> certificates = PemCertificateParser.parse(read("test-cert-chain.pem"));
|
List<X509Certificate> certificates = PemCertificateParser.parse(read("test-cert-chain.pem"));
|
||||||
assertThat(certificates).isNotNull();
|
assertThat(certificates).isNotNull();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -26,6 +26,8 @@ import java.util.List;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.springframework.boot.io.ApplicationResourceLoader;
|
import org.springframework.boot.io.ApplicationResourceLoader;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.ResourcePath;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.core.io.ClassPathResource;
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.DefaultResourceLoader;
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
@ -51,6 +53,7 @@ class PemContentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-cert-chain.pem")
|
||||||
void getCertificateReturnsCertificates() throws Exception {
|
void getCertificateReturnsCertificates() throws Exception {
|
||||||
PemContent content = PemContent.load(contentFromClasspath("/test-cert-chain.pem"),
|
PemContent content = PemContent.load(contentFromClasspath("/test-cert-chain.pem"),
|
||||||
new ApplicationResourceLoader());
|
new ApplicationResourceLoader());
|
||||||
@ -69,9 +72,9 @@ class PemContentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("dsa.key")
|
||||||
void getPrivateKeyReturnsPrivateKey() throws Exception {
|
void getPrivateKeyReturnsPrivateKey() throws Exception {
|
||||||
PemContent content = PemContent.load(contentFromClasspath("/org/springframework/boot/web/server/pkcs8/dsa.key"),
|
PemContent content = PemContent.load(contentFromClasspath("dsa.key"), new ApplicationResourceLoader());
|
||||||
new ApplicationResourceLoader());
|
|
||||||
PrivateKey privateKey = content.getPrivateKey();
|
PrivateKey privateKey = content.getPrivateKey();
|
||||||
assertThat(privateKey).isNotNull();
|
assertThat(privateKey).isNotNull();
|
||||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||||
@ -122,6 +125,7 @@ class PemContentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-cert.pem")
|
||||||
void loadWithStringWhenClasspathLocationReturnsContent() throws IOException {
|
void loadWithStringWhenClasspathLocationReturnsContent() throws IOException {
|
||||||
String actual = PemContent.load("classpath:test-cert.pem", new ApplicationResourceLoader()).toString();
|
String actual = PemContent.load("classpath:test-cert.pem", new ApplicationResourceLoader()).toString();
|
||||||
String expected = contentFromClasspath("test-cert.pem");
|
String expected = contentFromClasspath("test-cert.pem");
|
||||||
@ -129,21 +133,24 @@ class PemContentTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loadWithStringWhenFileLocationReturnsContent() throws IOException {
|
@WithPackageResources("test-cert.pem")
|
||||||
String actual = PemContent.load("src/test/resources/test-cert.pem", new ApplicationResourceLoader()).toString();
|
void loadWithStringWhenFileLocationReturnsContent(@ResourcePath("test-cert.pem") String testCert)
|
||||||
|
throws IOException {
|
||||||
|
String actual = PemContent.load(testCert, new ApplicationResourceLoader()).toString();
|
||||||
String expected = contentFromClasspath("test-cert.pem");
|
String expected = contentFromClasspath("test-cert.pem");
|
||||||
assertThat(actual).isEqualTo(expected);
|
assertThat(actual).isEqualTo(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loadWithPathReturnsContent() throws IOException {
|
@WithPackageResources("test-cert.pem")
|
||||||
Path path = Path.of("src/test/resources/test-cert.pem");
|
void loadWithPathReturnsContent(@ResourcePath("test-cert.pem") Path testCert) throws IOException {
|
||||||
String actual = PemContent.load(path).toString();
|
String actual = PemContent.load(testCert).toString();
|
||||||
String expected = contentFromClasspath("test-cert.pem");
|
String expected = contentFromClasspath("test-cert.pem");
|
||||||
assertThat(actual).isEqualTo(expected);
|
assertThat(actual).isEqualTo(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test-cert.pem")
|
||||||
void loadWithResourceLoaderUsesResourceLoader() throws IOException {
|
void loadWithResourceLoaderUsesResourceLoader() throws IOException {
|
||||||
ResourceLoader resourceLoader = spy(new DefaultResourceLoader());
|
ResourceLoader resourceLoader = spy(new DefaultResourceLoader());
|
||||||
PemContent.load("classpath:test-cert.pem", resourceLoader);
|
PemContent.load("classpath:test-cert.pem", resourceLoader);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -49,34 +49,23 @@ class PemPrivateKeyParserTests {
|
|||||||
})
|
})
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
void shouldParseTraditionalPkcs8(String file, String algorithm) throws IOException {
|
void shouldParseTraditionalPkcs8(String file, String algorithm) throws IOException {
|
||||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs8/" + file));
|
PrivateKey privateKey = PemPrivateKeyParser.parse(read("pkcs8/" + file));
|
||||||
assertThat(privateKey).isNotNull();
|
assertThat(privateKey).isNotNull();
|
||||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||||
assertThat(privateKey.getAlgorithm()).isEqualTo(algorithm);
|
assertThat(privateKey.getAlgorithm()).isEqualTo(algorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
// @formatter:off
|
void shouldParseTraditionalPkcs1() throws IOException {
|
||||||
@CsvSource({
|
PrivateKey privateKey = PemPrivateKeyParser.parse(read("pkcs1/rsa.key"));
|
||||||
"rsa.key, RSA"
|
|
||||||
})
|
|
||||||
// @formatter:on
|
|
||||||
void shouldParseTraditionalPkcs1(String file, String algorithm) throws IOException {
|
|
||||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs1/" + file));
|
|
||||||
assertThat(privateKey).isNotNull();
|
assertThat(privateKey).isNotNull();
|
||||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||||
assertThat(privateKey.getAlgorithm()).isEqualTo(algorithm);
|
assertThat(privateKey.getAlgorithm()).isEqualTo("RSA");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@Test
|
||||||
// @formatter:off
|
void shouldNotParseUnsupportedTraditionalPkcs1() {
|
||||||
@ValueSource(strings = {
|
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs1/dsa.key")))
|
||||||
"dsa.key"
|
|
||||||
})
|
|
||||||
// @formatter:on
|
|
||||||
void shouldNotParseUnsupportedTraditionalPkcs1(String file) {
|
|
||||||
assertThatIllegalStateException()
|
|
||||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs1/" + file)))
|
|
||||||
.withMessageContaining("Missing private key or unrecognized format");
|
.withMessageContaining("Missing private key or unrecognized format");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +85,7 @@ class PemPrivateKeyParserTests {
|
|||||||
})
|
})
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
void shouldParseEcPkcs8(String file, String curveName, String oid) throws IOException {
|
void shouldParseEcPkcs8(String file, String curveName, String oid) throws IOException {
|
||||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs8/" + file));
|
PrivateKey privateKey = PemPrivateKeyParser.parse(read("pkcs8/" + file));
|
||||||
assertThat(privateKey).isNotNull();
|
assertThat(privateKey).isNotNull();
|
||||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||||
assertThat(privateKey.getAlgorithm()).isEqualTo("EC");
|
assertThat(privateKey.getAlgorithm()).isEqualTo("EC");
|
||||||
@ -115,8 +104,7 @@ class PemPrivateKeyParserTests {
|
|||||||
})
|
})
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
void shouldNotParseUnsupportedEcPkcs8(String file) {
|
void shouldNotParseUnsupportedEcPkcs8(String file) {
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs8/" + file)))
|
||||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs8/" + file)))
|
|
||||||
.withMessageContaining("Missing private key or unrecognized format");
|
.withMessageContaining("Missing private key or unrecognized format");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +116,7 @@ class PemPrivateKeyParserTests {
|
|||||||
})
|
})
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
void shouldParseEdDsaPkcs8(String file) throws IOException {
|
void shouldParseEdDsaPkcs8(String file) throws IOException {
|
||||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs8/" + file));
|
PrivateKey privateKey = PemPrivateKeyParser.parse(read("pkcs8/" + file));
|
||||||
assertThat(privateKey).isNotNull();
|
assertThat(privateKey).isNotNull();
|
||||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||||
assertThat(privateKey.getAlgorithm()).isEqualTo("EdDSA");
|
assertThat(privateKey.getAlgorithm()).isEqualTo("EdDSA");
|
||||||
@ -142,7 +130,7 @@ class PemPrivateKeyParserTests {
|
|||||||
})
|
})
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
void shouldParseXdhPkcs8(String file) throws IOException {
|
void shouldParseXdhPkcs8(String file) throws IOException {
|
||||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs8/" + file));
|
PrivateKey privateKey = PemPrivateKeyParser.parse(read("pkcs8/" + file));
|
||||||
assertThat(privateKey).isNotNull();
|
assertThat(privateKey).isNotNull();
|
||||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||||
assertThat(privateKey.getAlgorithm()).isEqualTo("XDH");
|
assertThat(privateKey.getAlgorithm()).isEqualTo("XDH");
|
||||||
@ -164,7 +152,7 @@ class PemPrivateKeyParserTests {
|
|||||||
})
|
})
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
void shouldParseEcSec1(String file, String curveName, String oid) throws IOException {
|
void shouldParseEcSec1(String file, String curveName, String oid) throws IOException {
|
||||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/sec1/" + file));
|
PrivateKey privateKey = PemPrivateKeyParser.parse(read("sec1/" + file));
|
||||||
assertThat(privateKey).isNotNull();
|
assertThat(privateKey).isNotNull();
|
||||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||||
assertThat(privateKey.getAlgorithm()).isEqualTo("EC");
|
assertThat(privateKey.getAlgorithm()).isEqualTo("EC");
|
||||||
@ -183,14 +171,13 @@ class PemPrivateKeyParserTests {
|
|||||||
})
|
})
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
void shouldNotParseUnsupportedEcSec1(String file) {
|
void shouldNotParseUnsupportedEcSec1(String file) {
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("sec1/" + file)))
|
||||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/sec1/" + file)))
|
|
||||||
.withMessageContaining("Missing private key or unrecognized format");
|
.withMessageContaining("Missing private key or unrecognized format");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void parseWithNonKeyTextWillThrowException() {
|
void parseWithNonKeyTextWillThrowException() {
|
||||||
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("test-banner.txt")));
|
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("file.txt")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ -208,8 +195,7 @@ class PemPrivateKeyParserTests {
|
|||||||
// openssl pkcs8 -topk8 -in <input file> -out <output file> -v2 <algorithm>
|
// openssl pkcs8 -topk8 -in <input file> -out <output file> -v2 <algorithm>
|
||||||
// -passout pass:test
|
// -passout pass:test
|
||||||
// where <algorithm> is aes128 or aes256
|
// where <algorithm> is aes128 or aes256
|
||||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs8/" + file),
|
PrivateKey privateKey = PemPrivateKeyParser.parse(read("pkcs8/" + file), "test");
|
||||||
"test");
|
|
||||||
assertThat(privateKey).isNotNull();
|
assertThat(privateKey).isNotNull();
|
||||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||||
assertThat(privateKey.getAlgorithm()).isEqualTo(algorithm);
|
assertThat(privateKey.getAlgorithm()).isEqualTo(algorithm);
|
||||||
@ -221,8 +207,7 @@ class PemPrivateKeyParserTests {
|
|||||||
// openssl pkcs8 -topk8 -in rsa.key -out rsa-des-ede3-cbc.key -v2 des3 -passout
|
// openssl pkcs8 -topk8 -in rsa.key -out rsa-des-ede3-cbc.key -v2 des3 -passout
|
||||||
// pass:test
|
// pass:test
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(() -> PemPrivateKeyParser
|
.isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs8/rsa-des-ede3-cbc.key"), "test"))
|
||||||
.parse(read("org/springframework/boot/web/server/pkcs8/rsa-des-ede3-cbc.key"), "test"))
|
|
||||||
.isInstanceOf(IllegalStateException.class)
|
.isInstanceOf(IllegalStateException.class)
|
||||||
.withMessageContaining("Error decrypting private key");
|
.withMessageContaining("Error decrypting private key");
|
||||||
}
|
}
|
||||||
@ -233,8 +218,7 @@ class PemPrivateKeyParserTests {
|
|||||||
// openssl pkcs8 -topk8 -in rsa.key -out rsa-des-ede3-cbc.key -scrypt -passout
|
// openssl pkcs8 -topk8 -in rsa.key -out rsa-des-ede3-cbc.key -scrypt -passout
|
||||||
// pass:test
|
// pass:test
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(() -> PemPrivateKeyParser
|
.isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs8/rsa-scrypt.key"), "test"))
|
||||||
.parse(read("org/springframework/boot/web/server/pkcs8/rsa-scrypt.key"), "test"))
|
|
||||||
.withMessageContaining("Error decrypting private key");
|
.withMessageContaining("Error decrypting private key");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,8 +228,7 @@ class PemPrivateKeyParserTests {
|
|||||||
// openssl ecparam -genkey -name prime256v1 | openssl ec -aes-128-cbc -out
|
// openssl ecparam -genkey -name prime256v1 | openssl ec -aes-128-cbc -out
|
||||||
// prime256v1-aes-128-cbc.key
|
// prime256v1-aes-128-cbc.key
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(() -> PemPrivateKeyParser
|
.isThrownBy(() -> PemPrivateKeyParser.parse(read("sec1/prime256v1-aes-128-cbc.key"), "test"))
|
||||||
.parse(read("org/springframework/boot/web/server/sec1/prime256v1-aes-128-cbc.key"), "test"))
|
|
||||||
.withMessageContaining("Missing private key or unrecognized format");
|
.withMessageContaining("Missing private key or unrecognized format");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,13 +237,13 @@ class PemPrivateKeyParserTests {
|
|||||||
// created with:
|
// created with:
|
||||||
// openssl genrsa -aes-256-cbc -out rsa-aes-256-cbc.key
|
// openssl genrsa -aes-256-cbc -out rsa-aes-256-cbc.key
|
||||||
assertThatIllegalStateException()
|
assertThatIllegalStateException()
|
||||||
.isThrownBy(() -> PemPrivateKeyParser
|
.isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs1/rsa-aes-256-cbc.key"), "test"))
|
||||||
.parse(read("org/springframework/boot/web/server/pkcs1/rsa-aes-256-cbc.key"), "test"))
|
|
||||||
.withMessageContaining("Missing private key or unrecognized format");
|
.withMessageContaining("Missing private key or unrecognized format");
|
||||||
}
|
}
|
||||||
|
|
||||||
private String read(String path) throws IOException {
|
private String read(String path) throws IOException {
|
||||||
return new ClassPathResource(path).getContentAsString(StandardCharsets.UTF_8);
|
return new ClassPathResource("org/springframework/boot/ssl/pem/" + path)
|
||||||
|
.getContentAsString(StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -24,6 +24,7 @@ import java.util.function.Consumer;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.util.function.ThrowingConsumer;
|
import org.springframework.util.function.ThrowingConsumer;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -120,6 +121,7 @@ class PemSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void createWithDetailsWhenHasKeyStoreDetailsCertAndKey() {
|
void createWithDetailsWhenHasKeyStoreDetailsCertAndKey() {
|
||||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||||
.withPrivateKey("classpath:test-key.pem");
|
.withPrivateKey("classpath:test-key.pem");
|
||||||
@ -130,9 +132,10 @@ class PemSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "pkcs8/key-rsa-encrypted.pem" })
|
||||||
void createWithDetailsWhenHasKeyStoreDetailsCertAndEncryptedKey() {
|
void createWithDetailsWhenHasKeyStoreDetailsCertAndEncryptedKey() {
|
||||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||||
.withPrivateKey("classpath:ssl/pkcs8/key-rsa-encrypted.pem")
|
.withPrivateKey("classpath:pkcs8/key-rsa-encrypted.pem")
|
||||||
.withPrivateKeyPassword("test");
|
.withPrivateKeyPassword("test");
|
||||||
PemSslStoreDetails trustStoreDetails = null;
|
PemSslStoreDetails trustStoreDetails = null;
|
||||||
PemSslStoreBundle bundle = new PemSslStoreBundle(keyStoreDetails, trustStoreDetails);
|
PemSslStoreBundle bundle = new PemSslStoreBundle(keyStoreDetails, trustStoreDetails);
|
||||||
@ -141,6 +144,7 @@ class PemSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsWithoutKey() {
|
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsWithoutKey() {
|
||||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||||
.withPrivateKey("classpath:test-key.pem");
|
.withPrivateKey("classpath:test-key.pem");
|
||||||
@ -151,6 +155,7 @@ class PemSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetails() {
|
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetails() {
|
||||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||||
.withPrivateKey("classpath:test-key.pem");
|
.withPrivateKey("classpath:test-key.pem");
|
||||||
@ -173,6 +178,7 @@ class PemSslStoreBundleTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("removal")
|
@SuppressWarnings("removal")
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsAndAlias() {
|
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsAndAlias() {
|
||||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||||
.withPrivateKey("classpath:test-key.pem");
|
.withPrivateKey("classpath:test-key.pem");
|
||||||
@ -184,6 +190,7 @@ class PemSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void createWithDetailsWhenHasStoreType() {
|
void createWithDetailsWhenHasStoreType() {
|
||||||
PemSslStoreDetails keyStoreDetails = new PemSslStoreDetails("PKCS12", "classpath:test-cert.pem",
|
PemSslStoreDetails keyStoreDetails = new PemSslStoreDetails("PKCS12", "classpath:test-cert.pem",
|
||||||
"classpath:test-key.pem");
|
"classpath:test-key.pem");
|
||||||
@ -195,6 +202,7 @@ class PemSslStoreBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||||
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsAndKeyPassword() {
|
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsAndKeyPassword() {
|
||||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||||
.withPrivateKey("classpath:test-key.pem")
|
.withPrivateKey("classpath:test-key.pem")
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -36,6 +36,7 @@ import org.springframework.boot.ssl.SslBundle;
|
|||||||
import org.springframework.boot.ssl.SslBundleKey;
|
import org.springframework.boot.ssl.SslBundleKey;
|
||||||
import org.springframework.boot.ssl.jks.JksSslStoreBundle;
|
import org.springframework.boot.ssl.jks.JksSslStoreBundle;
|
||||||
import org.springframework.boot.ssl.jks.JksSslStoreDetails;
|
import org.springframework.boot.ssl.jks.JksSslStoreDetails;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
||||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||||
import org.springframework.boot.web.server.Ssl;
|
import org.springframework.boot.web.server.Ssl;
|
||||||
@ -124,6 +125,7 @@ abstract class AbstractClientHttpRequestFactoriesTests<T extends ClientHttpReque
|
|||||||
|
|
||||||
@ParameterizedTest
|
@ParameterizedTest
|
||||||
@ValueSource(strings = { "GET", "POST" })
|
@ValueSource(strings = { "GET", "POST" })
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void connectWithSslBundle(String httpMethod) throws Exception {
|
void connectWithSslBundle(String httpMethod) throws Exception {
|
||||||
TomcatServletWebServerFactory webServerFactory = new TomcatServletWebServerFactory(0);
|
TomcatServletWebServerFactory webServerFactory = new TomcatServletWebServerFactory(0);
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -62,6 +62,8 @@ import org.junit.jupiter.api.Disabled;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.ResourcePath;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.web.server.Compression;
|
import org.springframework.boot.web.server.Compression;
|
||||||
import org.springframework.boot.web.server.GracefulShutdownResult;
|
import org.springframework.boot.web.server.GracefulShutdownResult;
|
||||||
@ -230,9 +232,10 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sslCiphersConfiguration() {
|
@WithPackageResources("test.jks")
|
||||||
|
void sslCiphersConfiguration(@ResourcePath("test.jks") String keyStore) {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore(keyStore);
|
||||||
ssl.setKeyStorePassword("secret");
|
ssl.setKeyStorePassword("secret");
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
||||||
@ -261,9 +264,10 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sslEnabledMultiProtocolsConfiguration() {
|
@WithPackageResources("test.jks")
|
||||||
|
void sslEnabledMultiProtocolsConfiguration(@ResourcePath("test.jks") String keyStore) {
|
||||||
JettyServletWebServerFactory factory = getFactory();
|
JettyServletWebServerFactory factory = getFactory();
|
||||||
factory.setSsl(getSslSettings("TLSv1.1", "TLSv1.2"));
|
factory.setSsl(getSslSettings(keyStore, "TLSv1.1", "TLSv1.2"));
|
||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
JettyWebServer jettyWebServer = (JettyWebServer) this.webServer;
|
JettyWebServer jettyWebServer = (JettyWebServer) this.webServer;
|
||||||
@ -274,9 +278,10 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sslEnabledProtocolsConfiguration() {
|
@WithPackageResources("test.jks")
|
||||||
|
void sslEnabledProtocolsConfiguration(@ResourcePath("test.jks") String keyStore) {
|
||||||
JettyServletWebServerFactory factory = getFactory();
|
JettyServletWebServerFactory factory = getFactory();
|
||||||
factory.setSsl(getSslSettings("TLSv1.1"));
|
factory.setSsl(getSslSettings(keyStore, "TLSv1.1"));
|
||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
JettyWebServer jettyWebServer = (JettyWebServer) this.webServer;
|
JettyWebServer jettyWebServer = (JettyWebServer) this.webServer;
|
||||||
@ -393,9 +398,9 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
|||||||
assertThat(((HttpResponse) requestResult).getFirstHeader("Connection").getValue()).isEqualTo("close");
|
assertThat(((HttpResponse) requestResult).getFirstHeader("Connection").getValue()).isEqualTo("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Ssl getSslSettings(String... enabledProtocols) {
|
private Ssl getSslSettings(String keyStore, String... enabledProtocols) {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore(keyStore);
|
||||||
ssl.setKeyStorePassword("secret");
|
ssl.setKeyStorePassword("secret");
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
||||||
@ -426,6 +431,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void basicSslClasspathKeyStore() throws Exception {
|
void basicSslClasspathKeyStore() throws Exception {
|
||||||
testBasicSslWithKeyStore("classpath:test.jks");
|
testBasicSslWithKeyStore("classpath:test.jks");
|
||||||
}
|
}
|
||||||
@ -479,12 +485,13 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void specificIPAddressWithSslIsNotReverseResolved() throws Exception {
|
void specificIPAddressWithSslIsNotReverseResolved() throws Exception {
|
||||||
JettyServletWebServerFactory factory = getFactory();
|
JettyServletWebServerFactory factory = getFactory();
|
||||||
InetAddress localhost = InetAddress.getLocalHost();
|
InetAddress localhost = InetAddress.getLocalHost();
|
||||||
factory.setAddress(InetAddress.getByAddress(localhost.getAddress()));
|
factory.setAddress(InetAddress.getByAddress(localhost.getAddress()));
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore("classpath:test.jks");
|
||||||
ssl.setKeyStorePassword("secret");
|
ssl.setKeyStorePassword("secret");
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
factory.setSsl(ssl);
|
factory.setSsl(ssl);
|
||||||
|
@ -30,6 +30,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.condition.OS;
|
import org.junit.jupiter.api.condition.OS;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.junit.DisabledOnOs;
|
import org.springframework.boot.testsupport.junit.DisabledOnOs;
|
||||||
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
||||||
import org.springframework.boot.testsupport.ssl.MockPkcs11SecurityProvider;
|
import org.springframework.boot.testsupport.ssl.MockPkcs11SecurityProvider;
|
||||||
@ -53,6 +54,7 @@ class SslServerCustomizerTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void whenHttp2IsNotEnabledServerConnectorHasSslAndHttpConnectionFactories() {
|
void whenHttp2IsNotEnabledServerConnectorHasSslAndHttpConnectionFactories() {
|
||||||
Server server = createCustomizedServer();
|
Server server = createCustomizedServer();
|
||||||
assertThat(server.getConnectors()).hasSize(1);
|
assertThat(server.getConnectors()).hasSize(1);
|
||||||
@ -63,6 +65,7 @@ class SslServerCustomizerTests {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
|
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
|
||||||
disabledReason = "conscrypt doesn't support Linux/macOS aarch64, see https://github.com/google/conscrypt/issues/1051")
|
disabledReason = "conscrypt doesn't support Linux/macOS aarch64, see https://github.com/google/conscrypt/issues/1051")
|
||||||
void whenHttp2IsEnabledServerConnectorsHasSslAlpnH2AndHttpConnectionFactories() {
|
void whenHttp2IsEnabledServerConnectorsHasSslAlpnH2AndHttpConnectionFactories() {
|
||||||
@ -77,6 +80,7 @@ class SslServerCustomizerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
|
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
|
||||||
disabledReason = "conscrypt doesn't support Linux/macOS aarch64, see https://github.com/google/conscrypt/issues/1051")
|
disabledReason = "conscrypt doesn't support Linux/macOS aarch64, see https://github.com/google/conscrypt/issues/1051")
|
||||||
void alpnConnectionFactoryHasNullDefaultProtocolToAllowNegotiationToHttp11() {
|
void alpnConnectionFactoryHasNullDefaultProtocolToAllowNegotiationToHttp11() {
|
||||||
@ -98,11 +102,12 @@ class SslServerCustomizerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void configureSslWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsException() {
|
void configureSslWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsException() {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStoreType("PKCS11");
|
ssl.setKeyStoreType("PKCS11");
|
||||||
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore("classpath:test.jks");
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
assertThatIllegalStateException().isThrownBy(() -> {
|
assertThatIllegalStateException().isThrownBy(() -> {
|
||||||
SslServerCustomizer customizer = new SslServerCustomizer(null, null, null, WebServerSslBundle.get(ssl));
|
SslServerCustomizer customizer = new SslServerCustomizer(null, null, null, WebServerSslBundle.get(ssl));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -39,6 +39,7 @@ import org.springframework.boot.ssl.SslBundle;
|
|||||||
import org.springframework.boot.ssl.SslBundles;
|
import org.springframework.boot.ssl.SslBundles;
|
||||||
import org.springframework.boot.ssl.pem.PemSslStoreBundle;
|
import org.springframework.boot.ssl.pem.PemSslStoreBundle;
|
||||||
import org.springframework.boot.ssl.pem.PemSslStoreDetails;
|
import org.springframework.boot.ssl.pem.PemSslStoreDetails;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
|
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactory;
|
||||||
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests;
|
import org.springframework.boot.web.reactive.server.AbstractReactiveWebServerFactoryTests;
|
||||||
import org.springframework.boot.web.server.PortInUseException;
|
import org.springframework.boot.web.server.PortInUseException;
|
||||||
@ -133,12 +134,14 @@ class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void whenSslIsConfiguredWithAValidAliasARequestSucceeds() {
|
void whenSslIsConfiguredWithAValidAliasARequestSucceeds() {
|
||||||
Mono<String> result = testSslWithAlias("test-alias");
|
Mono<String> result = testSslWithAlias("test-alias");
|
||||||
StepVerifier.create(result).expectNext("Hello World").expectComplete().verify(Duration.ofSeconds(30));
|
StepVerifier.create(result).expectNext("Hello World").expectComplete().verify(Duration.ofSeconds(30));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "1.key", "1.crt", "2.key", "2.crt" })
|
||||||
void whenSslBundleIsUpdatedThenSslIsReloaded() {
|
void whenSslBundleIsUpdatedThenSslIsReloaded() {
|
||||||
DefaultSslBundleRegistry bundles = new DefaultSslBundleRegistry("bundle1", createSslBundle("1.key", "1.crt"));
|
DefaultSslBundleRegistry bundles = new DefaultSslBundleRegistry("bundle1", createSslBundle("1.key", "1.crt"));
|
||||||
Mono<String> result = testSslWithBundle(bundles, "bundle1");
|
Mono<String> result = testSslWithBundle(bundles, "bundle1");
|
||||||
@ -231,9 +234,7 @@ class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor
|
|||||||
|
|
||||||
private static SslBundle createSslBundle(String key, String certificate) {
|
private static SslBundle createSslBundle(String key, String certificate) {
|
||||||
return SslBundle.of(new PemSslStoreBundle(
|
return SslBundle.of(new PemSslStoreBundle(
|
||||||
new PemSslStoreDetails(null, "classpath:org/springframework/boot/web/embedded/netty/" + certificate,
|
new PemSslStoreDetails(null, "classpath:" + certificate, "classpath:" + key), null));
|
||||||
"classpath:org/springframework/boot/web/embedded/netty/" + key),
|
|
||||||
null));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class NoPortNettyReactiveWebServerFactory extends NettyReactiveWebServerFactory {
|
static class NoPortNettyReactiveWebServerFactory extends NettyReactiveWebServerFactory {
|
||||||
|
@ -28,6 +28,7 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
||||||
import org.springframework.boot.testsupport.ssl.MockPkcs11SecurityProvider;
|
import org.springframework.boot.testsupport.ssl.MockPkcs11SecurityProvider;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
@ -71,6 +72,7 @@ class SslConnectorCustomizerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslCiphersConfiguration() throws Exception {
|
void sslCiphersConfiguration() throws Exception {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStore("classpath:test.jks");
|
ssl.setKeyStore("classpath:test.jks");
|
||||||
@ -85,10 +87,11 @@ class SslConnectorCustomizerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslEnabledMultipleProtocolsConfiguration() throws Exception {
|
void sslEnabledMultipleProtocolsConfiguration() throws Exception {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore("classpath:test.jks");
|
||||||
ssl.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
|
ssl.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
|
||||||
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
||||||
Connector connector = this.tomcat.getConnector();
|
Connector connector = this.tomcat.getConnector();
|
||||||
@ -101,10 +104,11 @@ class SslConnectorCustomizerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslEnabledProtocolsConfiguration() throws Exception {
|
void sslEnabledProtocolsConfiguration() throws Exception {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore("classpath:test.jks");
|
||||||
ssl.setEnabledProtocols(new String[] { "TLSv1.2" });
|
ssl.setEnabledProtocols(new String[] { "TLSv1.2" });
|
||||||
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
||||||
Connector connector = this.tomcat.getConnector();
|
Connector connector = this.tomcat.getConnector();
|
||||||
@ -126,11 +130,12 @@ class SslConnectorCustomizerTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void customizeWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsException() {
|
void customizeWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsException() {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStoreType("PKCS11");
|
ssl.setKeyStoreType("PKCS11");
|
||||||
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore("classpath:test.jks");
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
assertThatIllegalStateException().isThrownBy(() -> {
|
assertThatIllegalStateException().isThrownBy(() -> {
|
||||||
SslConnectorCustomizer customizer = new SslConnectorCustomizer(this.logger, this.tomcat.getConnector(),
|
SslConnectorCustomizer customizer = new SslConnectorCustomizer(this.logger, this.tomcat.getConnector(),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -80,6 +80,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
import org.springframework.boot.ssl.DefaultSslBundleRegistry;
|
import org.springframework.boot.ssl.DefaultSslBundleRegistry;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.web.server.PortInUseException;
|
import org.springframework.boot.web.server.PortInUseException;
|
||||||
import org.springframework.boot.web.server.Shutdown;
|
import org.springframework.boot.web.server.Shutdown;
|
||||||
@ -683,11 +684,12 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslWithHttp11Nio2Protocol() throws Exception {
|
void sslWithHttp11Nio2Protocol() throws Exception {
|
||||||
TomcatServletWebServerFactory factory = getFactory();
|
TomcatServletWebServerFactory factory = getFactory();
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
factory.setProtocol(Http11Nio2Protocol.class.getName());
|
factory.setProtocol(Http11Nio2Protocol.class.getName());
|
||||||
factory.setSsl(getSsl(null, "password", "src/test/resources/test.jks"));
|
factory.setSsl(getSsl(null, "password", "classpath:test.jks"));
|
||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -38,7 +38,9 @@ import io.undertow.servlet.api.ServletContainer;
|
|||||||
import jakarta.servlet.ServletRegistration.Dynamic;
|
import jakarta.servlet.ServletRegistration.Dynamic;
|
||||||
import org.apache.hc.client5.http.classic.HttpClient;
|
import org.apache.hc.client5.http.classic.HttpClient;
|
||||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||||
|
import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory;
|
||||||
import org.apache.hc.core5.http.HttpResponse;
|
import org.apache.hc.core5.http.HttpResponse;
|
||||||
|
import org.apache.hc.core5.ssl.SSLContextBuilder;
|
||||||
import org.apache.jasper.servlet.JspServlet;
|
import org.apache.jasper.servlet.JspServlet;
|
||||||
import org.awaitility.Awaitility;
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
@ -46,6 +48,7 @@ import org.junit.jupiter.api.Disabled;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.InOrder;
|
import org.mockito.InOrder;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.web.servlet.ExampleServlet;
|
import org.springframework.boot.testsupport.web.servlet.ExampleServlet;
|
||||||
import org.springframework.boot.web.server.ErrorPage;
|
import org.springframework.boot.web.server.ErrorPage;
|
||||||
import org.springframework.boot.web.server.GracefulShutdownResult;
|
import org.springframework.boot.web.server.GracefulShutdownResult;
|
||||||
@ -55,6 +58,7 @@ import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
|||||||
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
|
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
|
||||||
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests;
|
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||||
import org.springframework.test.util.ReflectionTestUtils;
|
import org.springframework.test.util.ReflectionTestUtils;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -155,7 +159,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void basicSslClasspathKeyStore() throws Exception {
|
void basicSslClasspathKeyStore() throws Exception {
|
||||||
testBasicSslWithKeyStore("classpath:test.jks");
|
testBasicSslWithKeyStore("classpath:org/springframework/boot/web/server/test.jks");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -286,6 +290,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("restricted.jks")
|
||||||
void sslRestrictedProtocolsEmptyCipherFailure() {
|
void sslRestrictedProtocolsEmptyCipherFailure() {
|
||||||
assertThatIOException()
|
assertThatIOException()
|
||||||
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
||||||
@ -294,6 +299,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("restricted.jks")
|
||||||
void sslRestrictedProtocolsECDHETLS1Failure() {
|
void sslRestrictedProtocolsECDHETLS1Failure() {
|
||||||
assertThatIOException()
|
assertThatIOException()
|
||||||
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1" },
|
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1" },
|
||||||
@ -302,18 +308,21 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("restricted.jks")
|
||||||
void sslRestrictedProtocolsECDHESuccess() throws Exception {
|
void sslRestrictedProtocolsECDHESuccess() throws Exception {
|
||||||
testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
||||||
new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" });
|
new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("restricted.jks")
|
||||||
void sslRestrictedProtocolsRSATLS12Success() throws Exception {
|
void sslRestrictedProtocolsRSATLS12Success() throws Exception {
|
||||||
testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
||||||
new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA256" });
|
new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA256" });
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("restricted.jks")
|
||||||
void sslRestrictedProtocolsRSATLS11Failure() {
|
void sslRestrictedProtocolsRSATLS11Failure() {
|
||||||
assertThatIOException()
|
assertThatIOException()
|
||||||
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.1" },
|
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.1" },
|
||||||
@ -374,4 +383,15 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
|||||||
return ((UndertowServletWebServer) this.webServer).getStartLogMessage();
|
return ((UndertowServletWebServer) this.webServer).getStartLogMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testRestrictedSSLProtocolsAndCipherSuites(String[] protocols, String[] ciphers) throws Exception {
|
||||||
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
|
factory.setSsl(getSsl(null, "password", "classpath:restricted.jks", null, protocols, ciphers));
|
||||||
|
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello"));
|
||||||
|
this.webServer.start();
|
||||||
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
|
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build());
|
||||||
|
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory);
|
||||||
|
assertThat(getResponse(getLocalUrl("https", "/hello"), requestFactory)).contains("scheme=https");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2022 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -21,6 +21,7 @@ import java.time.Duration;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.support.GenericApplicationContext;
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@ -32,8 +33,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*/
|
*/
|
||||||
class MustacheViewResolverTests {
|
class MustacheViewResolverTests {
|
||||||
|
|
||||||
private final String prefix = "classpath:/" + getClass().getPackage().getName().replace(".", "/") + "/";
|
|
||||||
|
|
||||||
private final MustacheViewResolver resolver = new MustacheViewResolver();
|
private final MustacheViewResolver resolver = new MustacheViewResolver();
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@ -41,7 +40,7 @@ class MustacheViewResolverTests {
|
|||||||
GenericApplicationContext applicationContext = new GenericApplicationContext();
|
GenericApplicationContext applicationContext = new GenericApplicationContext();
|
||||||
applicationContext.refresh();
|
applicationContext.refresh();
|
||||||
this.resolver.setApplicationContext(applicationContext);
|
this.resolver.setApplicationContext(applicationContext);
|
||||||
this.resolver.setPrefix(this.prefix);
|
this.resolver.setPrefix("classpath:");
|
||||||
this.resolver.setSuffix(".html");
|
this.resolver.setSuffix(".html");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +50,7 @@ class MustacheViewResolverTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||||
void resolveExisting() {
|
void resolveExisting() {
|
||||||
assertThat(this.resolver.resolveViewName("template", null).block(Duration.ofSeconds(30))).isNotNull();
|
assertThat(this.resolver.resolveViewName("template", null).block(Duration.ofSeconds(30))).isNotNull();
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -24,6 +24,7 @@ import com.samskivert.mustache.Mustache;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import reactor.test.StepVerifier;
|
import reactor.test.StepVerifier;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.support.StaticApplicationContext;
|
import org.springframework.context.support.StaticApplicationContext;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||||
@ -38,17 +39,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*/
|
*/
|
||||||
class MustacheViewTests {
|
class MustacheViewTests {
|
||||||
|
|
||||||
private final String templateUrl = "classpath:/" + getClass().getPackage().getName().replace(".", "/")
|
|
||||||
+ "/template.html";
|
|
||||||
|
|
||||||
private final StaticApplicationContext context = new StaticApplicationContext();
|
private final StaticApplicationContext context = new StaticApplicationContext();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||||
void viewResolvesHandlebars() {
|
void viewResolvesHandlebars() {
|
||||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test").build());
|
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test").build());
|
||||||
MustacheView view = new MustacheView();
|
MustacheView view = new MustacheView();
|
||||||
view.setCompiler(Mustache.compiler());
|
view.setCompiler(Mustache.compiler());
|
||||||
view.setUrl(this.templateUrl);
|
view.setUrl("classpath:template.html");
|
||||||
view.setCharset(StandardCharsets.UTF_8.displayName());
|
view.setCharset(StandardCharsets.UTF_8.displayName());
|
||||||
view.setApplicationContext(this.context);
|
view.setApplicationContext(this.context);
|
||||||
view.render(Collections.singletonMap("World", "Spring"), MediaType.TEXT_HTML, exchange)
|
view.render(Collections.singletonMap("World", "Spring"), MediaType.TEXT_HTML, exchange)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.springframework.boot.web.reactive.server;
|
package org.springframework.boot.web.reactive.server;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
@ -54,12 +53,15 @@ import reactor.netty.http.Http11SslContextSpec;
|
|||||||
import reactor.netty.http.client.HttpClient;
|
import reactor.netty.http.client.HttpClient;
|
||||||
import reactor.test.StepVerifier;
|
import reactor.test.StepVerifier;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.ResourcePath;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.web.server.Compression;
|
import org.springframework.boot.web.server.Compression;
|
||||||
import org.springframework.boot.web.server.GracefulShutdownResult;
|
import org.springframework.boot.web.server.GracefulShutdownResult;
|
||||||
import org.springframework.boot.web.server.Http2;
|
import org.springframework.boot.web.server.Http2;
|
||||||
import org.springframework.boot.web.server.Shutdown;
|
import org.springframework.boot.web.server.Shutdown;
|
||||||
import org.springframework.boot.web.server.Ssl;
|
import org.springframework.boot.web.server.Ssl;
|
||||||
import org.springframework.boot.web.server.WebServer;
|
import org.springframework.boot.web.server.WebServer;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
import org.springframework.core.io.buffer.DataBuffer;
|
import org.springframework.core.io.buffer.DataBuffer;
|
||||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||||
@ -165,13 +167,15 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void basicSslFromClassPath() {
|
void basicSslFromClassPath() {
|
||||||
testBasicSslWithKeyStore("classpath:test.jks", "password");
|
testBasicSslWithKeyStore("classpath:test.jks", "password");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void basicSslFromFileSystem() {
|
@WithPackageResources("test.jks")
|
||||||
testBasicSslWithKeyStore("src/test/resources/test.jks", "password");
|
void basicSslFromFileSystem(@ResourcePath("test.jks") String keyStore) {
|
||||||
|
testBasicSslWithKeyStore(keyStore, "password");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +203,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslWithValidAlias() {
|
void sslWithValidAlias() {
|
||||||
String keyStore = "classpath:test.jks";
|
String keyStore = "classpath:test.jks";
|
||||||
String keyPassword = "password";
|
String keyPassword = "password";
|
||||||
@ -228,6 +233,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslWithInvalidAliasFailsDuringStartup() {
|
void sslWithInvalidAliasFailsDuringStartup() {
|
||||||
String keyStore = "classpath:test.jks";
|
String keyStore = "classpath:test.jks";
|
||||||
String keyPassword = "password";
|
String keyPassword = "password";
|
||||||
@ -254,6 +260,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslWantsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
void sslWantsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setClientAuth(Ssl.ClientAuth.WANT);
|
ssl.setClientAuth(Ssl.ClientAuth.WANT);
|
||||||
@ -265,6 +272,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslWantsClientAuthenticationSucceedsWithoutClientCertificate() {
|
void sslWantsClientAuthenticationSucceedsWithoutClientCertificate() {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setClientAuth(Ssl.ClientAuth.WANT);
|
ssl.setClientAuth(Ssl.ClientAuth.WANT);
|
||||||
@ -275,10 +283,10 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
testClientAuthSuccess(ssl, buildTrustAllSslConnector());
|
testClientAuthSuccess(ssl, buildTrustAllSslConnector());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ReactorClientHttpConnector buildTrustAllSslWithClientKeyConnector(String keyStoreFile,
|
protected ReactorClientHttpConnector buildTrustAllSslWithClientKeyConnector(String keyStore,
|
||||||
String keyStorePassword) throws Exception {
|
String keyStorePassword) throws Exception {
|
||||||
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
try (InputStream stream = new FileInputStream("src/test/resources/" + keyStoreFile)) {
|
try (InputStream stream = new ClassPathResource(keyStore).getInputStream()) {
|
||||||
clientKeyStore.load(stream, "secret".toCharArray());
|
clientKeyStore.load(stream, "secret".toCharArray());
|
||||||
}
|
}
|
||||||
KeyManagerFactory clientKeyManagerFactory = KeyManagerFactory
|
KeyManagerFactory clientKeyManagerFactory = KeyManagerFactory
|
||||||
@ -312,6 +320,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslNeedsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
void sslNeedsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setClientAuth(Ssl.ClientAuth.NEED);
|
ssl.setClientAuth(Ssl.ClientAuth.NEED);
|
||||||
@ -323,6 +332,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslNeedsClientAuthenticationFailsWithoutClientCertificate() {
|
void sslNeedsClientAuthenticationFailsWithoutClientCertificate() {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setClientAuth(Ssl.ClientAuth.NEED);
|
ssl.setClientAuth(Ssl.ClientAuth.NEED);
|
||||||
@ -334,6 +344,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem", "test.p12" })
|
||||||
void sslWithPemCertificates() throws Exception {
|
void sslWithPemCertificates() throws Exception {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setClientAuth(Ssl.ClientAuth.NEED);
|
ssl.setClientAuth(Ssl.ClientAuth.NEED);
|
||||||
|
@ -22,6 +22,8 @@ import org.springframework.boot.ssl.SslBundle;
|
|||||||
import org.springframework.boot.ssl.SslBundleKey;
|
import org.springframework.boot.ssl.SslBundleKey;
|
||||||
import org.springframework.boot.ssl.SslOptions;
|
import org.springframework.boot.ssl.SslOptions;
|
||||||
import org.springframework.boot.ssl.SslStoreBundle;
|
import org.springframework.boot.ssl.SslStoreBundle;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.ResourcePath;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
||||||
import org.springframework.boot.testsupport.ssl.MockPkcs11SecurityProvider;
|
import org.springframework.boot.testsupport.ssl.MockPkcs11SecurityProvider;
|
||||||
|
|
||||||
@ -47,6 +49,7 @@ class WebServerSslBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.p12")
|
||||||
void whenFromJksProperties() {
|
void whenFromJksProperties() {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStore("classpath:test.p12");
|
ssl.setKeyStore("classpath:test.p12");
|
||||||
@ -77,11 +80,12 @@ class WebServerSslBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void whenFromJksPropertiesWithPkcs11StoreType() {
|
@WithPackageResources("test.jks")
|
||||||
|
void whenFromJksPropertiesWithPkcs11StoreType(@ResourcePath("test.jks") String keyStorePath) {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStoreType("PKCS11");
|
ssl.setKeyStoreType("PKCS11");
|
||||||
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore(keyStorePath);
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
ssl.setClientAuth(Ssl.ClientAuth.NONE);
|
ssl.setClientAuth(Ssl.ClientAuth.NONE);
|
||||||
assertThatIllegalStateException().isThrownBy(() -> WebServerSslBundle.get(ssl))
|
assertThatIllegalStateException().isThrownBy(() -> WebServerSslBundle.get(ssl))
|
||||||
@ -108,6 +112,7 @@ class WebServerSslBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem", "test-cert-chain.pem" })
|
||||||
void whenFromPemProperties() {
|
void whenFromPemProperties() {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setCertificate("classpath:test-cert.pem");
|
ssl.setCertificate("classpath:test-cert.pem");
|
||||||
@ -135,6 +140,7 @@ class WebServerSslBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test-cert.pem", "test-key.pem", "test.p12" })
|
||||||
void whenPemKeyStoreAndJksTrustStoreProperties() {
|
void whenPemKeyStoreAndJksTrustStoreProperties() {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setCertificate("classpath:test-cert.pem");
|
ssl.setCertificate("classpath:test-cert.pem");
|
||||||
@ -163,6 +169,7 @@ class WebServerSslBundleTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources({ "test.p12", "test-cert-chain.pem" })
|
||||||
void whenJksKeyStoreAndPemTrustStoreProperties() {
|
void whenJksKeyStoreAndPemTrustStoreProperties() {
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setKeyStore("classpath:test.p12");
|
ssl.setKeyStore("classpath:test.p12");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2023 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -21,6 +21,7 @@ import java.net.URI;
|
|||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
||||||
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
|
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
|
||||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||||
@ -86,6 +87,7 @@ class ServletWebServerMvcIntegrationTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "conf.properties", content = "context=/example")
|
||||||
void advancedConfig() throws Exception {
|
void advancedConfig() throws Exception {
|
||||||
this.context = new AnnotationConfigServletWebServerApplicationContext(AdvancedConfig.class);
|
this.context = new AnnotationConfigServletWebServerApplicationContext(AdvancedConfig.class);
|
||||||
doTest(this.context, "/example/spring/hello");
|
doTest(this.context, "/example/spring/hello");
|
||||||
@ -161,7 +163,7 @@ class ServletWebServerMvcIntegrationTests {
|
|||||||
|
|
||||||
@Configuration(proxyBeanMethods = false)
|
@Configuration(proxyBeanMethods = false)
|
||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
@PropertySource("classpath:/org/springframework/boot/web/servlet/context/conf.properties")
|
@PropertySource("classpath:conf.properties")
|
||||||
static class AdvancedConfig {
|
static class AdvancedConfig {
|
||||||
|
|
||||||
private final Environment env;
|
private final Environment env;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2024 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -121,6 +121,8 @@ import org.springframework.boot.ssl.pem.PemSslStoreBundle;
|
|||||||
import org.springframework.boot.ssl.pem.PemSslStoreDetails;
|
import org.springframework.boot.ssl.pem.PemSslStoreDetails;
|
||||||
import org.springframework.boot.system.ApplicationHome;
|
import org.springframework.boot.system.ApplicationHome;
|
||||||
import org.springframework.boot.system.ApplicationTemp;
|
import org.springframework.boot.system.ApplicationTemp;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.ResourcePath;
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||||
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
||||||
@ -426,16 +428,19 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void basicSslFromClassPath() throws Exception {
|
void basicSslFromClassPath() throws Exception {
|
||||||
testBasicSslWithKeyStore("classpath:test.jks");
|
testBasicSslWithKeyStore("classpath:test.jks");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void basicSslFromFileSystem() throws Exception {
|
@WithPackageResources("test.jks")
|
||||||
testBasicSslWithKeyStore("src/test/resources/test.jks");
|
void basicSslFromFileSystem(@ResourcePath("test.jks") String keyStore) throws Exception {
|
||||||
|
testBasicSslWithKeyStore(keyStore);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslDisabled() throws Exception {
|
void sslDisabled() throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
Ssl ssl = getSsl(null, "password", "classpath:test.jks");
|
Ssl ssl = getSsl(null, "password", "classpath:test.jks");
|
||||||
@ -451,9 +456,10 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslGetScheme() throws Exception { // gh-2232
|
void sslGetScheme() throws Exception { // gh-2232
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
factory.setSsl(getSsl(null, "password", "src/test/resources/test.jks"));
|
factory.setSsl(getSsl(null, "password", "classpath:test.jks"));
|
||||||
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello"));
|
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello"));
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
@ -463,9 +469,10 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslKeyAlias() throws Exception {
|
void sslKeyAlias() throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
Ssl ssl = getSsl(null, "password", "test-alias", "src/test/resources/test.jks");
|
Ssl ssl = getSsl(null, "password", "test-alias", "classpath:test.jks");
|
||||||
factory.setSsl(ssl);
|
factory.setSsl(ssl);
|
||||||
ServletRegistrationBean<ExampleServlet> registration = new ServletRegistrationBean<>(
|
ServletRegistrationBean<ExampleServlet> registration = new ServletRegistrationBean<>(
|
||||||
new ExampleServlet(true, false), "/hello");
|
new ExampleServlet(true, false), "/hello");
|
||||||
@ -483,9 +490,10 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslWithInvalidAliasFailsDuringStartup() {
|
void sslWithInvalidAliasFailsDuringStartup() {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
Ssl ssl = getSsl(null, "password", "test-alias-404", "src/test/resources/test.jks");
|
Ssl ssl = getSsl(null, "password", "test-alias-404", "classpath:test.jks");
|
||||||
factory.setSsl(ssl);
|
factory.setSsl(ssl);
|
||||||
ServletRegistrationBean<ExampleServlet> registration = new ServletRegistrationBean<>(
|
ServletRegistrationBean<ExampleServlet> registration = new ServletRegistrationBean<>(
|
||||||
new ExampleServlet(true, false), "/hello");
|
new ExampleServlet(true, false), "/hello");
|
||||||
@ -499,9 +507,10 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void serverHeaderIsDisabledByDefaultWhenUsingSsl() throws Exception {
|
void serverHeaderIsDisabledByDefaultWhenUsingSsl() throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
factory.setSsl(getSsl(null, "password", "src/test/resources/test.jks"));
|
factory.setSsl(getSsl(null, "password", "classpath:test.jks"));
|
||||||
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello"));
|
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello"));
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
@ -516,10 +525,11 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void serverHeaderCanBeCustomizedWhenUsingSsl() throws Exception {
|
void serverHeaderCanBeCustomizedWhenUsingSsl() throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
factory.setServerHeader("MyServer");
|
factory.setServerHeader("MyServer");
|
||||||
factory.setSsl(getSsl(null, "password", "src/test/resources/test.jks"));
|
factory.setSsl(getSsl(null, "password", "classpath:test.jks"));
|
||||||
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello"));
|
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello"));
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
@ -546,14 +556,15 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void pkcs12KeyStoreAndTrustStore() throws Exception {
|
@WithPackageResources("test.p12")
|
||||||
|
void pkcs12KeyStoreAndTrustStore(@ResourcePath("test.p12") File keyStoreFile) throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
factory.setSsl(getSsl(ClientAuth.NEED, null, "classpath:test.p12", "classpath:test.p12", null, null));
|
factory.setSsl(getSsl(ClientAuth.NEED, null, "classpath:test.p12", "classpath:test.p12", null, null));
|
||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
||||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12"));
|
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||||
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
||||||
@ -563,14 +574,15 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void pemKeyStoreAndTrustStore() throws Exception {
|
@WithPackageResources({ "test.p12", "test-cert.pem", "test-key.pem" })
|
||||||
|
void pemKeyStoreAndTrustStore(@ResourcePath("test.p12") File keyStoreFile) throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
factory.setSsl(getSsl("classpath:test-cert.pem", "classpath:test-key.pem"));
|
factory.setSsl(getSsl("classpath:test-cert.pem", "classpath:test-key.pem"));
|
||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
||||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12"));
|
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||||
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
||||||
@ -580,7 +592,8 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void pkcs12KeyStoreAndTrustStoreFromBundle() throws Exception {
|
@WithPackageResources("test.p12")
|
||||||
|
void pkcs12KeyStoreAndTrustStoreFromBundle(@ResourcePath("test.p12") File keyStoreFile) throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
factory.setSsl(Ssl.forBundle("test"));
|
factory.setSsl(Ssl.forBundle("test"));
|
||||||
@ -589,7 +602,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
||||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12"));
|
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||||
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
||||||
@ -599,7 +612,8 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void pemKeyStoreAndTrustStoreFromBundle() throws Exception {
|
@WithPackageResources({ "test.p12", "test-cert.pem", "test-key.pem" })
|
||||||
|
void pemKeyStoreAndTrustStoreFromBundle(@ResourcePath("test.p12") File keyStoreFile) throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
factory.setSsl(Ssl.forBundle("test"));
|
factory.setSsl(Ssl.forBundle("test"));
|
||||||
@ -608,7 +622,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
||||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12"));
|
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||||
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
||||||
@ -618,7 +632,9 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sslNeedsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
@WithPackageResources("test.jks")
|
||||||
|
void sslNeedsClientAuthenticationSucceedsWithClientCertificate(@ResourcePath("test.jks") File keyStoreFile)
|
||||||
|
throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
factory.setRegisterDefaultServlet(true);
|
factory.setRegisterDefaultServlet(true);
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
@ -626,7 +642,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.jks"));
|
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||||
.loadKeyMaterial(keyStore, "password".toCharArray())
|
.loadKeyMaterial(keyStore, "password".toCharArray())
|
||||||
@ -636,6 +652,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslNeedsClientAuthenticationFailsWithoutClientCertificate() throws Exception {
|
void sslNeedsClientAuthenticationFailsWithoutClientCertificate() throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
@ -650,7 +667,9 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void sslWantsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
@WithPackageResources("test.jks")
|
||||||
|
void sslWantsClientAuthenticationSucceedsWithClientCertificate(@ResourcePath("test.jks") File keyStoreFile)
|
||||||
|
throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
factory
|
factory
|
||||||
@ -658,7 +677,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
this.webServer = factory.getWebServer();
|
this.webServer = factory.getWebServer();
|
||||||
this.webServer.start();
|
this.webServer.start();
|
||||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.jks"));
|
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||||
.loadKeyMaterial(keyStore, "password".toCharArray())
|
.loadKeyMaterial(keyStore, "password".toCharArray())
|
||||||
@ -668,6 +687,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithPackageResources("test.jks")
|
||||||
void sslWantsClientAuthenticationSucceedsWithoutClientCertificate() throws Exception {
|
void sslWantsClientAuthenticationSucceedsWithoutClientCertificate() throws Exception {
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
addTestTxtFile(factory);
|
addTestTxtFile(factory);
|
||||||
@ -706,7 +726,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
return getSsl(clientAuth, keyPassword, keyAlias, keyStore, null, null, null);
|
return getSsl(clientAuth, keyPassword, keyAlias, keyStore, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Ssl getSsl(ClientAuth clientAuth, String keyPassword, String keyStore, String trustStore,
|
protected Ssl getSsl(ClientAuth clientAuth, String keyPassword, String keyStore, String trustStore,
|
||||||
String[] supportedProtocols, String[] ciphers) {
|
String[] supportedProtocols, String[] ciphers) {
|
||||||
return getSsl(clientAuth, keyPassword, null, keyStore, trustStore, supportedProtocols, ciphers);
|
return getSsl(clientAuth, keyPassword, null, keyStore, trustStore, supportedProtocols, ciphers);
|
||||||
}
|
}
|
||||||
@ -767,17 +787,6 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
return SslBundle.of(stores);
|
return SslBundle.of(stores);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void testRestrictedSSLProtocolsAndCipherSuites(String[] protocols, String[] ciphers) throws Exception {
|
|
||||||
AbstractServletWebServerFactory factory = getFactory();
|
|
||||||
factory.setSsl(getSsl(null, "password", "src/test/resources/restricted.jks", null, protocols, ciphers));
|
|
||||||
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(true, false), "/hello"));
|
|
||||||
this.webServer.start();
|
|
||||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
|
||||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build());
|
|
||||||
HttpComponentsClientHttpRequestFactory requestFactory = createHttpComponentsRequestFactory(socketFactory);
|
|
||||||
assertThat(getResponse(getLocalUrl("https", "/hello"), requestFactory)).contains("scheme=https");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected HttpComponentsClientHttpRequestFactory createHttpComponentsRequestFactory(
|
protected HttpComponentsClientHttpRequestFactory createHttpComponentsRequestFactory(
|
||||||
SSLConnectionSocketFactory socketFactory) {
|
SSLConnectionSocketFactory socketFactory) {
|
||||||
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
|
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
|
||||||
@ -949,7 +958,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
|||||||
AbstractServletWebServerFactory factory = getFactory();
|
AbstractServletWebServerFactory factory = getFactory();
|
||||||
Ssl ssl = new Ssl();
|
Ssl ssl = new Ssl();
|
||||||
ssl.setEnabled(true);
|
ssl.setEnabled(true);
|
||||||
ssl.setKeyStore("src/test/resources/test.jks");
|
ssl.setKeyStore("src/test/resources/org/springframework/boot/web/server/test.jks");
|
||||||
ssl.setKeyPassword("password");
|
ssl.setKeyPassword("password");
|
||||||
factory.setSsl(ssl);
|
factory.setSsl(ssl);
|
||||||
factory.getSession().setTrackingModes(EnumSet.of(SessionTrackingMode.SSL));
|
factory.getSession().setTrackingModes(EnumSet.of(SessionTrackingMode.SSL));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2022 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -19,6 +19,7 @@ package org.springframework.boot.web.servlet.view;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.context.support.GenericApplicationContext;
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.mock.web.MockServletContext;
|
import org.springframework.mock.web.MockServletContext;
|
||||||
import org.springframework.web.servlet.View;
|
import org.springframework.web.servlet.View;
|
||||||
@ -33,8 +34,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*/
|
*/
|
||||||
class MustacheViewResolverTests {
|
class MustacheViewResolverTests {
|
||||||
|
|
||||||
private final String prefix = "classpath:/" + getClass().getPackage().getName().replace(".", "/") + "/";
|
|
||||||
|
|
||||||
private final MustacheViewResolver resolver = new MustacheViewResolver();
|
private final MustacheViewResolver resolver = new MustacheViewResolver();
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
@ -43,7 +42,7 @@ class MustacheViewResolverTests {
|
|||||||
applicationContext.refresh();
|
applicationContext.refresh();
|
||||||
this.resolver.setApplicationContext(applicationContext);
|
this.resolver.setApplicationContext(applicationContext);
|
||||||
this.resolver.setServletContext(new MockServletContext());
|
this.resolver.setServletContext(new MockServletContext());
|
||||||
this.resolver.setPrefix(this.prefix);
|
this.resolver.setPrefix("classpath:");
|
||||||
this.resolver.setSuffix(".html");
|
this.resolver.setSuffix(".html");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,11 +52,13 @@ class MustacheViewResolverTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||||
void resolveExisting() throws Exception {
|
void resolveExisting() throws Exception {
|
||||||
assertThat(this.resolver.resolveViewName("template", null)).isNotNull();
|
assertThat(this.resolver.resolveViewName("template", null)).isNotNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||||
void setsContentType() throws Exception {
|
void setsContentType() throws Exception {
|
||||||
this.resolver.setContentType("application/octet-stream");
|
this.resolver.setContentType("application/octet-stream");
|
||||||
View view = this.resolver.resolveViewName("template", null);
|
View view = this.resolver.resolveViewName("template", null);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2012-2022 the original author or authors.
|
* Copyright 2012-2025 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -22,6 +22,7 @@ import com.samskivert.mustache.Mustache;
|
|||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
|
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
@ -37,9 +38,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||||||
*/
|
*/
|
||||||
class MustacheViewTests {
|
class MustacheViewTests {
|
||||||
|
|
||||||
private final String templateUrl = "classpath:/" + getClass().getPackage().getName().replace(".", "/")
|
|
||||||
+ "/template.html";
|
|
||||||
|
|
||||||
private final MockHttpServletRequest request = new MockHttpServletRequest();
|
private final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
|
||||||
private final MockHttpServletResponse response = new MockHttpServletResponse();
|
private final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||||
@ -55,10 +53,11 @@ class MustacheViewTests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||||
void viewResolvesHandlebars() throws Exception {
|
void viewResolvesHandlebars() throws Exception {
|
||||||
MustacheView view = new MustacheView();
|
MustacheView view = new MustacheView();
|
||||||
view.setCompiler(Mustache.compiler());
|
view.setCompiler(Mustache.compiler());
|
||||||
view.setUrl(this.templateUrl);
|
view.setUrl("classpath:template.html");
|
||||||
view.setApplicationContext(this.context);
|
view.setApplicationContext(this.context);
|
||||||
view.render(Collections.singletonMap("World", "Spring"), this.request, this.response);
|
view.render(Collections.singletonMap("World", "Spring"), this.request, this.response);
|
||||||
assertThat(this.response.getContentAsString().trim()).isEqualTo("Hello Spring");
|
assertThat(this.response.getContentAsString().trim()).isEqualTo("Hello Spring");
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
org.springframework.boot.env.PropertySourceLoader=\
|
|
||||||
org.springframework.boot.context.config.TestPropertySourceLoader1,\
|
|
||||||
org.springframework.boot.context.config.TestPropertySourceLoader2
|
|
||||||
|
|
||||||
org.springframework.boot.context.config.ConfigDataLocationResolver=\
|
|
||||||
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorIntegrationTests.LocationResolver,\
|
|
||||||
org.springframework.boot.context.config.TestConfigDataBootstrap.LocationResolver,\
|
|
||||||
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegrationTests.LocationResolver
|
|
||||||
|
|
||||||
org.springframework.boot.context.config.ConfigDataLoader=\
|
|
||||||
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorIntegrationTests.Loader,\
|
|
||||||
org.springframework.boot.context.config.TestConfigDataBootstrap.Loader,\
|
|
||||||
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegrationTests.Loader
|
|
@ -1,6 +0,0 @@
|
|||||||
# A comment spanning a complete line
|
|
||||||
class1
|
|
||||||
|
|
||||||
class2 # with comment at the end
|
|
||||||
# Comment with some whitespace in front
|
|
||||||
class3
|
|
@ -1 +0,0 @@
|
|||||||
spring.output.ansi.enabled=never
|
|
@ -1,4 +0,0 @@
|
|||||||
test1=test1
|
|
||||||
#---
|
|
||||||
spring.config.activate.on-profile=other
|
|
||||||
test2=test2
|
|
@ -1 +0,0 @@
|
|||||||
spring.profiles.active=test,other
|
|
@ -1,6 +0,0 @@
|
|||||||
spring.config.import=testbootstrap:test
|
|
||||||
spring.profiles.active=test
|
|
||||||
myprop=igotbound
|
|
||||||
#---
|
|
||||||
spring.config.activate.on-profile=test
|
|
||||||
myprofileprop=igotprofilebound
|
|
@ -1 +0,0 @@
|
|||||||
customdefault=true
|
|
@ -1 +0,0 @@
|
|||||||
my.property=fromdevpropertiesfile
|
|
@ -1 +0,0 @@
|
|||||||
my.value=iwasimported
|
|
@ -1,3 +0,0 @@
|
|||||||
my.import=application-import-with-placeholder-imported
|
|
||||||
#---
|
|
||||||
spring.config.import=classpath:${my.import}.properties
|
|
@ -1 +0,0 @@
|
|||||||
my.value=application-import-with-placeholder-in-earlier-document-imported
|
|
@ -1,6 +0,0 @@
|
|||||||
my.import=application-import-with-placeholder-in-earlier-document-imported
|
|
||||||
#---
|
|
||||||
my.value=should-be-ignored
|
|
||||||
spring.config.activate.on-profile=missing
|
|
||||||
#---
|
|
||||||
spring.config.import=classpath:${my.import}.properties
|
|
@ -1 +0,0 @@
|
|||||||
my.value=application-import-with-placeholder-in-earlier-profile-document-imported
|
|
@ -1,6 +0,0 @@
|
|||||||
my.value=application-import-with-placeholder-in-earlier-profile-document
|
|
||||||
#---
|
|
||||||
my.import=application-import-with-placeholder-in-earlier-profile-document-imported
|
|
||||||
spring.config.activate.on-profile=missing
|
|
||||||
#---
|
|
||||||
spring.config.import=classpath:${my.import}.properties
|
|
@ -1,6 +0,0 @@
|
|||||||
my.import=application-import-with-placeholder-imported
|
|
||||||
#---
|
|
||||||
spring.config.import=classpath:${my.import}.properties
|
|
||||||
#---
|
|
||||||
my.import=badbadbad
|
|
||||||
spring.config.activate.on-profile=missing
|
|
@ -1,2 +0,0 @@
|
|||||||
my.import=application-import-with-placeholder-imported
|
|
||||||
spring.config.import=classpath:${my.import}.properties
|
|
@ -1,2 +0,0 @@
|
|||||||
spring.config.import=classpath:application-import-with-profile-variant-imported-dev.properties
|
|
||||||
my.value=application-import-with-profile-variant-and-direct-profile-import-dev
|
|
@ -1,2 +0,0 @@
|
|||||||
spring.config.import=classpath:application-import-with-profile-variant-imported.properties
|
|
||||||
my.value=application-import-with-profile-variant-and-direct-profile-import
|
|
@ -1 +0,0 @@
|
|||||||
my.value=application-import-with-profile-variant-dev
|
|
@ -1 +0,0 @@
|
|||||||
my.value=application-import-with-profile-variant-imported-dev
|
|
@ -1 +0,0 @@
|
|||||||
my.value=application-import-with-profile-variant-imported
|
|
@ -1,2 +0,0 @@
|
|||||||
spring.config.import=classpath:application-import-with-profile-variant-imported.properties
|
|
||||||
my.value=application-import-with-profile-variant
|
|
@ -1,6 +0,0 @@
|
|||||||
spring.profiles.active=p1
|
|
||||||
spring.profiles.include=p2
|
|
||||||
#---
|
|
||||||
spring.config.activate.on-profile=p2
|
|
||||||
spring.profiles.include=p3
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
spring.profiles.include=p2
|
|
@ -1 +0,0 @@
|
|||||||
spring.profiles.active=test
|
|
@ -1,4 +0,0 @@
|
|||||||
spring:
|
|
||||||
profiles:
|
|
||||||
include:
|
|
||||||
- p
|
|
@ -1,9 +0,0 @@
|
|||||||
spring.profiles.active=p1
|
|
||||||
spring.profiles.include=p2
|
|
||||||
#---
|
|
||||||
myprofile=p4
|
|
||||||
spring.profiles.include=p3,${myprofile}
|
|
||||||
#---
|
|
||||||
myotherprofile=p5
|
|
||||||
spring.profiles.include=${myotherprofile}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
|||||||
spring.profiles.active=p1
|
|
||||||
spring.profiles.include=p2
|
|
||||||
#---
|
|
||||||
spring.profiles.include=p3,p4
|
|
||||||
#---
|
|
||||||
spring.profiles.include=p5
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
spring.profiles.include=specific
|
|
@ -1 +0,0 @@
|
|||||||
bar: spam
|
|
@ -1 +0,0 @@
|
|||||||
my.property=fromotherpropertiesfile
|
|
@ -1 +0,0 @@
|
|||||||
spring.config.import:test:boot
|
|
@ -1,2 +0,0 @@
|
|||||||
spring.profiles.active=p1,p2
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
application-profile-specific-import-with-import-import-p1=true
|
|
@ -1 +0,0 @@
|
|||||||
application-profile-specific-import-with-import-import-p2=true
|
|
@ -1 +0,0 @@
|
|||||||
application-profile-specific-import-with-import-import=true
|
|
@ -1,2 +0,0 @@
|
|||||||
application-profile-specific-import-with-import-p1=true
|
|
||||||
spring.config.import=application-profile-specific-import-with-import-import.properties
|
|
@ -1,2 +0,0 @@
|
|||||||
spring.profiles.active=p1,p2
|
|
||||||
application-profile-specific-import-with-import=true
|
|
@ -1 +0,0 @@
|
|||||||
withnotext=test
|
|
@ -1 +0,0 @@
|
|||||||
spring.main.web-application-type: reactive
|
|
@ -1,6 +0,0 @@
|
|||||||
foo: bucket
|
|
||||||
value: 1234
|
|
||||||
my.property: fromapplicationproperties
|
|
||||||
sample.app.test.prop: *
|
|
||||||
my.placeholder: ${my.fallback}
|
|
||||||
duplicate=properties
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user