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");
|
||||
* 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.MyNamedComponent;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
@ -72,8 +73,9 @@ class BeanDefinitionLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSampleBeansXmlResource
|
||||
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);
|
||||
assertThat(load(loader)).isOne();
|
||||
assertThat(this.registry.containsBean("myXmlComponent")).isTrue();
|
||||
@ -81,8 +83,15 @@ class BeanDefinitionLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "org/springframework/boot/sample-beans.groovy", content = """
|
||||
import org.springframework.boot.sampleconfig.MyComponent;
|
||||
|
||||
beans {
|
||||
myGroovyComponent(MyComponent) {}
|
||||
}
|
||||
""")
|
||||
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);
|
||||
assertThat(load(loader)).isOne();
|
||||
assertThat(this.registry.containsBean("myGroovyComponent")).isTrue();
|
||||
@ -90,8 +99,17 @@ class BeanDefinitionLoaderTests {
|
||||
}
|
||||
|
||||
@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() {
|
||||
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);
|
||||
assertThat(load(loader)).isOne();
|
||||
assertThat(this.registry.containsBean("myGroovyComponent")).isTrue();
|
||||
@ -114,7 +132,8 @@ class BeanDefinitionLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadResourceName() {
|
||||
@WithSampleBeansXmlResource
|
||||
void loadXmlName() {
|
||||
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry,
|
||||
"classpath:org/springframework/boot/sample-beans.xml");
|
||||
assertThat(load(loader)).isOne();
|
||||
@ -122,6 +141,13 @@ class BeanDefinitionLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "org/springframework/boot/sample-beans.groovy", content = """
|
||||
import org.springframework.boot.sampleconfig.MyComponent;
|
||||
|
||||
beans {
|
||||
myGroovyComponent(MyComponent) {}
|
||||
}
|
||||
""")
|
||||
void loadGroovyName() {
|
||||
BeanDefinitionLoader loader = new BeanDefinitionLoader(this.registry,
|
||||
"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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -61,12 +61,14 @@ class SimpleMainTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSampleBeansXmlResource
|
||||
void xmlContext(CapturedOutput output) throws Exception {
|
||||
SpringApplication.main(getArgs("org/springframework/boot/sample-beans.xml"));
|
||||
assertThat(output).contains(SPRING_STARTUP);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSampleBeansXmlResource
|
||||
void mixedContext(CapturedOutput output) throws Exception {
|
||||
SpringApplication.main(getArgs(getClass().getName(), "org/springframework/boot/sample-beans.xml"));
|
||||
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");
|
||||
* 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.predicate.RuntimeHintsPredicates;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@ -47,9 +48,10 @@ class SpringApplicationBannerPrinterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "banner.txt", content = "\uD83D\uDE0D Spring Boot! \uD83D\uDE0D")
|
||||
void shouldUseUtf8() {
|
||||
ResourceLoader resourceLoader = new GenericApplicationContext();
|
||||
Resource resource = resourceLoader.getResource("classpath:/banner-utf8.txt");
|
||||
Resource resource = resourceLoader.getResource("classpath:banner.txt");
|
||||
SpringApplicationBannerPrinter printer = new SpringApplicationBannerPrinter(resourceLoader,
|
||||
new ResourceBanner(resource));
|
||||
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");
|
||||
* 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.convert.ApplicationConversionService;
|
||||
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.OutputCaptureExtension;
|
||||
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
|
||||
@ -226,19 +227,24 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "banner.txt", content = "Running a Test!")
|
||||
void customBanner(CapturedOutput output) {
|
||||
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
|
||||
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!");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "banner.txt", content = """
|
||||
Running a Test!
|
||||
|
||||
${test.property}""")
|
||||
void customBannerWithProperties(CapturedOutput output) {
|
||||
SpringApplication application = spy(new SpringApplication(ExampleConfig.class));
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
this.context = application.run("--spring.banner.location=classpath:test-banner-with-placeholder.txt",
|
||||
"--test.property=123456");
|
||||
this.context = application.run("--test.property=123456");
|
||||
assertThat(output).containsPattern("Running a Test!\\s+123456");
|
||||
}
|
||||
|
||||
@ -289,6 +295,7 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "bindtoapplication.properties", content = "spring.main.banner-mode=off")
|
||||
void triggersConfigFileApplicationListenerBeforeBinding() {
|
||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
@ -540,6 +547,7 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "foo=bucket")
|
||||
void propertiesFileEnhancesEnvironment() {
|
||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
@ -572,6 +580,8 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "my.property=fromapplicationproperties")
|
||||
@WithResource(name = "application-other.properties", content = "my.property=fromotherpropertiesfile")
|
||||
void addProfilesOrderWithProperties() {
|
||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
@ -584,6 +594,7 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "foo=bucket")
|
||||
void emptyCommandLinePropertySourceNotAdded() {
|
||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
@ -814,11 +825,13 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSampleBeansXmlResource
|
||||
@WithResource(name = "application.properties", content = "sample.app.test.prop=*")
|
||||
void wildcardSources() {
|
||||
TestSpringApplication application = new TestSpringApplication();
|
||||
application.getSources().add("classpath*:org/springframework/boot/sample-${sample.app.test.prop}.xml");
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
this.context = application.run();
|
||||
this.context = application.run("--spring.config.location=classpath:/");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -1139,6 +1152,8 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application-withwebapplicationtype.yml",
|
||||
content = "spring.main.web-application-type: reactive")
|
||||
void environmentIsConvertedIfTypeDoesNotMatch() {
|
||||
ConfigurableApplicationContext context = new SpringApplication(ExampleReactiveWebConfig.class)
|
||||
.run("--spring.profiles.active=withwebapplicationtype");
|
||||
@ -1195,6 +1210,7 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "custom-config/application.yml", content = "hello: world")
|
||||
void relaxedBindingShouldWorkBeforeEnvironmentIsPrepared() {
|
||||
SpringApplication application = new SpringApplication(ExampleConfig.class);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
@ -1329,6 +1345,8 @@ class SpringApplicationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "spring-application-config-property-source.properties",
|
||||
content = "test.name=spring-application-config-property-source")
|
||||
void movesConfigClassPropertySourcesToEnd() {
|
||||
SpringApplication application = new SpringApplication(PropertySourceConfig.class);
|
||||
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");
|
||||
* 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.SpringApplicationShutdownHookInstance;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@ -72,14 +73,21 @@ class SpringApplicationBuilderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = """
|
||||
b=file
|
||||
c=file
|
||||
""")
|
||||
@WithResource(name = "application-foo.properties", content = "b=profile-specific-file")
|
||||
void profileAndProperties() {
|
||||
SpringApplicationBuilder application = new SpringApplicationBuilder().sources(ExampleConfig.class)
|
||||
.contextFactory(ApplicationContextFactory.ofContextClass(StaticApplicationContext.class))
|
||||
.profiles("foo")
|
||||
.properties("foo=bar");
|
||||
.properties("a=default");
|
||||
this.context = application.run();
|
||||
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();
|
||||
}
|
||||
|
||||
@ -194,6 +202,7 @@ class SpringApplicationBuilderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application-node.properties", content = "bar=spam")
|
||||
void parentFirstCreationWithProfileAndDefaultArgs() {
|
||||
SpringApplicationBuilder application = new SpringApplicationBuilder(ExampleConfig.class).profiles("node")
|
||||
.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");
|
||||
* 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.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
@ -32,7 +34,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class ImportCandidatesTests {
|
||||
|
||||
private static final String IMPORTS_FILE = "META-INF/spring/org.springframework.boot.context.annotation.ImportCandidatesTests$TestAnnotation.imports";
|
||||
|
||||
@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() {
|
||||
ImportCandidates candidates = ImportCandidates.load(TestAnnotation.class, null);
|
||||
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");
|
||||
* 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.Enabled;
|
||||
import org.springframework.boot.ansi.AnsiOutputEnabledValue;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
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;
|
||||
|
||||
@ -81,11 +79,9 @@ class AnsiOutputApplicationListenerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "spring.output.ansi.enabled=never")
|
||||
void disabledViaApplicationProperties() {
|
||||
ConfigurableEnvironment environment = new StandardEnvironment();
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(environment, "spring.config.name=ansi");
|
||||
SpringApplication application = new SpringApplication(Config.class);
|
||||
application.setEnvironment(environment);
|
||||
application.setWebApplicationType(WebApplicationType.NONE);
|
||||
this.context = application.run();
|
||||
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");
|
||||
* 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.WebApplicationType;
|
||||
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.annotation.Configuration;
|
||||
|
||||
@ -45,9 +46,24 @@ class ConfigDataEnvironmentPostProcessorBootstrapContextIntegrationTests {
|
||||
}
|
||||
|
||||
@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() {
|
||||
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);
|
||||
assertThat(bean).isNotNull();
|
||||
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");
|
||||
* 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.Options;
|
||||
import org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessorIntegrationTests.Config;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
@ -45,6 +46,18 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @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 {
|
||||
|
||||
private SpringApplication application;
|
||||
@ -60,16 +73,14 @@ class ConfigDataEnvironmentPostProcessorImportCombinedWithProfileSpecificIntegra
|
||||
|
||||
@Test
|
||||
void testWithoutProfile() {
|
||||
ConfigurableApplicationContext context = this.application
|
||||
.run("--spring.config.name=configimportwithprofilespecific");
|
||||
ConfigurableApplicationContext context = this.application.run();
|
||||
String value = context.getEnvironment().getProperty("prop");
|
||||
assertThat(value).isEqualTo("fromicwps1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithProfile() {
|
||||
ConfigurableApplicationContext context = this.application
|
||||
.run("--spring.config.name=configimportwithprofilespecific", "--spring.profiles.active=prod");
|
||||
ConfigurableApplicationContext context = this.application.run("--spring.profiles.active=prod");
|
||||
String value = context.getEnvironment().getProperty("prop");
|
||||
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");
|
||||
* 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.SpringApplication;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@ -103,6 +104,8 @@ class ConfigDataEnvironmentPostProcessorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "property=value")
|
||||
@WithResource(name = "application-dev.properties", content = "property=dev-value")
|
||||
void applyToAppliesPostProcessing() {
|
||||
int before = this.environment.getPropertySources().size();
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Collection;
|
||||
@ -28,7 +27,6 @@ import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestInfo;
|
||||
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.properties.bind.Binder;
|
||||
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.support.DefaultConversionService;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
@ -149,8 +148,8 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void processAndApplyAddsImportedSourceToEnvironment(TestInfo info) {
|
||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||
@WithResource(name = "application.properties", content = "spring=boot")
|
||||
void processAndApplyAddsImportedSourceToEnvironment() {
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||
configDataEnvironment.processAndApply();
|
||||
@ -158,8 +157,14 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void processAndApplyOnlyAddsActiveContributors(TestInfo info) {
|
||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||
@WithResource(name = "application.properties", content = """
|
||||
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,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||
configDataEnvironment.processAndApply();
|
||||
@ -180,8 +185,8 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "spring.profiles.default=one,two,three")
|
||||
void processAndApplySetsDefaultProfiles(TestInfo info) {
|
||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||
configDataEnvironment.processAndApply();
|
||||
@ -189,8 +194,8 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void processAndApplySetsActiveProfiles(TestInfo info) {
|
||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||
@WithResource(name = "application.properties", content = "spring.profiles.active=one,two,three")
|
||||
void processAndApplySetsActiveProfiles() {
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||
configDataEnvironment.processAndApply();
|
||||
@ -198,8 +203,11 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void processAndApplySetsActiveProfilesAndProfileGroups(TestInfo info) {
|
||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||
@WithResource(name = "application.properties", content = """
|
||||
spring.profiles.active=one,two,three
|
||||
spring.profiles.group.one=four,five
|
||||
""")
|
||||
void processAndApplySetsActiveProfilesAndProfileGroups() {
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||
configDataEnvironment.processAndApply();
|
||||
@ -207,8 +215,8 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "spring.profiles.active=test")
|
||||
void processAndApplyDoesNotSetProfilesFromIgnoreProfilesContributors(TestInfo info) {
|
||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, null) {
|
||||
|
||||
@ -281,8 +289,8 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "spring=boot")
|
||||
void processAndApplyDoesNotSetProfilesFromIgnoreProfilesContributorsWhenNoProfilesActive(TestInfo info) {
|
||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, null) {
|
||||
|
||||
@ -307,9 +315,8 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Disabled until spring.profiles support is dropped")
|
||||
void processAndApplyWhenHasInvalidPropertyThrowsException() {
|
||||
this.environment.setProperty("spring.profile", "a");
|
||||
this.environment.setProperty("spring.profiles", "a");
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, null);
|
||||
assertThatExceptionOfType(InvalidConfigDataPropertyException.class)
|
||||
@ -317,8 +324,9 @@ class ConfigDataEnvironmentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "custom/config.properties", content = "spring=boot")
|
||||
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();
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, listener);
|
||||
@ -326,14 +334,14 @@ class ConfigDataEnvironmentTests {
|
||||
assertThat(listener.getAddedPropertySources()).hasSize(1);
|
||||
AddedPropertySource addedPropertySource = listener.getAddedPropertySources().get(0);
|
||||
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")
|
||||
.contains(info.getTestMethod().get().getName());
|
||||
.contains("custom/config.properties");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "spring.profiles.active=one,two,three")
|
||||
void processAndApplyWhenHasListenerCallsOnSetProfiles(TestInfo info) {
|
||||
this.environment.setProperty("spring.config.location", getConfigLocation(info));
|
||||
TestConfigDataEnvironmentUpdateListener listener = new TestConfigDataEnvironmentUpdateListener();
|
||||
ConfigDataEnvironment configDataEnvironment = new ConfigDataEnvironment(this.logFactory, this.bootstrapContext,
|
||||
this.environment, this.resourceLoader, this.additionalProfiles, listener);
|
||||
@ -343,17 +351,18 @@ class ConfigDataEnvironmentTests {
|
||||
|
||||
@Test
|
||||
@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() {
|
||||
ResourceLoader resourceLoader = mock(ResourceLoader.class);
|
||||
ClassLoader classLoader = new ClassLoader() {
|
||||
ClassLoader classLoader = new ClassLoader(Thread.currentThread().getContextClassLoader()) {
|
||||
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException {
|
||||
if (SpringFactoriesLoader.FACTORIES_RESOURCE_LOCATION.equals(name)) {
|
||||
return Collections.enumeration(List.of(new File(
|
||||
"src/test/resources/org/springframework/boot/context/config/separate-class-loader-spring.factories")
|
||||
.toURI()
|
||||
.toURL()));
|
||||
return super.getResources("separate-class-loader-spring.factories");
|
||||
}
|
||||
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");
|
||||
* 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.PropertySourceLoader;
|
||||
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.test.io.support.MockSpringFactoriesLoader;
|
||||
|
||||
@ -41,9 +42,11 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class ConfigDataLocationRuntimeHintsTests {
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties", content = "")
|
||||
@WithResource(name = "config/application.properties", content = "")
|
||||
void registerWithDefaultSettings() {
|
||||
RuntimeHints hints = new RuntimeHints();
|
||||
new TestConfigDataLocationRuntimeHints().registerHints(hints, null);
|
||||
new TestConfigDataLocationRuntimeHints().registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
||||
.satisfies(includes("application*.properties", "application*.xml", "application*.yaml", "application*.yml",
|
||||
"config/application*.properties", "config/application*.xml", "config/application*.yaml",
|
||||
@ -51,6 +54,8 @@ class ConfigDataLocationRuntimeHintsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "test.properties")
|
||||
@WithResource(name = "config/test.properties")
|
||||
void registerWithCustomName() {
|
||||
RuntimeHints hints = new RuntimeHints();
|
||||
new TestConfigDataLocationRuntimeHints() {
|
||||
@ -59,13 +64,15 @@ class ConfigDataLocationRuntimeHintsTests {
|
||||
return List.of("test");
|
||||
}
|
||||
|
||||
}.registerHints(hints, null);
|
||||
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
||||
.satisfies(includes("test*.properties", "test*.xml", "test*.yaml", "test*.yml", "config/test*.properties",
|
||||
"config/test*.xml", "config/test*.yaml", "config/test*.yml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties")
|
||||
@WithResource(name = "config/application.properties")
|
||||
void registerWithCustomLocation() {
|
||||
RuntimeHints hints = new RuntimeHints();
|
||||
new TestConfigDataLocationRuntimeHints() {
|
||||
@ -73,13 +80,15 @@ class ConfigDataLocationRuntimeHintsTests {
|
||||
protected List<String> getLocations(ClassLoader classLoader) {
|
||||
return List.of("config/");
|
||||
}
|
||||
}.registerHints(hints, null);
|
||||
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
||||
.satisfies(includes("config/application*.properties", "config/application*.xml", "config/application*.yaml",
|
||||
"config/application*.yml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.conf")
|
||||
@WithResource(name = "config/application.conf")
|
||||
void registerWithCustomExtension() {
|
||||
RuntimeHints hints = new RuntimeHints();
|
||||
new ConfigDataLocationRuntimeHints() {
|
||||
@ -87,7 +96,7 @@ class ConfigDataLocationRuntimeHintsTests {
|
||||
protected List<String> getExtensions(ClassLoader classLoader) {
|
||||
return List.of(".conf");
|
||||
}
|
||||
}.registerHints(hints, null);
|
||||
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||
assertThat(hints.resources().resourcePatternHints()).singleElement()
|
||||
.satisfies(includes("application*.conf", "config/application*.conf"));
|
||||
}
|
||||
@ -100,7 +109,7 @@ class ConfigDataLocationRuntimeHintsTests {
|
||||
protected List<String> getLocations(ClassLoader classLoader) {
|
||||
return List.of(UUID.randomUUID().toString());
|
||||
}
|
||||
}.registerHints(hints, null);
|
||||
}.registerHints(hints, Thread.currentThread().getContextClassLoader());
|
||||
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");
|
||||
* 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.YamlPropertySourceLoader;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
@ -41,32 +42,36 @@ class StandardConfigDataLoaderTests {
|
||||
private final ConfigDataLoaderContext loaderContext = mock(ConfigDataLoaderContext.class);
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.yml", content = """
|
||||
foo: bar
|
||||
---
|
||||
hello: world
|
||||
""")
|
||||
void loadWhenLocationResultsInMultiplePropertySourcesAddsAllToConfigData() throws IOException {
|
||||
ClassPathResource resource = new ClassPathResource("configdata/yaml/application.yml");
|
||||
ClassPathResource resource = new ClassPathResource("application.yml");
|
||||
StandardConfigDataReference reference = new StandardConfigDataReference(
|
||||
ConfigDataLocation.of("classpath:configdata/yaml/application.yml"), null,
|
||||
"classpath:configdata/yaml/application", null, "yml", new YamlPropertySourceLoader());
|
||||
ConfigDataLocation.of("classpath:application.yml"), null, "classpath:application", null, "yml",
|
||||
new YamlPropertySourceLoader());
|
||||
StandardConfigDataResource location = new StandardConfigDataResource(reference, resource);
|
||||
ConfigData configData = this.loader.load(this.loaderContext, location);
|
||||
assertThat(configData.getPropertySources()).hasSize(2);
|
||||
PropertySource<?> source1 = configData.getPropertySources().get(0);
|
||||
PropertySource<?> source2 = configData.getPropertySources().get(1);
|
||||
assertThat(source1.getName())
|
||||
.isEqualTo("Config resource 'class path resource [configdata/yaml/application.yml]' "
|
||||
+ "via location 'classpath:configdata/yaml/application.yml' (document #0)");
|
||||
assertThat(source1.getName()).isEqualTo("Config resource 'class path resource [application.yml]' "
|
||||
+ "via location 'classpath:application.yml' (document #0)");
|
||||
assertThat(source1.getProperty("foo")).isEqualTo("bar");
|
||||
assertThat(source2.getName())
|
||||
.isEqualTo("Config resource 'class path resource [configdata/yaml/application.yml]' "
|
||||
+ "via location 'classpath:configdata/yaml/application.yml' (document #1)");
|
||||
assertThat(source2.getName()).isEqualTo("Config resource 'class path resource [application.yml]' "
|
||||
+ "via location 'classpath:application.yml' (document #1)");
|
||||
assertThat(source2.getProperty("hello")).isEqualTo("world");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "empty.properties")
|
||||
void loadWhenPropertySourceIsEmptyAddsNothingToConfigData() throws IOException {
|
||||
ClassPathResource resource = new ClassPathResource("config/0-empty/testproperties.properties");
|
||||
ClassPathResource resource = new ClassPathResource("empty.properties");
|
||||
StandardConfigDataReference reference = new StandardConfigDataReference(
|
||||
ConfigDataLocation.of("classpath:config/0-empty/testproperties.properties"), null,
|
||||
"config/0-empty/testproperties", null, "properties", new PropertiesPropertySourceLoader());
|
||||
ConfigDataLocation.of("empty.properties"), null, "empty", null, "properties",
|
||||
new PropertiesPropertySourceLoader());
|
||||
StandardConfigDataResource location = new StandardConfigDataResource(reference, resource);
|
||||
ConfigData configData = this.loader.load(this.loaderContext, location);
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.context.config;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
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.env.PropertiesPropertySourceLoader;
|
||||
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.io.ClassPathResource;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
@ -71,23 +74,22 @@ class StandardConfigDataLocationResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "configdata/application.properties")
|
||||
void resolveWhenLocationIsDirectoryResolvesAllMatchingFilesInDirectory() {
|
||||
ConfigDataLocation location = ConfigDataLocation.of("classpath:/configdata/properties/");
|
||||
ConfigDataLocation location = ConfigDataLocation.of("classpath:/configdata/");
|
||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||
assertThat(locations).hasSize(1);
|
||||
assertThat(locations).extracting(Object::toString)
|
||||
.containsExactly("class path resource [configdata/properties/application.properties]");
|
||||
.containsExactly("class path resource [configdata/application.properties]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveWhenLocationIsFileResolvesFile() {
|
||||
ConfigDataLocation location = ConfigDataLocation
|
||||
.of("file:src/test/resources/configdata/properties/application.properties");
|
||||
ConfigDataLocation location = ConfigDataLocation.of("file:configdata/application.properties");
|
||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||
assertThat(locations).hasSize(1);
|
||||
assertThat(locations).extracting(Object::toString)
|
||||
.containsExactly(
|
||||
filePath("src", "test", "resources", "configdata", "properties", "application.properties"));
|
||||
.containsExactly(filePath("configdata", "application.properties"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -143,49 +145,55 @@ class StandardConfigDataLocationResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveWhenLocationIsWildcardDirectoriesRestrictsToOneLevelDeep() {
|
||||
ConfigDataLocation location = ConfigDataLocation.of("file:src/test/resources/config/*/");
|
||||
@WithResource(name = "config/0-empty/testproperties.properties")
|
||||
@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.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||
this.resourceLoader);
|
||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||
assertThat(locations).hasSize(3);
|
||||
assertThat(locations).extracting(Object::toString)
|
||||
.contains(filePath("src", "test", "resources", "config", "1-first", "testproperties.properties"))
|
||||
.contains(filePath("src", "test", "resources", "config", "2-second", "testproperties.properties"))
|
||||
.doesNotContain(filePath("src", "test", "resources", "config", "3-third", "testproperties.properties"));
|
||||
.contains(filePath(resourcesRoot.resolve("config/1-first/testproperties.properties")))
|
||||
.contains(filePath(resourcesRoot.resolve("config/2-second/testproperties.properties")))
|
||||
.doesNotContain(filePath(resourcesRoot.resolve("config/nested/3-third/testproperties.properties")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveWhenLocationIsWildcardDirectoriesSortsAlphabeticallyBasedOnAbsolutePath() {
|
||||
ConfigDataLocation location = ConfigDataLocation.of("file:src/test/resources/config/*/");
|
||||
@WithResource(name = "config/0-empty/testproperties.properties")
|
||||
@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.resolver = new StandardConfigDataLocationResolver(new DeferredLogs(), this.environmentBinder,
|
||||
this.resourceLoader);
|
||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||
assertThat(locations).extracting(Object::toString)
|
||||
.containsExactly(filePath("src", "test", "resources", "config", "0-empty", "testproperties.properties"),
|
||||
filePath("src", "test", "resources", "config", "1-first", "testproperties.properties"),
|
||||
filePath("src", "test", "resources", "config", "2-second", "testproperties.properties"));
|
||||
.containsExactly(filePath(resourcesRoot.resolve("config/0-empty/testproperties.properties")),
|
||||
filePath(resourcesRoot.resolve("config/1-first/testproperties.properties")),
|
||||
filePath(resourcesRoot.resolve("config/2-second/testproperties.properties")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveWhenLocationIsWildcardAndMatchingFilePresentShouldNotFail() {
|
||||
ConfigDataLocation location = ConfigDataLocation.of("optional:file:src/test/resources/a-file/*/");
|
||||
assertThatNoException().isThrownBy(() -> this.resolver.resolve(this.context, location));
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveWhenLocationIsWildcardFilesLoadsAllFilesThatMatch() {
|
||||
@WithResource(name = "config/0-empty/testproperties.properties")
|
||||
@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 resolveWhenLocationIsWildcardFilesLoadsAllFilesThatMatch(@ResourcesRoot Path resourcesRoot) {
|
||||
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);
|
||||
assertThat(locations).hasSize(3);
|
||||
assertThat(locations).extracting(Object::toString)
|
||||
.contains(filePath("src", "test", "resources", "config", "1-first", "testproperties.properties"))
|
||||
.contains(filePath("src", "test", "resources", "config", "2-second", "testproperties.properties"))
|
||||
.doesNotContain(
|
||||
filePath("src", "test", "resources", "config", "nested", "3-third", "testproperties.properties"));
|
||||
.contains(filePath(resourcesRoot.resolve("config/1-first/testproperties.properties")))
|
||||
.contains(filePath(resourcesRoot.resolve("config/2-second/testproperties.properties")))
|
||||
.doesNotContain(filePath(resourcesRoot.resolve("config/nested/3-third/testproperties.properties")));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -208,6 +216,8 @@ class StandardConfigDataLocationResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "config/specific.properties")
|
||||
@WithResource(name = "config/nested/3-third/testproperties.properties")
|
||||
void resolveWhenLocationIsRelativeAndDirectoryResolves() {
|
||||
this.environment.setProperty("spring.config.name", "testproperties");
|
||||
ConfigDataLocation location = ConfigDataLocation.of("nested/3-third/");
|
||||
@ -240,6 +250,7 @@ class StandardConfigDataLocationResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application-props-no-extension", content = "withnoextension=test")
|
||||
void resolveWhenLocationUsesOptionalExtensionSyntaxResolves() throws Exception {
|
||||
ConfigDataLocation location = ConfigDataLocation.of("classpath:/application-props-no-extension[.properties]");
|
||||
List<StandardConfigDataResource> locations = this.resolver.resolve(this.context, location);
|
||||
@ -248,19 +259,20 @@ class StandardConfigDataLocationResolverTests {
|
||||
assertThat(resolved.getResource().getFilename()).endsWith("application-props-no-extension");
|
||||
ConfigData loaded = new StandardConfigDataLoader().load(null, resolved);
|
||||
PropertySource<?> propertySource = loaded.getPropertySources().get(0);
|
||||
assertThat(propertySource.getProperty("withnotext")).isEqualTo("test");
|
||||
assertThat(propertySource.getProperty("withnoextension")).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application-dev.properties")
|
||||
void resolveProfileSpecificReturnsProfileSpecificFiles() {
|
||||
ConfigDataLocation location = ConfigDataLocation.of("classpath:/configdata/properties/");
|
||||
ConfigDataLocation location = ConfigDataLocation.of("classpath:/");
|
||||
Profiles profiles = mock(Profiles.class);
|
||||
given(profiles.iterator()).willReturn(Collections.singletonList("dev").iterator());
|
||||
List<StandardConfigDataResource> locations = this.resolver.resolveProfileSpecific(this.context, location,
|
||||
profiles);
|
||||
assertThat(locations).hasSize(1);
|
||||
assertThat(locations).extracting(Object::toString)
|
||||
.containsExactly("class path resource [configdata/properties/application-dev.properties]");
|
||||
.containsExactly("class path resource [application-dev.properties]");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -297,4 +309,8 @@ class StandardConfigDataLocationResolverTests {
|
||||
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.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.util.Collections;
|
||||
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.system.ApplicationPid;
|
||||
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.OutputCaptureExtension;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
@ -160,8 +165,9 @@ class LoggingApplicationListenerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
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.logger.info("Hello world");
|
||||
assertThat(this.output).contains("Hello world").doesNotContain("???").startsWith("null ").endsWith("BOOTBOOT");
|
||||
@ -178,8 +184,9 @@ class LoggingApplicationListenerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
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.logger.info("Hello world");
|
||||
assertThat(this.output).contains("Hello world").doesNotContain("???").startsWith("null ").endsWith("BOOTBOOT");
|
||||
@ -226,8 +233,9 @@ class LoggingApplicationListenerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
void addLogFileProperty() {
|
||||
addPropertiesToEnvironment(this.context, "logging.config=classpath:logback-nondefault.xml",
|
||||
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml",
|
||||
"logging.file.name=" + this.logFile);
|
||||
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
||||
Log logger = LogFactory.getLog(LoggingApplicationListenerTests.class);
|
||||
@ -248,8 +256,9 @@ class LoggingApplicationListenerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
void addLogPathProperty() {
|
||||
addPropertiesToEnvironment(this.context, "logging.config=classpath:logback-nondefault.xml",
|
||||
addPropertiesToEnvironment(this.context, "logging.config=classpath:nondefault.xml",
|
||||
"logging.file.path=" + this.tempDir);
|
||||
this.listener.initialize(this.context.getEnvironment(), this.context.getClassLoader());
|
||||
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");
|
||||
* 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.PeriodUnit;
|
||||
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.OutputCaptureExtension;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
@ -260,6 +261,21 @@ class ConfigurationPropertiesTests {
|
||||
}
|
||||
|
||||
@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() {
|
||||
removeSystemProperties();
|
||||
load(new Class<?>[] { DefaultsInXmlConfiguration.class });
|
||||
@ -633,6 +649,7 @@ class ConfigurationPropertiesTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "application.properties")
|
||||
void customProtocolResolver() {
|
||||
this.context = new AnnotationConfigApplicationContext();
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.context,
|
||||
@ -1356,7 +1373,7 @@ class ConfigurationPropertiesTests {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties
|
||||
@ImportResource("org/springframework/boot/context/properties/testProperties.xml")
|
||||
@ImportResource("testProperties.xml")
|
||||
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");
|
||||
* 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.params.provider.Arguments;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
@ -52,9 +53,10 @@ class StringToFileConverterTests {
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
@WithResource(name = "com/example/test-file.txt", content = "test content")
|
||||
void convertWhenClasspathPrefixedReturnsFile(ConversionService conversionService) throws IOException {
|
||||
String resource = new ClassPathResource("test-banner.txt", this.getClass().getClassLoader()).getURL().getFile();
|
||||
assertThat(convert(conversionService, "classpath:test-banner.txt").getAbsoluteFile())
|
||||
String resource = new ClassPathResource("com/example/test-file.txt").getURL().getFile();
|
||||
assertThat(convert(conversionService, "classpath:com/example/test-file.txt").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");
|
||||
* 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.analyzer.nounique.TestBean;
|
||||
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.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
@ -38,6 +39,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Andy Wilkinson
|
||||
* @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 {
|
||||
|
||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
@ -78,6 +90,17 @@ class NoUniqueBeanDefinitionFailureAnalyzerTests {
|
||||
}
|
||||
|
||||
@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() {
|
||||
FailureAnalysis failureAnalysis = analyzeFailure(createFailure(XmlConsumer.class));
|
||||
assertThat(failureAnalysis.getDescription()).startsWith("Parameter 0 of constructor in "
|
||||
@ -131,7 +154,7 @@ class NoUniqueBeanDefinitionFailureAnalyzerTests {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ComponentScan(basePackageClasses = TestBean.class)
|
||||
@ImportResource("/org/springframework/boot/diagnostics/analyzer/nounique/producer.xml")
|
||||
@ImportResource("classpath:producer.xml")
|
||||
static class DuplicateBeansProducer {
|
||||
|
||||
@Bean
|
||||
@ -200,7 +223,7 @@ class NoUniqueBeanDefinitionFailureAnalyzerTests {
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ImportResource("/org/springframework/boot/diagnostics/analyzer/nounique/consumer.xml")
|
||||
@ImportResource("classpath:consumer.xml")
|
||||
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");
|
||||
* 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.origin.OriginTrackedValue;
|
||||
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.ClassPathResource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
@ -92,9 +93,10 @@ class OriginTrackedPropertiesLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "malformed-unicode.properties", content = "test-malformed-unicode=properties\\u(026test")
|
||||
void getMalformedUnicodeProperty() {
|
||||
// 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())
|
||||
.withMessageContaining("Malformed \\uxxxx encoding");
|
||||
}
|
||||
@ -326,8 +328,43 @@ class OriginTrackedPropertiesLoaderTests {
|
||||
}
|
||||
|
||||
@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 {
|
||||
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();
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,6 +16,10 @@
|
||||
|
||||
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.util.Collections;
|
||||
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.TextResourceOrigin;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
@ -48,11 +53,12 @@ class OriginTrackedYamlLoaderTests {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
Resource resource = new ClassPathResource("test-yaml.yml", getClass());
|
||||
Resource resource = new ClassPathResource("test-yaml.yml");
|
||||
this.loader = new OriginTrackedYamlLoader(resource);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithTestYamlResource
|
||||
void processSimpleKey() {
|
||||
OriginTrackedValue value = getValue("name");
|
||||
assertThat(value).hasToString("Martin D'vloper");
|
||||
@ -60,6 +66,7 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithTestYamlResource
|
||||
void processMap() {
|
||||
OriginTrackedValue perl = getValue("languages.perl");
|
||||
OriginTrackedValue python = getValue("languages.python");
|
||||
@ -73,6 +80,7 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithTestYamlResource
|
||||
void processCollection() {
|
||||
OriginTrackedValue apple = getValue("foods[0]");
|
||||
OriginTrackedValue orange = getValue("foods[1]");
|
||||
@ -89,6 +97,7 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithTestYamlResource
|
||||
void processMultiline() {
|
||||
OriginTrackedValue education = getValue("education");
|
||||
assertThat(education).hasToString("4 GCSEs\n3 A-Levels\nBSc in the Internet of Things\n");
|
||||
@ -96,6 +105,7 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithTestYamlResource
|
||||
void processListOfMaps() {
|
||||
OriginTrackedValue name = getValue("example.foo[0].name");
|
||||
OriginTrackedValue url = getValue("example.foo[0].url");
|
||||
@ -112,6 +122,7 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithTestYamlResource
|
||||
void processEmptyAndNullValues() {
|
||||
OriginTrackedValue empty = getValue("empty");
|
||||
OriginTrackedValue nullValue = getValue("null-value");
|
||||
@ -122,6 +133,7 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithTestYamlResource
|
||||
void processEmptyListAndMap() {
|
||||
OriginTrackedValue emptymap = getValue("emptymap");
|
||||
OriginTrackedValue emptylist = getValue("emptylist");
|
||||
@ -138,8 +150,15 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "test-empty-yaml.yml", content = """
|
||||
---
|
||||
---
|
||||
|
||||
---
|
||||
---
|
||||
""")
|
||||
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();
|
||||
assertThat(loaded).isEmpty();
|
||||
}
|
||||
@ -165,8 +184,17 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "recursive.yml", content = """
|
||||
&def1
|
||||
*def1: a
|
||||
test:
|
||||
a:
|
||||
spring: 'a'
|
||||
b:
|
||||
boot: 'b'
|
||||
""")
|
||||
void loadWhenRecursiveLoadsYaml() {
|
||||
Resource resource = new ClassPathResource("recursive.yml", getClass());
|
||||
Resource resource = new ClassPathResource("recursive.yml");
|
||||
this.loader = new OriginTrackedYamlLoader(resource);
|
||||
Map<String, Object> loaded = this.loader.load().get(0);
|
||||
assertThat(loaded.get("test.a.spring")).hasToString("a");
|
||||
@ -174,8 +202,16 @@ class OriginTrackedYamlLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "anchors.yml", content = """
|
||||
some:
|
||||
path: &anchor
|
||||
config:
|
||||
key: value
|
||||
anotherpath:
|
||||
<<: *anchor
|
||||
""")
|
||||
void loadWhenUsingAnchors() {
|
||||
Resource resource = new ClassPathResource("anchors.yml", getClass());
|
||||
Resource resource = new ClassPathResource("anchors.yml");
|
||||
this.loader = new OriginTrackedYamlLoader(resource);
|
||||
Map<String, Object> loaded = this.loader.load().get(0);
|
||||
assertThat(loaded.get("some.path.config.key")).hasToString("value");
|
||||
@ -205,4 +241,49 @@ class OriginTrackedYamlLoaderTests {
|
||||
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");
|
||||
* 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.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
@ -41,17 +42,28 @@ class PropertiesPropertySourceLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "test.properties", content = "test=properties")
|
||||
void loadProperties() throws Exception {
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.properties",
|
||||
new ClassPathResource("test-properties.properties", getClass()));
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.properties", new ClassPathResource("test.properties"));
|
||||
PropertySource<?> source = loaded.get(0);
|
||||
assertThat(source.getProperty("test")).isEqualTo("properties");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "test.properties", content = """
|
||||
#---
|
||||
#test
|
||||
blah=hello world
|
||||
bar=baz
|
||||
hello=world
|
||||
#---
|
||||
foo=bar
|
||||
bling=biz
|
||||
#comment1
|
||||
#comment2
|
||||
""")
|
||||
void loadMultiDocumentPropertiesWithSeparatorAtTheBeginningOfFile() throws Exception {
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.properties",
|
||||
new ClassPathResource("multi-document-properties-2.properties", getClass()));
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.properties", new ClassPathResource("test.properties"));
|
||||
assertThat(loaded).hasSize(2);
|
||||
PropertySource<?> source1 = loaded.get(0);
|
||||
PropertySource<?> source2 = loaded.get(1);
|
||||
@ -60,9 +72,20 @@ class PropertiesPropertySourceLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "test.properties", content = """
|
||||
#test
|
||||
blah=hello world
|
||||
bar=baz
|
||||
hello=world
|
||||
#---
|
||||
foo=bar
|
||||
bling=biz
|
||||
#comment1
|
||||
#comment2
|
||||
#---
|
||||
""")
|
||||
void loadMultiDocumentProperties() throws Exception {
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.properties",
|
||||
new ClassPathResource("multi-document-properties.properties", getClass()));
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.properties", new ClassPathResource("test.properties"));
|
||||
assertThat(loaded).hasSize(2);
|
||||
PropertySource<?> source1 = loaded.get(0);
|
||||
PropertySource<?> source2 = loaded.get(1);
|
||||
@ -71,9 +94,22 @@ class PropertiesPropertySourceLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "test.properties", content = """
|
||||
|
||||
#---
|
||||
#test
|
||||
blah=hello world
|
||||
bar=baz
|
||||
hello=world
|
||||
#---
|
||||
#---
|
||||
foo=bar
|
||||
bling=biz
|
||||
#comment1
|
||||
#comment2
|
||||
""")
|
||||
void loadMultiDocumentPropertiesWithEmptyDocument() throws Exception {
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.properties",
|
||||
new ClassPathResource("multi-document-properties-empty.properties", getClass()));
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.properties", new ClassPathResource("test.properties"));
|
||||
assertThat(loaded).hasSize(2);
|
||||
PropertySource<?> source1 = loaded.get(0);
|
||||
PropertySource<?> source2 = loaded.get(1);
|
||||
@ -82,9 +118,15 @@ class PropertiesPropertySourceLoaderTests {
|
||||
}
|
||||
|
||||
@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 {
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.xml",
|
||||
new ClassPathResource("test-xml.xml", getClass()));
|
||||
List<PropertySource<?>> loaded = this.loader.load("test.xml", new ClassPathResource("test.xml"));
|
||||
PropertySource<?> source = loaded.get(0);
|
||||
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");
|
||||
* 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.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
@ -86,8 +87,14 @@ class YamlPropertySourceLoaderTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "test-yaml.yml", content = """
|
||||
a: b
|
||||
---
|
||||
c: d
|
||||
e: f
|
||||
""")
|
||||
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);
|
||||
for (PropertySource<?> source : loaded) {
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -70,6 +70,7 @@ class DataSourceScriptDatabaseInitializerTests
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithDataSqlResource
|
||||
void whenCustomizeIsOverriddenThenDatabasePopulatorIsConfiguredAccordingly() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,15 +16,14 @@
|
||||
|
||||
package org.springframework.boot.json;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.assertj.core.api.InstanceOfAssertFactories;
|
||||
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.assertThatExceptionOfType;
|
||||
@ -192,26 +191,22 @@ abstract class AbstractJsonParserTests {
|
||||
}
|
||||
|
||||
@Test // gh-31868
|
||||
void listWithRepeatedOpenArray() throws IOException {
|
||||
String input = StreamUtils.copyToString(
|
||||
AbstractJsonParserTests.class.getResourceAsStream("repeated-open-array.txt"), StandardCharsets.UTF_8);
|
||||
@WithPackageResources("repeated-open-array.txt")
|
||||
void listWithRepeatedOpenArray(@ResourceContent("repeated-open-array.txt") String input) {
|
||||
assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input))
|
||||
.havingCause()
|
||||
.withMessageContaining("too deeply nested");
|
||||
}
|
||||
|
||||
@Test // gh-31869
|
||||
void largeMalformed() throws IOException {
|
||||
String input = StreamUtils.copyToString(
|
||||
AbstractJsonParserTests.class.getResourceAsStream("large-malformed-json.txt"), StandardCharsets.UTF_8);
|
||||
@WithPackageResources("large-malformed-json.txt")
|
||||
void largeMalformed(@ResourceContent("large-malformed-json.txt") String input) {
|
||||
assertThatExceptionOfType(JsonParseException.class).isThrownBy(() -> this.parser.parseList(input));
|
||||
}
|
||||
|
||||
@Test // gh-32029
|
||||
void deeplyNestedMap() throws IOException {
|
||||
String input = StreamUtils.copyToString(
|
||||
AbstractJsonParserTests.class.getResourceAsStream("deeply-nested-map-json.txt"),
|
||||
StandardCharsets.UTF_8);
|
||||
@WithPackageResources("deeply-nested-map-json.txt")
|
||||
void deeplyNestedMap(@ResourceContent("deeply-nested-map-json.txt") String 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.boot.json;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Tests for {@link GsonJsonParser}.
|
||||
*
|
||||
@ -31,7 +29,7 @@ class GsonJsonParserTests extends AbstractJsonParserTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
void listWithRepeatedOpenArray() throws IOException {
|
||||
void listWithRepeatedOpenArray(String input) {
|
||||
// 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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -52,7 +52,7 @@ class JacksonJsonParserTests extends AbstractJsonParserTests {
|
||||
@Override
|
||||
@Disabled("Jackson's array handling is no longer stack bound so protection has been removed.")
|
||||
// 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");
|
||||
* 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.LoggingSystem;
|
||||
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.OutputCaptureExtension;
|
||||
import org.springframework.util.ClassUtils;
|
||||
@ -123,6 +124,10 @@ class JavaLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "logging-nondefault.properties", content = """
|
||||
handlers = java.util.logging.ConsoleHandler
|
||||
.level = INFO
|
||||
""")
|
||||
void testNonDefaultConfigLocation(CapturedOutput output) {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
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");
|
||||
* 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.PropertyChangeListener;
|
||||
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.util.EnumSet;
|
||||
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.LoggingSystemProperty;
|
||||
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.system.CapturedOutput;
|
||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||
@ -158,16 +163,16 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
void testNonDefaultConfigLocation(CapturedOutput output) {
|
||||
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));
|
||||
this.logger.info("Hello world");
|
||||
Configuration configuration = this.loggingSystem.getConfiguration();
|
||||
assertThat(output).contains("Hello world").contains(tmpDir() + "/tmp.log");
|
||||
assertThat(new File(tmpDir() + "/tmp.log")).doesNotExist();
|
||||
assertThat(configuration.getConfigurationSource().getFile().getAbsolutePath())
|
||||
.contains("log4j2-nondefault.xml");
|
||||
assertThat(configuration.getConfigurationSource().getFile().getAbsolutePath()).contains("nondefault.xml");
|
||||
assertThat(configuration.getWatchManager().getIntervalSeconds()).isEqualTo(30);
|
||||
}
|
||||
|
||||
@ -461,15 +466,18 @@ class Log4J2LoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
@WithOverrideXmlResource
|
||||
void compositeConfigurationWithCustomBaseConfiguration() {
|
||||
this.environment.setProperty("logging.log4j2.config.override", "src/test/resources/log4j2-override.xml");
|
||||
this.loggingSystem.initialize(this.initializationContext, "src/test/resources/log4j2-nondefault.xml", null);
|
||||
this.environment.setProperty("logging.log4j2.config.override", "classpath:override.xml");
|
||||
this.loggingSystem.initialize(this.initializationContext, "classpath:nondefault.xml", null);
|
||||
assertThat(this.loggingSystem.getConfiguration()).isInstanceOf(CompositeConfiguration.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithOverrideXmlResource
|
||||
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);
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,6 +16,10 @@
|
||||
|
||||
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 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.testsupport.classpath.ClassPathExclusions;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.boot.testsupport.logging.ConfigureClasspathToPreferLog4j2;
|
||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@ -93,6 +97,7 @@ class SpringProfileArbiterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProductionProfileXmlResource
|
||||
void profileActive() {
|
||||
this.environment.setActiveProfiles("production");
|
||||
initialize("production-profile.xml");
|
||||
@ -101,6 +106,7 @@ class SpringProfileArbiterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMultiProfileNamesXmlResource
|
||||
void multipleNamesFirstProfileActive() {
|
||||
this.environment.setActiveProfiles("production");
|
||||
initialize("multi-profile-names.xml");
|
||||
@ -109,6 +115,7 @@ class SpringProfileArbiterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMultiProfileNamesXmlResource
|
||||
void multipleNamesSecondProfileActive() {
|
||||
this.environment.setActiveProfiles("test");
|
||||
initialize("multi-profile-names.xml");
|
||||
@ -117,6 +124,7 @@ class SpringProfileArbiterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProductionProfileXmlResource
|
||||
void profileNotActive() {
|
||||
initialize("production-profile.xml");
|
||||
this.logger.trace("Hello");
|
||||
@ -124,6 +132,7 @@ class SpringProfileArbiterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProfileExpressionXmlResource
|
||||
void profileExpressionMatchFirst() {
|
||||
this.environment.setActiveProfiles("production");
|
||||
initialize("profile-expression.xml");
|
||||
@ -132,6 +141,7 @@ class SpringProfileArbiterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProfileExpressionXmlResource
|
||||
void profileExpressionMatchSecond() {
|
||||
this.environment.setActiveProfiles("test");
|
||||
initialize("profile-expression.xml");
|
||||
@ -140,6 +150,7 @@ class SpringProfileArbiterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProfileExpressionXmlResource
|
||||
void profileExpressionNoMatch() {
|
||||
this.environment.setActiveProfiles("development");
|
||||
initialize("profile-expression.xml");
|
||||
@ -148,13 +159,56 @@ class SpringProfileArbiterTests {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private String getPackageResource(String fileName) {
|
||||
String path = ClassUtils.getPackageName(getClass());
|
||||
return "src/test/resources/" + path.replace('.', '/') + "/" + fileName;
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@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");
|
||||
* 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 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;
|
||||
|
||||
/**
|
||||
@ -43,11 +46,17 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class LogbackConfigurationTests {
|
||||
|
||||
@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();
|
||||
LoggerContext context = new LoggerContext();
|
||||
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");
|
||||
assertThat(appender).isInstanceOf(ConsoleAppender.class);
|
||||
Encoder<?> encoder = ((ConsoleAppender<?>) appender).getEncoder();
|
||||
@ -56,11 +65,17 @@ class LogbackConfigurationTests {
|
||||
}
|
||||
|
||||
@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();
|
||||
LoggerContext context = new LoggerContext();
|
||||
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");
|
||||
assertThat(appender).isInstanceOf(FileAppender.class);
|
||||
Encoder<?> encoder = ((FileAppender<?>) appender).getEncoder();
|
||||
@ -69,11 +84,17 @@ class LogbackConfigurationTests {
|
||||
}
|
||||
|
||||
@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();
|
||||
LoggerContext context = new LoggerContext();
|
||||
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");
|
||||
assertThat(appender).isInstanceOf(RollingFileAppender.class);
|
||||
RollingPolicy rollingPolicy = ((RollingFileAppender<?>) appender).getRollingPolicy();
|
||||
@ -82,11 +103,17 @@ class LogbackConfigurationTests {
|
||||
}
|
||||
|
||||
@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();
|
||||
LoggerContext context = new LoggerContext();
|
||||
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");
|
||||
assertThat(appender).isInstanceOf(RollingFileAppender.class);
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -17,6 +17,10 @@
|
||||
package org.springframework.boot.logging.logback;
|
||||
|
||||
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.Modifier;
|
||||
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.testsupport.classpath.ClassPathExclusions;
|
||||
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.OutputCaptureExtension;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
@ -132,16 +137,30 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@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) {
|
||||
initialize(this.initializationContext, "classpath:logback-include-defaults.xml", null);
|
||||
initialize(this.initializationContext, "classpath:include-defaults.xml", null);
|
||||
this.logger.info("Hello world");
|
||||
assertThat(getLineWithText(output, "Hello world")).isEqualTo("[INFO] - Hello world");
|
||||
assertThat(output.toString()).doesNotContain("WARN").doesNotContain("deprecated");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithIncludeBaseXmlResource
|
||||
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");
|
||||
assertThat(getLineWithText(output, "Hello world")).contains(" INFO ").endsWith(": Hello world");
|
||||
assertThat(output.toString()).doesNotContain("WARN").doesNotContain("deprecated");
|
||||
@ -199,10 +218,10 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
void testNonDefaultConfigLocation(CapturedOutput output) {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
initialize(this.initializationContext, "classpath:logback-nondefault.xml",
|
||||
getLogFile(tmpDir() + "/tmp.log", null));
|
||||
initialize(this.initializationContext, "classpath:nondefault.xml", getLogFile(tmpDir() + "/tmp.log", null));
|
||||
this.logger.info("Hello world");
|
||||
assertThat(output).doesNotContain("DEBUG")
|
||||
.contains("Hello world")
|
||||
@ -406,12 +425,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithIncludeBaseXmlResource
|
||||
void testCleanHistoryOnStartPropertyWithXmlConfiguration() {
|
||||
this.environment.setProperty("logging.file.clean-history-on-start", "true");
|
||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||
File file = new File(tmpDir(), "logback-test.log");
|
||||
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");
|
||||
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
||||
assertThat(getRollingPolicy().isCleanHistoryOnStart()).isTrue();
|
||||
@ -444,12 +464,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithIncludeBaseXmlResource
|
||||
void testMaxFileSizePropertyWithXmlConfiguration() {
|
||||
this.environment.setProperty("logging.file.max-size", "100MB");
|
||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||
File file = new File(tmpDir(), "logback-test.log");
|
||||
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");
|
||||
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
||||
assertThat(ReflectionTestUtils.getField(getRollingPolicy(), "maxFileSize")).hasToString("100 MB");
|
||||
@ -468,12 +489,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithIncludeBaseXmlResource
|
||||
void testMaxHistoryPropertyWithXmlConfiguration() {
|
||||
this.environment.setProperty("logging.file.max-history", "30");
|
||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||
File file = new File(tmpDir(), "logback-test.log");
|
||||
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");
|
||||
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
||||
assertThat(getRollingPolicy().getMaxHistory()).isEqualTo(30);
|
||||
@ -506,13 +528,14 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithIncludeBaseXmlResource
|
||||
void testTotalSizeCapPropertyWithXmlConfiguration() {
|
||||
String expectedSize = "101 MB";
|
||||
this.environment.setProperty("logging.file.total-size-cap", expectedSize);
|
||||
LoggingInitializationContext loggingInitializationContext = new LoggingInitializationContext(this.environment);
|
||||
File file = new File(tmpDir(), "logback-test.log");
|
||||
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");
|
||||
assertThat(getLineWithText(file, "Hello world")).contains("INFO");
|
||||
assertThat(ReflectionTestUtils.getField(getRollingPolicy(), "totalSizeCap")).hasToString(expectedSize);
|
||||
@ -546,12 +569,13 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
void initializeShouldSetSystemProperty() {
|
||||
// gh-5491
|
||||
this.loggingSystem.beforeInitialize();
|
||||
this.logger.info("Hidden");
|
||||
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()))
|
||||
.endsWith("example.log");
|
||||
}
|
||||
@ -698,9 +722,23 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@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) {
|
||||
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");
|
||||
assertThat(output).contains("<springProfile> elements cannot be nested within an");
|
||||
}
|
||||
@ -756,9 +794,10 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithIncludeBaseXmlResource
|
||||
void correlationLoggingToConsoleWhenUsingXmlConfiguration(CapturedOutput output) {
|
||||
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"));
|
||||
this.logger.info("Hello world");
|
||||
assertThat(getLineWithText(output, "Hello world"))
|
||||
@ -766,11 +805,12 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithIncludeBaseXmlResource
|
||||
void correlationLoggingToFileWhenUsingFileConfiguration() {
|
||||
this.environment.setProperty(LoggingSystem.EXPECT_CORRELATION_ID_PROPERTY, "true");
|
||||
File file = new File(tmpDir(), "logback-test.log");
|
||||
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"));
|
||||
this.logger.info("Hello world");
|
||||
assertThat(getLineWithText(file, "Hello world"))
|
||||
@ -834,30 +874,55 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@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() {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> initialize(this.initializationContext, "classpath:logback-broken.xml",
|
||||
.isThrownBy(() -> initialize(this.initializationContext, "classpath:broken.xml",
|
||||
getLogFile(tmpDir() + "/tmp.log", null)))
|
||||
.satisfies((ex) -> assertThat(ex.getSuppressed())
|
||||
.hasAtLeastOneElementOfType(DynamicClassLoadingException.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "invalid-format.txt", content = "Not XML")
|
||||
void whenConfigLocationIsNotXmlThenIllegalArgumentExceptionShouldBeThrown() {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> initialize(this.initializationContext, "classpath:logback-invalid-format.txt",
|
||||
.isThrownBy(() -> initialize(this.initializationContext, "classpath:invalid-format.txt",
|
||||
getLogFile(tmpDir() + "/tmp.log", null)))
|
||||
.satisfies((ex) -> assertThat(ex.getCause()).isInstanceOf(JoranException.class)
|
||||
.hasMessageStartingWith("Problem parsing XML document. See previously reported errors"));
|
||||
}
|
||||
|
||||
@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) {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
initialize(this.initializationContext, "classpath:logback-without-extension",
|
||||
getLogFile(tmpDir() + "/tmp.log", null));
|
||||
initialize(this.initializationContext, "classpath:without-extension", getLogFile(tmpDir() + "/tmp.log", null));
|
||||
this.logger.info("No extension and works!");
|
||||
assertThat(output.toString()).contains("No extension and works!");
|
||||
}
|
||||
@ -895,11 +960,12 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNonDefaultXmlResource
|
||||
void applyingSystemPropertiesDoesNotCauseUnwantedStatusWarnings(CapturedOutput output) {
|
||||
this.loggingSystem.beforeInitialize();
|
||||
this.environment.getPropertySources()
|
||||
.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");
|
||||
}
|
||||
|
||||
@ -935,4 +1001,33 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,6 +16,11 @@
|
||||
|
||||
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.LoggerContext;
|
||||
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.boot.context.properties.source.ConfigurationPropertySources;
|
||||
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.OutputCaptureExtension;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
@ -77,6 +84,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProductionProfileXmlResource
|
||||
void profileActive() throws Exception {
|
||||
this.environment.setActiveProfiles("production");
|
||||
initialize("production-profile.xml");
|
||||
@ -85,6 +93,20 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@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 {
|
||||
this.environment.setActiveProfiles("production");
|
||||
initialize("profile-in-include.xml");
|
||||
@ -93,6 +115,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMultiProfileNamesXmlResource
|
||||
void multipleNamesFirstProfileActive() throws Exception {
|
||||
this.environment.setActiveProfiles("production");
|
||||
initialize("multi-profile-names.xml");
|
||||
@ -101,6 +124,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMultiProfileNamesXmlResource
|
||||
void multipleNamesSecondProfileActive() throws Exception {
|
||||
this.environment.setActiveProfiles("test");
|
||||
initialize("multi-profile-names.xml");
|
||||
@ -109,6 +133,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProductionProfileXmlResource
|
||||
void profileNotActive() throws Exception {
|
||||
initialize("production-profile.xml");
|
||||
this.logger.trace("Hello");
|
||||
@ -116,6 +141,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProfileExpressionXmlResource
|
||||
void profileExpressionMatchFirst() throws Exception {
|
||||
this.environment.setActiveProfiles("production");
|
||||
initialize("profile-expression.xml");
|
||||
@ -124,6 +150,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProfileExpressionXmlResource
|
||||
void profileExpressionMatchSecond() throws Exception {
|
||||
this.environment.setActiveProfiles("test");
|
||||
initialize("profile-expression.xml");
|
||||
@ -132,6 +159,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithProfileExpressionXmlResource
|
||||
void profileExpressionNoMatch() throws Exception {
|
||||
this.environment.setActiveProfiles("development");
|
||||
initialize("profile-expression.xml");
|
||||
@ -140,26 +168,31 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNestedXmlResource
|
||||
void profileNestedActiveActive() throws Exception {
|
||||
doTestNestedProfile(true, "outer", "inner");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNestedXmlResource
|
||||
void profileNestedActiveNotActive() throws Exception {
|
||||
doTestNestedProfile(false, "outer");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNestedXmlResource
|
||||
void profileNestedNotActiveActive() throws Exception {
|
||||
doTestNestedProfile(false, "inner");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithNestedXmlResource
|
||||
void profileNestedNotActiveNotActive() throws Exception {
|
||||
doTestNestedProfile(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyXmlResource
|
||||
void springProperty() throws Exception {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=test");
|
||||
initialize("property.xml");
|
||||
@ -167,6 +200,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyXmlResource
|
||||
void relaxedSpringProperty() throws Exception {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.EXAMPLE_PROPERTY=test");
|
||||
ConfigurationPropertySources.attach(this.environment);
|
||||
@ -175,30 +209,35 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyXmlResource
|
||||
void springPropertyNoValue() throws Exception {
|
||||
initialize("property.xml");
|
||||
assertThat(this.context.getProperty("SIMPLE")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyXmlResource
|
||||
void relaxedSpringPropertyNoValue() throws Exception {
|
||||
initialize("property.xml");
|
||||
assertThat(this.context.getProperty("MINE")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyDefaultValueXmlResource
|
||||
void springPropertyWithDefaultValue() throws Exception {
|
||||
initialize("property-default-value.xml");
|
||||
assertThat(this.context.getProperty("SIMPLE")).isEqualTo("foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyDefaultValueXmlResource
|
||||
void relaxedSpringPropertyWithDefaultValue() throws Exception {
|
||||
initialize("property-default-value.xml");
|
||||
assertThat(this.context.getProperty("MINE")).isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyInIfXmlResource
|
||||
void springPropertyInIfWhenTrue() throws Exception {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=true");
|
||||
initialize("property-in-if.xml");
|
||||
@ -206,6 +245,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyInIfXmlResource
|
||||
void springPropertyInIfWhenFalse() throws Exception {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=false");
|
||||
initialize("property-in-if.xml");
|
||||
@ -213,6 +253,19 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@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 {
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, "my.example-property=test");
|
||||
initialize("property-in-include.xml");
|
||||
@ -220,6 +273,7 @@ class SpringBootJoranConfiguratorTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPropertyXmlResource
|
||||
void addsAotContributionToContextDuringAotProcessing() throws Exception {
|
||||
withSystemProperty("spring.aot.processing", "true", () -> {
|
||||
initialize("property.xml");
|
||||
@ -253,7 +307,8 @@ class SpringBootJoranConfiguratorTests {
|
||||
|
||||
private void initialize(String config) throws JoranException {
|
||||
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 {
|
||||
@ -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");
|
||||
* 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.pem.PemSslStoreBundle;
|
||||
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.core.codec.CharSequenceEncoder;
|
||||
import org.springframework.core.codec.StringDecoder;
|
||||
@ -156,91 +158,107 @@ class NettyRSocketServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void tcpTransportBasicSslFromClassPath() {
|
||||
testBasicSslWithKeyStore("classpath:test.jks", "password", Transport.TCP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void tcpTransportBasicSslFromFileSystem() {
|
||||
testBasicSslWithKeyStore("src/test/resources/test.jks", "password", Transport.TCP);
|
||||
@WithPackageResources("test.jks")
|
||||
void tcpTransportBasicSslFromFileSystem(@ResourcePath("test.jks") String keyStore) {
|
||||
testBasicSslWithKeyStore(keyStore, "password", Transport.TCP);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void websocketTransportBasicSslFromClassPath() {
|
||||
testBasicSslWithKeyStore("classpath:test.jks", "password", Transport.WEBSOCKET);
|
||||
}
|
||||
|
||||
@Test
|
||||
void websocketTransportBasicSslFromFileSystem() {
|
||||
testBasicSslWithKeyStore("src/test/resources/test.jks", "password", Transport.WEBSOCKET);
|
||||
@WithPackageResources("test.jks")
|
||||
void websocketTransportBasicSslFromFileSystem(@ResourcePath("test.jks") String keyStore) {
|
||||
testBasicSslWithKeyStore(keyStore, "password", Transport.WEBSOCKET);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void tcpTransportBasicSslCertificateFromClassPath() {
|
||||
testBasicSslWithPemCertificate("classpath:test-cert.pem", "classpath:test-key.pem", "classpath:test-cert.pem",
|
||||
Transport.TCP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void tcpTransportBasicSslCertificateFromFileSystem() {
|
||||
testBasicSslWithPemCertificate("src/test/resources/test-cert.pem", "src/test/resources/test-key.pem",
|
||||
"src/test/resources/test-cert.pem", Transport.TCP);
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void tcpTransportBasicSslCertificateFromFileSystem(@ResourcePath("test-cert.pem") String testCert,
|
||||
@ResourcePath("test-key.pem") String testKey) {
|
||||
testBasicSslWithPemCertificate(testCert, testKey, testCert, Transport.TCP);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void websocketTransportBasicSslCertificateFromClassPath() {
|
||||
testBasicSslWithPemCertificate("classpath:test-cert.pem", "classpath:test-key.pem", "classpath:test-cert.pem",
|
||||
Transport.WEBSOCKET);
|
||||
}
|
||||
|
||||
@Test
|
||||
void websocketTransportBasicSslCertificateFromFileSystem() {
|
||||
testBasicSslWithPemCertificate("src/test/resources/test-cert.pem", "src/test/resources/test-key.pem",
|
||||
"src/test/resources/test-cert.pem", Transport.WEBSOCKET);
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void websocketTransportBasicSslCertificateFromFileSystem(@ResourcePath("test-cert.pem") String testCert,
|
||||
@ResourcePath("test-key.pem") String testKey) {
|
||||
testBasicSslWithPemCertificate(testCert, testKey, testCert, Transport.WEBSOCKET);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void tcpTransportBasicSslFromClassPathWithBundle() {
|
||||
testBasicSslWithKeyStoreFromBundle("classpath:test.jks", "password", Transport.TCP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void tcpTransportBasicSslFromFileSystemWithBundle() {
|
||||
testBasicSslWithKeyStoreFromBundle("src/test/resources/test.jks", "password", Transport.TCP);
|
||||
@WithPackageResources("test.jks")
|
||||
void tcpTransportBasicSslFromFileSystemWithBundle(@ResourcePath("test.jks") String keyStore) {
|
||||
testBasicSslWithKeyStoreFromBundle(keyStore, "password", Transport.TCP);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void websocketTransportBasicSslFromClassPathWithBundle() {
|
||||
testBasicSslWithKeyStoreFromBundle("classpath:test.jks", "password", Transport.WEBSOCKET);
|
||||
}
|
||||
|
||||
@Test
|
||||
void websocketTransportBasicSslFromFileSystemWithBundle() {
|
||||
testBasicSslWithKeyStoreFromBundle("src/test/resources/test.jks", "password", Transport.WEBSOCKET);
|
||||
@WithPackageResources("test.jks")
|
||||
void websocketTransportBasicSslFromFileSystemWithBundle(@ResourcePath("test.jks") String keyStore) {
|
||||
testBasicSslWithKeyStoreFromBundle(keyStore, "password", Transport.WEBSOCKET);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void tcpTransportBasicSslCertificateFromClassPathWithBundle() {
|
||||
testBasicSslWithPemCertificateFromBundle("classpath:test-cert.pem", "classpath:test-key.pem",
|
||||
"classpath:test-cert.pem", Transport.TCP);
|
||||
}
|
||||
|
||||
@Test
|
||||
void tcpTransportBasicSslCertificateFromFileSystemWithBundle() {
|
||||
testBasicSslWithPemCertificateFromBundle("src/test/resources/test-cert.pem", "src/test/resources/test-key.pem",
|
||||
"src/test/resources/test-cert.pem", Transport.TCP);
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void tcpTransportBasicSslCertificateFromFileSystemWithBundle(@ResourcePath("test-cert.pem") String testCert,
|
||||
@ResourcePath("test-key.pem") String testKey) {
|
||||
testBasicSslWithPemCertificateFromBundle(testCert, testKey, testCert, Transport.TCP);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void websocketTransportBasicSslCertificateFromClassPathWithBundle() {
|
||||
testBasicSslWithPemCertificateFromBundle("classpath:test-cert.pem", "classpath:test-key.pem",
|
||||
"classpath:test-cert.pem", Transport.WEBSOCKET);
|
||||
}
|
||||
|
||||
@Test
|
||||
void websocketTransportBasicSslCertificateFromFileSystemWithBundle() {
|
||||
testBasicSslWithPemCertificateFromBundle("src/test/resources/test-cert.pem", "src/test/resources/test-key.pem",
|
||||
"src/test/resources/test-cert.pem", Transport.WEBSOCKET);
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void websocketTransportBasicSslCertificateFromFileSystemWithBundle(@ResourcePath("test-cert.pem") String testCert,
|
||||
@ResourcePath("test-key.pem") String testKey) {
|
||||
testBasicSslWithPemCertificateFromBundle(testCert, testKey, testCert, Transport.WEBSOCKET);
|
||||
}
|
||||
|
||||
private void checkEchoRequest() {
|
||||
@ -318,7 +336,7 @@ class NettyRSocketServerFactoryTests {
|
||||
NettyRSocketServerFactory factory = getFactory();
|
||||
factory.setTransport(Transport.TCP);
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("classpath:test.jks");
|
||||
ssl.setKeyStore("classpath:org/springframework/boot/rsocket/netty/test.jks");
|
||||
ssl.setKeyPassword("password");
|
||||
factory.setSsl(ssl);
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,10 +16,15 @@
|
||||
|
||||
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 org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
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> {
|
||||
|
||||
@Test
|
||||
@WithSchemaSqlResource
|
||||
@WithDataSqlResource
|
||||
void whenDatabaseIsInitializedThenSchemaAndDataScriptsAreApplied() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||
@ -55,6 +62,7 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithDataSqlResource
|
||||
void whenContinueOnErrorIsFalseThenInitializationFailsOnError() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
settings.setDataLocations(Arrays.asList("data.sql"));
|
||||
@ -64,6 +72,7 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithDataSqlResource
|
||||
void whenContinueOnErrorIsTrueThenInitializationDoesNotFailOnError() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
settings.setContinueOnError(true);
|
||||
@ -112,6 +121,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSchemaSqlResource
|
||||
@WithDataSqlResource
|
||||
void whenModeIsNeverThenEmbeddedDatabaseIsNotInitialized() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||
@ -123,6 +134,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSchemaSqlResource
|
||||
@WithDataSqlResource
|
||||
void whenModeIsNeverThenStandaloneDatabaseIsNotInitialized() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||
@ -134,6 +147,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSchemaSqlResource
|
||||
@WithDataSqlResource
|
||||
void whenModeIsEmbeddedThenEmbeddedDatabaseIsInitialized() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||
@ -145,6 +160,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSchemaSqlResource
|
||||
@WithDataSqlResource
|
||||
void whenModeIsEmbeddedThenStandaloneDatabaseIsNotInitialized() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||
@ -156,6 +173,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSchemaSqlResource
|
||||
@WithDataSqlResource
|
||||
void whenModeIsAlwaysThenEmbeddedDatabaseIsInitialized() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
settings.setSchemaLocations(Arrays.asList("schema.sql"));
|
||||
@ -167,6 +186,8 @@ public abstract class AbstractScriptDatabaseInitializerTests<T extends AbstractS
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithSchemaSqlResource
|
||||
@WithDataSqlResource
|
||||
void whenModeIsAlwaysThenStandaloneDatabaseIsInitialized() {
|
||||
DatabaseInitializationSettings settings = new DatabaseInitializationSettings();
|
||||
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);
|
||||
|
||||
@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.springframework.boot.io.ApplicationResourceLoader;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
@ -77,6 +78,7 @@ class JksSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void whenHasKeyStoreLocation() {
|
||||
JksSslStoreDetails keyStoreDetails = JksSslStoreDetails.forLocation("classpath:test.jks")
|
||||
.withPassword("secret");
|
||||
@ -86,6 +88,7 @@ class JksSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void getTrustStoreWithLocations() {
|
||||
JksSslStoreDetails keyStoreDetails = null;
|
||||
JksSslStoreDetails trustStoreDetails = JksSslStoreDetails.forLocation("classpath:test.jks")
|
||||
@ -95,6 +98,7 @@ class JksSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void whenHasKeyStoreType() {
|
||||
JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails("jks", null, "classpath:test.jks", "secret");
|
||||
JksSslStoreDetails trustStoreDetails = null;
|
||||
@ -103,6 +107,7 @@ class JksSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void whenHasTrustStoreType() {
|
||||
JksSslStoreDetails keyStoreDetails = null;
|
||||
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails("jks", null, "classpath:test.jks", "secret");
|
||||
@ -111,6 +116,7 @@ class JksSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void whenHasKeyStoreProvider() {
|
||||
JksSslStoreDetails keyStoreDetails = new JksSslStoreDetails(null, "com.example.KeyStoreProvider",
|
||||
"classpath:test.jks", "secret");
|
||||
@ -120,6 +126,7 @@ class JksSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void whenHasTrustStoreProvider() {
|
||||
JksSslStoreDetails trustStoreDetails = new JksSslStoreDetails(null, "com.example.KeyStoreProvider",
|
||||
"classpath:test.jks", "secret");
|
||||
@ -137,6 +144,7 @@ class JksSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test.p12", "test.jks" })
|
||||
void whenLocationsAreBase64Encoded() throws IOException {
|
||||
JksSslStoreDetails keyStoreDetails = JksSslStoreDetails.forLocation(encodeFileContent("classpath:test.p12"))
|
||||
.withPassword("secret");
|
||||
@ -169,6 +177,7 @@ class JksSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void usesResourceLoader() {
|
||||
JksSslStoreDetails keyStoreDetails = null;
|
||||
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");
|
||||
* 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.springframework.boot.io.ApplicationResourceLoader;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
|
||||
@ -37,6 +38,7 @@ import static org.mockito.Mockito.spy;
|
||||
class LoadedPemSslStoreTests {
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-key.pem")
|
||||
void certificatesAreLoadedLazily() {
|
||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
||||
.withPrivateKey("classpath:test-key.pem");
|
||||
@ -45,6 +47,7 @@ class LoadedPemSslStoreTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-cert.pem")
|
||||
void privateKeyIsLoadedLazily() {
|
||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||
.withPrivateKey("classpath:missing-test-key.pem");
|
||||
@ -53,6 +56,7 @@ class LoadedPemSslStoreTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-key.pem")
|
||||
void withAliasIsLazy() {
|
||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
||||
.withPrivateKey("classpath:test-key.pem");
|
||||
@ -61,6 +65,7 @@ class LoadedPemSslStoreTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-key.pem")
|
||||
void withPasswordIsLazy() {
|
||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:missing-test-cert.pem")
|
||||
.withPrivateKey("classpath:test-key.pem");
|
||||
@ -69,6 +74,7 @@ class LoadedPemSslStoreTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-cert.pem")
|
||||
void usesResourceLoader() {
|
||||
PemSslStoreDetails details = PemSslStoreDetails.forCertificate("classpath:test-cert.pem");
|
||||
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");
|
||||
* 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.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -35,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
class PemCertificateParserTests {
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-cert.pem")
|
||||
void parseCertificate() throws Exception {
|
||||
List<X509Certificate> certificates = PemCertificateParser.parse(read("test-cert.pem"));
|
||||
assertThat(certificates).isNotNull();
|
||||
@ -43,6 +45,7 @@ class PemCertificateParserTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-cert-chain.pem")
|
||||
void parseCertificateChain() throws Exception {
|
||||
List<X509Certificate> certificates = PemCertificateParser.parse(read("test-cert-chain.pem"));
|
||||
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");
|
||||
* 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.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.DefaultResourceLoader;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
@ -51,6 +53,7 @@ class PemContentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-cert-chain.pem")
|
||||
void getCertificateReturnsCertificates() throws Exception {
|
||||
PemContent content = PemContent.load(contentFromClasspath("/test-cert-chain.pem"),
|
||||
new ApplicationResourceLoader());
|
||||
@ -69,9 +72,9 @@ class PemContentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("dsa.key")
|
||||
void getPrivateKeyReturnsPrivateKey() throws Exception {
|
||||
PemContent content = PemContent.load(contentFromClasspath("/org/springframework/boot/web/server/pkcs8/dsa.key"),
|
||||
new ApplicationResourceLoader());
|
||||
PemContent content = PemContent.load(contentFromClasspath("dsa.key"), new ApplicationResourceLoader());
|
||||
PrivateKey privateKey = content.getPrivateKey();
|
||||
assertThat(privateKey).isNotNull();
|
||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||
@ -122,6 +125,7 @@ class PemContentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-cert.pem")
|
||||
void loadWithStringWhenClasspathLocationReturnsContent() throws IOException {
|
||||
String actual = PemContent.load("classpath:test-cert.pem", new ApplicationResourceLoader()).toString();
|
||||
String expected = contentFromClasspath("test-cert.pem");
|
||||
@ -129,21 +133,24 @@ class PemContentTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadWithStringWhenFileLocationReturnsContent() throws IOException {
|
||||
String actual = PemContent.load("src/test/resources/test-cert.pem", new ApplicationResourceLoader()).toString();
|
||||
@WithPackageResources("test-cert.pem")
|
||||
void loadWithStringWhenFileLocationReturnsContent(@ResourcePath("test-cert.pem") String testCert)
|
||||
throws IOException {
|
||||
String actual = PemContent.load(testCert, new ApplicationResourceLoader()).toString();
|
||||
String expected = contentFromClasspath("test-cert.pem");
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void loadWithPathReturnsContent() throws IOException {
|
||||
Path path = Path.of("src/test/resources/test-cert.pem");
|
||||
String actual = PemContent.load(path).toString();
|
||||
@WithPackageResources("test-cert.pem")
|
||||
void loadWithPathReturnsContent(@ResourcePath("test-cert.pem") Path testCert) throws IOException {
|
||||
String actual = PemContent.load(testCert).toString();
|
||||
String expected = contentFromClasspath("test-cert.pem");
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test-cert.pem")
|
||||
void loadWithResourceLoaderUsesResourceLoader() throws IOException {
|
||||
ResourceLoader resourceLoader = spy(new DefaultResourceLoader());
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -47,36 +47,25 @@ class PemPrivateKeyParserTests {
|
||||
"rsa.key, RSA",
|
||||
"rsa-pss.key, RSASSA-PSS"
|
||||
})
|
||||
// @formatter:on
|
||||
// @formatter:on
|
||||
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.getFormat()).isEqualTo("PKCS#8");
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo(algorithm);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
// @formatter:off
|
||||
@CsvSource({
|
||||
"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));
|
||||
@Test
|
||||
void shouldParseTraditionalPkcs1() throws IOException {
|
||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("pkcs1/rsa.key"));
|
||||
assertThat(privateKey).isNotNull();
|
||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo(algorithm);
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo("RSA");
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
// @formatter:off
|
||||
@ValueSource(strings = {
|
||||
"dsa.key"
|
||||
})
|
||||
// @formatter:on
|
||||
void shouldNotParseUnsupportedTraditionalPkcs1(String file) {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs1/" + file)))
|
||||
@Test
|
||||
void shouldNotParseUnsupportedTraditionalPkcs1() {
|
||||
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs1/dsa.key")))
|
||||
.withMessageContaining("Missing private key or unrecognized format");
|
||||
}
|
||||
|
||||
@ -94,9 +83,9 @@ class PemPrivateKeyParserTests {
|
||||
"secp384r1.key, secp384r1, 1.3.132.0.34",
|
||||
"secp521r1.key, secp521r1, 1.3.132.0.35"
|
||||
})
|
||||
// @formatter:on
|
||||
// @formatter:on
|
||||
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.getFormat()).isEqualTo("PKCS#8");
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo("EC");
|
||||
@ -115,8 +104,7 @@ class PemPrivateKeyParserTests {
|
||||
})
|
||||
// @formatter:on
|
||||
void shouldNotParseUnsupportedEcPkcs8(String file) {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs8/" + file)))
|
||||
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs8/" + file)))
|
||||
.withMessageContaining("Missing private key or unrecognized format");
|
||||
}
|
||||
|
||||
@ -128,7 +116,7 @@ class PemPrivateKeyParserTests {
|
||||
})
|
||||
// @formatter:on
|
||||
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.getFormat()).isEqualTo("PKCS#8");
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo("EdDSA");
|
||||
@ -142,7 +130,7 @@ class PemPrivateKeyParserTests {
|
||||
})
|
||||
// @formatter:on
|
||||
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.getFormat()).isEqualTo("PKCS#8");
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo("XDH");
|
||||
@ -164,7 +152,7 @@ class PemPrivateKeyParserTests {
|
||||
})
|
||||
// @formatter:on
|
||||
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.getFormat()).isEqualTo("PKCS#8");
|
||||
assertThat(privateKey.getAlgorithm()).isEqualTo("EC");
|
||||
@ -183,14 +171,13 @@ class PemPrivateKeyParserTests {
|
||||
})
|
||||
// @formatter:on
|
||||
void shouldNotParseUnsupportedEcSec1(String file) {
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/sec1/" + file)))
|
||||
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("sec1/" + file)))
|
||||
.withMessageContaining("Missing private key or unrecognized format");
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseWithNonKeyTextWillThrowException() {
|
||||
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("test-banner.txt")));
|
||||
assertThatIllegalStateException().isThrownBy(() -> PemPrivateKeyParser.parse(read("file.txt")));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ -208,8 +195,7 @@ class PemPrivateKeyParserTests {
|
||||
// openssl pkcs8 -topk8 -in <input file> -out <output file> -v2 <algorithm>
|
||||
// -passout pass:test
|
||||
// where <algorithm> is aes128 or aes256
|
||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("org/springframework/boot/web/server/pkcs8/" + file),
|
||||
"test");
|
||||
PrivateKey privateKey = PemPrivateKeyParser.parse(read("pkcs8/" + file), "test");
|
||||
assertThat(privateKey).isNotNull();
|
||||
assertThat(privateKey.getFormat()).isEqualTo("PKCS#8");
|
||||
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
|
||||
// pass:test
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser
|
||||
.parse(read("org/springframework/boot/web/server/pkcs8/rsa-des-ede3-cbc.key"), "test"))
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs8/rsa-des-ede3-cbc.key"), "test"))
|
||||
.isInstanceOf(IllegalStateException.class)
|
||||
.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
|
||||
// pass:test
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser
|
||||
.parse(read("org/springframework/boot/web/server/pkcs8/rsa-scrypt.key"), "test"))
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs8/rsa-scrypt.key"), "test"))
|
||||
.withMessageContaining("Error decrypting private key");
|
||||
}
|
||||
|
||||
@ -244,8 +228,7 @@ class PemPrivateKeyParserTests {
|
||||
// openssl ecparam -genkey -name prime256v1 | openssl ec -aes-128-cbc -out
|
||||
// prime256v1-aes-128-cbc.key
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser
|
||||
.parse(read("org/springframework/boot/web/server/sec1/prime256v1-aes-128-cbc.key"), "test"))
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("sec1/prime256v1-aes-128-cbc.key"), "test"))
|
||||
.withMessageContaining("Missing private key or unrecognized format");
|
||||
}
|
||||
|
||||
@ -254,13 +237,13 @@ class PemPrivateKeyParserTests {
|
||||
// created with:
|
||||
// openssl genrsa -aes-256-cbc -out rsa-aes-256-cbc.key
|
||||
assertThatIllegalStateException()
|
||||
.isThrownBy(() -> PemPrivateKeyParser
|
||||
.parse(read("org/springframework/boot/web/server/pkcs1/rsa-aes-256-cbc.key"), "test"))
|
||||
.isThrownBy(() -> PemPrivateKeyParser.parse(read("pkcs1/rsa-aes-256-cbc.key"), "test"))
|
||||
.withMessageContaining("Missing private key or unrecognized format");
|
||||
}
|
||||
|
||||
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");
|
||||
* 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.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.util.function.ThrowingConsumer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -120,6 +121,7 @@ class PemSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void createWithDetailsWhenHasKeyStoreDetailsCertAndKey() {
|
||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||
.withPrivateKey("classpath:test-key.pem");
|
||||
@ -130,9 +132,10 @@ class PemSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "pkcs8/key-rsa-encrypted.pem" })
|
||||
void createWithDetailsWhenHasKeyStoreDetailsCertAndEncryptedKey() {
|
||||
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");
|
||||
PemSslStoreDetails trustStoreDetails = null;
|
||||
PemSslStoreBundle bundle = new PemSslStoreBundle(keyStoreDetails, trustStoreDetails);
|
||||
@ -141,6 +144,7 @@ class PemSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsWithoutKey() {
|
||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||
.withPrivateKey("classpath:test-key.pem");
|
||||
@ -151,6 +155,7 @@ class PemSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetails() {
|
||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||
.withPrivateKey("classpath:test-key.pem");
|
||||
@ -173,6 +178,7 @@ class PemSslStoreBundleTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("removal")
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsAndAlias() {
|
||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.pem")
|
||||
.withPrivateKey("classpath:test-key.pem");
|
||||
@ -184,6 +190,7 @@ class PemSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void createWithDetailsWhenHasStoreType() {
|
||||
PemSslStoreDetails keyStoreDetails = new PemSslStoreDetails("PKCS12", "classpath:test-cert.pem",
|
||||
"classpath:test-key.pem");
|
||||
@ -195,6 +202,7 @@ class PemSslStoreBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem" })
|
||||
void createWithDetailsWhenHasKeyStoreDetailsAndTrustStoreDetailsAndKeyPassword() {
|
||||
PemSslStoreDetails keyStoreDetails = PemSslStoreDetails.forCertificate("classpath:test-cert.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");
|
||||
* 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.jks.JksSslStoreBundle;
|
||||
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.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.server.Ssl;
|
||||
@ -124,6 +125,7 @@ abstract class AbstractClientHttpRequestFactoriesTests<T extends ClientHttpReque
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = { "GET", "POST" })
|
||||
@WithPackageResources("test.jks")
|
||||
void connectWithSslBundle(String httpMethod) throws Exception {
|
||||
TomcatServletWebServerFactory webServerFactory = new TomcatServletWebServerFactory(0);
|
||||
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");
|
||||
* 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.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.web.server.Compression;
|
||||
import org.springframework.boot.web.server.GracefulShutdownResult;
|
||||
@ -230,9 +232,10 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
||||
}
|
||||
|
||||
@Test
|
||||
void sslCiphersConfiguration() {
|
||||
@WithPackageResources("test.jks")
|
||||
void sslCiphersConfiguration(@ResourcePath("test.jks") String keyStore) {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStore(keyStore);
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
||||
@ -261,9 +264,10 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
||||
}
|
||||
|
||||
@Test
|
||||
void sslEnabledMultiProtocolsConfiguration() {
|
||||
@WithPackageResources("test.jks")
|
||||
void sslEnabledMultiProtocolsConfiguration(@ResourcePath("test.jks") String keyStore) {
|
||||
JettyServletWebServerFactory factory = getFactory();
|
||||
factory.setSsl(getSslSettings("TLSv1.1", "TLSv1.2"));
|
||||
factory.setSsl(getSslSettings(keyStore, "TLSv1.1", "TLSv1.2"));
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
JettyWebServer jettyWebServer = (JettyWebServer) this.webServer;
|
||||
@ -274,9 +278,10 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
||||
}
|
||||
|
||||
@Test
|
||||
void sslEnabledProtocolsConfiguration() {
|
||||
@WithPackageResources("test.jks")
|
||||
void sslEnabledProtocolsConfiguration(@ResourcePath("test.jks") String keyStore) {
|
||||
JettyServletWebServerFactory factory = getFactory();
|
||||
factory.setSsl(getSslSettings("TLSv1.1"));
|
||||
factory.setSsl(getSslSettings(keyStore, "TLSv1.1"));
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
JettyWebServer jettyWebServer = (JettyWebServer) this.webServer;
|
||||
@ -393,9 +398,9 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
||||
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.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStore(keyStore);
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
||||
@ -426,6 +431,7 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void basicSslClasspathKeyStore() throws Exception {
|
||||
testBasicSslWithKeyStore("classpath:test.jks");
|
||||
}
|
||||
@ -479,12 +485,13 @@ class JettyServletWebServerFactoryTests extends AbstractServletWebServerFactoryT
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void specificIPAddressWithSslIsNotReverseResolved() throws Exception {
|
||||
JettyServletWebServerFactory factory = getFactory();
|
||||
InetAddress localhost = InetAddress.getLocalHost();
|
||||
factory.setAddress(InetAddress.getByAddress(localhost.getAddress()));
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStore("classpath:test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
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.condition.OS;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.boot.testsupport.junit.DisabledOnOs;
|
||||
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
||||
import org.springframework.boot.testsupport.ssl.MockPkcs11SecurityProvider;
|
||||
@ -53,6 +54,7 @@ class SslServerCustomizerTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
@WithPackageResources("test.jks")
|
||||
void whenHttp2IsNotEnabledServerConnectorHasSslAndHttpConnectionFactories() {
|
||||
Server server = createCustomizedServer();
|
||||
assertThat(server.getConnectors()).hasSize(1);
|
||||
@ -63,6 +65,7 @@ class SslServerCustomizerTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
@WithPackageResources("test.jks")
|
||||
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
|
||||
disabledReason = "conscrypt doesn't support Linux/macOS aarch64, see https://github.com/google/conscrypt/issues/1051")
|
||||
void whenHttp2IsEnabledServerConnectorsHasSslAlpnH2AndHttpConnectionFactories() {
|
||||
@ -77,6 +80,7 @@ class SslServerCustomizerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
|
||||
disabledReason = "conscrypt doesn't support Linux/macOS aarch64, see https://github.com/google/conscrypt/issues/1051")
|
||||
void alpnConnectionFactoryHasNullDefaultProtocolToAllowNegotiationToHttp11() {
|
||||
@ -98,11 +102,12 @@ class SslServerCustomizerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void configureSslWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsException() {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStoreType("PKCS11");
|
||||
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStore("classpath:test.jks");
|
||||
ssl.setKeyPassword("password");
|
||||
assertThatIllegalStateException().isThrownBy(() -> {
|
||||
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");
|
||||
* 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.pem.PemSslStoreBundle;
|
||||
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.AbstractReactiveWebServerFactoryTests;
|
||||
import org.springframework.boot.web.server.PortInUseException;
|
||||
@ -133,12 +134,14 @@ class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void whenSslIsConfiguredWithAValidAliasARequestSucceeds() {
|
||||
Mono<String> result = testSslWithAlias("test-alias");
|
||||
StepVerifier.create(result).expectNext("Hello World").expectComplete().verify(Duration.ofSeconds(30));
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "1.key", "1.crt", "2.key", "2.crt" })
|
||||
void whenSslBundleIsUpdatedThenSslIsReloaded() {
|
||||
DefaultSslBundleRegistry bundles = new DefaultSslBundleRegistry("bundle1", createSslBundle("1.key", "1.crt"));
|
||||
Mono<String> result = testSslWithBundle(bundles, "bundle1");
|
||||
@ -231,9 +234,7 @@ class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor
|
||||
|
||||
private static SslBundle createSslBundle(String key, String certificate) {
|
||||
return SslBundle.of(new PemSslStoreBundle(
|
||||
new PemSslStoreDetails(null, "classpath:org/springframework/boot/web/embedded/netty/" + certificate,
|
||||
"classpath:org/springframework/boot/web/embedded/netty/" + key),
|
||||
null));
|
||||
new PemSslStoreDetails(null, "classpath:" + certificate, "classpath:" + key), null));
|
||||
}
|
||||
|
||||
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.extension.ExtendWith;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.boot.testsupport.ssl.MockPkcs11Security;
|
||||
import org.springframework.boot.testsupport.ssl.MockPkcs11SecurityProvider;
|
||||
import org.springframework.boot.testsupport.system.OutputCaptureExtension;
|
||||
@ -71,6 +72,7 @@ class SslConnectorCustomizerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslCiphersConfiguration() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("classpath:test.jks");
|
||||
@ -85,10 +87,11 @@ class SslConnectorCustomizerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslEnabledMultipleProtocolsConfiguration() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStore("classpath:test.jks");
|
||||
ssl.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
|
||||
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
||||
Connector connector = this.tomcat.getConnector();
|
||||
@ -101,10 +104,11 @@ class SslConnectorCustomizerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslEnabledProtocolsConfiguration() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStore("classpath:test.jks");
|
||||
ssl.setEnabledProtocols(new String[] { "TLSv1.2" });
|
||||
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
||||
Connector connector = this.tomcat.getConnector();
|
||||
@ -126,11 +130,12 @@ class SslConnectorCustomizerTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void customizeWhenSslIsEnabledWithPkcs11AndKeyStoreThrowsException() {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStoreType("PKCS11");
|
||||
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStore("classpath:test.jks");
|
||||
ssl.setKeyPassword("password");
|
||||
assertThatIllegalStateException().isThrownBy(() -> {
|
||||
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");
|
||||
* 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.springframework.boot.ssl.DefaultSslBundleRegistry;
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.boot.testsupport.system.CapturedOutput;
|
||||
import org.springframework.boot.web.server.PortInUseException;
|
||||
import org.springframework.boot.web.server.Shutdown;
|
||||
@ -683,11 +684,12 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslWithHttp11Nio2Protocol() throws Exception {
|
||||
TomcatServletWebServerFactory factory = getFactory();
|
||||
addTestTxtFile(factory);
|
||||
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.start();
|
||||
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");
|
||||
* 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 org.apache.hc.client5.http.classic.HttpClient;
|
||||
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.ssl.SSLContextBuilder;
|
||||
import org.apache.jasper.servlet.JspServlet;
|
||||
import org.awaitility.Awaitility;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
@ -46,6 +48,7 @@ import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithPackageResources;
|
||||
import org.springframework.boot.testsupport.web.servlet.ExampleServlet;
|
||||
import org.springframework.boot.web.server.ErrorPage;
|
||||
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.AbstractServletWebServerFactoryTests;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -155,7 +159,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
||||
|
||||
@Test
|
||||
void basicSslClasspathKeyStore() throws Exception {
|
||||
testBasicSslWithKeyStore("classpath:test.jks");
|
||||
testBasicSslWithKeyStore("classpath:org/springframework/boot/web/server/test.jks");
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -286,6 +290,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("restricted.jks")
|
||||
void sslRestrictedProtocolsEmptyCipherFailure() {
|
||||
assertThatIOException()
|
||||
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
||||
@ -294,6 +299,7 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("restricted.jks")
|
||||
void sslRestrictedProtocolsECDHETLS1Failure() {
|
||||
assertThatIOException()
|
||||
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1" },
|
||||
@ -302,18 +308,21 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("restricted.jks")
|
||||
void sslRestrictedProtocolsECDHESuccess() throws Exception {
|
||||
testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
||||
new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" });
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("restricted.jks")
|
||||
void sslRestrictedProtocolsRSATLS12Success() throws Exception {
|
||||
testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.2" },
|
||||
new String[] { "TLS_RSA_WITH_AES_128_CBC_SHA256" });
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("restricted.jks")
|
||||
void sslRestrictedProtocolsRSATLS11Failure() {
|
||||
assertThatIOException()
|
||||
.isThrownBy(() -> testRestrictedSSLProtocolsAndCipherSuites(new String[] { "TLSv1.1" },
|
||||
@ -374,4 +383,15 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto
|
||||
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");
|
||||
* 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.Test;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@ -32,8 +33,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class MustacheViewResolverTests {
|
||||
|
||||
private final String prefix = "classpath:/" + getClass().getPackage().getName().replace(".", "/") + "/";
|
||||
|
||||
private final MustacheViewResolver resolver = new MustacheViewResolver();
|
||||
|
||||
@BeforeEach
|
||||
@ -41,7 +40,7 @@ class MustacheViewResolverTests {
|
||||
GenericApplicationContext applicationContext = new GenericApplicationContext();
|
||||
applicationContext.refresh();
|
||||
this.resolver.setApplicationContext(applicationContext);
|
||||
this.resolver.setPrefix(this.prefix);
|
||||
this.resolver.setPrefix("classpath:");
|
||||
this.resolver.setSuffix(".html");
|
||||
}
|
||||
|
||||
@ -51,6 +50,7 @@ class MustacheViewResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||
void resolveExisting() {
|
||||
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");
|
||||
* 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 reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
|
||||
@ -38,17 +39,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class MustacheViewTests {
|
||||
|
||||
private final String templateUrl = "classpath:/" + getClass().getPackage().getName().replace(".", "/")
|
||||
+ "/template.html";
|
||||
|
||||
private final StaticApplicationContext context = new StaticApplicationContext();
|
||||
|
||||
@Test
|
||||
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||
void viewResolvesHandlebars() {
|
||||
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/test").build());
|
||||
MustacheView view = new MustacheView();
|
||||
view.setCompiler(Mustache.compiler());
|
||||
view.setUrl(this.templateUrl);
|
||||
view.setUrl("classpath:template.html");
|
||||
view.setCharset(StandardCharsets.UTF_8.displayName());
|
||||
view.setApplicationContext(this.context);
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -16,7 +16,6 @@
|
||||
|
||||
package org.springframework.boot.web.reactive.server;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
@ -54,12 +53,15 @@ import reactor.netty.http.Http11SslContextSpec;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
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.GracefulShutdownResult;
|
||||
import org.springframework.boot.web.server.Http2;
|
||||
import org.springframework.boot.web.server.Shutdown;
|
||||
import org.springframework.boot.web.server.Ssl;
|
||||
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.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
@ -165,13 +167,15 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void basicSslFromClassPath() {
|
||||
testBasicSslWithKeyStore("classpath:test.jks", "password");
|
||||
}
|
||||
|
||||
@Test
|
||||
void basicSslFromFileSystem() {
|
||||
testBasicSslWithKeyStore("src/test/resources/test.jks", "password");
|
||||
@WithPackageResources("test.jks")
|
||||
void basicSslFromFileSystem(@ResourcePath("test.jks") String keyStore) {
|
||||
testBasicSslWithKeyStore(keyStore, "password");
|
||||
|
||||
}
|
||||
|
||||
@ -199,6 +203,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslWithValidAlias() {
|
||||
String keyStore = "classpath:test.jks";
|
||||
String keyPassword = "password";
|
||||
@ -228,6 +233,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslWithInvalidAliasFailsDuringStartup() {
|
||||
String keyStore = "classpath:test.jks";
|
||||
String keyPassword = "password";
|
||||
@ -254,6 +260,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslWantsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setClientAuth(Ssl.ClientAuth.WANT);
|
||||
@ -265,6 +272,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslWantsClientAuthenticationSucceedsWithoutClientCertificate() {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setClientAuth(Ssl.ClientAuth.WANT);
|
||||
@ -275,10 +283,10 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
testClientAuthSuccess(ssl, buildTrustAllSslConnector());
|
||||
}
|
||||
|
||||
protected ReactorClientHttpConnector buildTrustAllSslWithClientKeyConnector(String keyStoreFile,
|
||||
protected ReactorClientHttpConnector buildTrustAllSslWithClientKeyConnector(String keyStore,
|
||||
String keyStorePassword) throws Exception {
|
||||
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());
|
||||
}
|
||||
KeyManagerFactory clientKeyManagerFactory = KeyManagerFactory
|
||||
@ -312,6 +320,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslNeedsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setClientAuth(Ssl.ClientAuth.NEED);
|
||||
@ -323,6 +332,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslNeedsClientAuthenticationFailsWithoutClientCertificate() {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setClientAuth(Ssl.ClientAuth.NEED);
|
||||
@ -334,6 +344,7 @@ public abstract class AbstractReactiveWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem", "test.p12" })
|
||||
void sslWithPemCertificates() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
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.SslOptions;
|
||||
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.MockPkcs11SecurityProvider;
|
||||
|
||||
@ -47,6 +49,7 @@ class WebServerSslBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.p12")
|
||||
void whenFromJksProperties() {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("classpath:test.p12");
|
||||
@ -77,11 +80,12 @@ class WebServerSslBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenFromJksPropertiesWithPkcs11StoreType() {
|
||||
@WithPackageResources("test.jks")
|
||||
void whenFromJksPropertiesWithPkcs11StoreType(@ResourcePath("test.jks") String keyStorePath) {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStoreType("PKCS11");
|
||||
ssl.setKeyStoreProvider(MockPkcs11SecurityProvider.NAME);
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStore(keyStorePath);
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setClientAuth(Ssl.ClientAuth.NONE);
|
||||
assertThatIllegalStateException().isThrownBy(() -> WebServerSslBundle.get(ssl))
|
||||
@ -108,6 +112,7 @@ class WebServerSslBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem", "test-cert-chain.pem" })
|
||||
void whenFromPemProperties() {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setCertificate("classpath:test-cert.pem");
|
||||
@ -135,6 +140,7 @@ class WebServerSslBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test-cert.pem", "test-key.pem", "test.p12" })
|
||||
void whenPemKeyStoreAndJksTrustStoreProperties() {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setCertificate("classpath:test-cert.pem");
|
||||
@ -163,6 +169,7 @@ class WebServerSslBundleTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources({ "test.p12", "test-cert-chain.pem" })
|
||||
void whenJksKeyStoreAndPemTrustStoreProperties() {
|
||||
Ssl ssl = new Ssl();
|
||||
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");
|
||||
* 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.Test;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
||||
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
@ -86,6 +87,7 @@ class ServletWebServerMvcIntegrationTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "conf.properties", content = "context=/example")
|
||||
void advancedConfig() throws Exception {
|
||||
this.context = new AnnotationConfigServletWebServerApplicationContext(AdvancedConfig.class);
|
||||
doTest(this.context, "/example/spring/hello");
|
||||
@ -161,7 +163,7 @@ class ServletWebServerMvcIntegrationTests {
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableWebMvc
|
||||
@PropertySource("classpath:/org/springframework/boot/web/servlet/context/conf.properties")
|
||||
@PropertySource("classpath:conf.properties")
|
||||
static class AdvancedConfig {
|
||||
|
||||
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");
|
||||
* 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.system.ApplicationHome;
|
||||
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.OutputCaptureExtension;
|
||||
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
|
||||
@ -426,16 +428,19 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void basicSslFromClassPath() throws Exception {
|
||||
testBasicSslWithKeyStore("classpath:test.jks");
|
||||
}
|
||||
|
||||
@Test
|
||||
void basicSslFromFileSystem() throws Exception {
|
||||
testBasicSslWithKeyStore("src/test/resources/test.jks");
|
||||
@WithPackageResources("test.jks")
|
||||
void basicSslFromFileSystem(@ResourcePath("test.jks") String keyStore) throws Exception {
|
||||
testBasicSslWithKeyStore(keyStore);
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslDisabled() throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
Ssl ssl = getSsl(null, "password", "classpath:test.jks");
|
||||
@ -451,9 +456,10 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslGetScheme() throws Exception { // gh-2232
|
||||
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.start();
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
@ -463,9 +469,10 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslKeyAlias() throws Exception {
|
||||
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);
|
||||
ServletRegistrationBean<ExampleServlet> registration = new ServletRegistrationBean<>(
|
||||
new ExampleServlet(true, false), "/hello");
|
||||
@ -483,9 +490,10 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslWithInvalidAliasFailsDuringStartup() {
|
||||
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);
|
||||
ServletRegistrationBean<ExampleServlet> registration = new ServletRegistrationBean<>(
|
||||
new ExampleServlet(true, false), "/hello");
|
||||
@ -499,9 +507,10 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void serverHeaderIsDisabledByDefaultWhenUsingSsl() throws Exception {
|
||||
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.start();
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
@ -516,10 +525,11 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void serverHeaderCanBeCustomizedWhenUsingSsl() throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
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.start();
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
@ -546,14 +556,15 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void pkcs12KeyStoreAndTrustStore() throws Exception {
|
||||
@WithPackageResources("test.p12")
|
||||
void pkcs12KeyStoreAndTrustStore(@ResourcePath("test.p12") File keyStoreFile) throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
addTestTxtFile(factory);
|
||||
factory.setSsl(getSsl(ClientAuth.NEED, null, "classpath:test.p12", "classpath:test.p12", null, null));
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12"));
|
||||
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
||||
@ -563,14 +574,15 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@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();
|
||||
addTestTxtFile(factory);
|
||||
factory.setSsl(getSsl("classpath:test-cert.pem", "classpath:test-key.pem"));
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12"));
|
||||
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
||||
@ -580,7 +592,8 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void pkcs12KeyStoreAndTrustStoreFromBundle() throws Exception {
|
||||
@WithPackageResources("test.p12")
|
||||
void pkcs12KeyStoreAndTrustStoreFromBundle(@ResourcePath("test.p12") File keyStoreFile) throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
addTestTxtFile(factory);
|
||||
factory.setSsl(Ssl.forBundle("test"));
|
||||
@ -589,7 +602,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12"));
|
||||
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
||||
@ -599,7 +612,8 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@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();
|
||||
addTestTxtFile(factory);
|
||||
factory.setSsl(Ssl.forBundle("test"));
|
||||
@ -608,7 +622,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
KeyStore keyStore = KeyStore.getInstance("pkcs12");
|
||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.p12"));
|
||||
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(keyStore, "secret".toCharArray())
|
||||
@ -618,7 +632,9 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void sslNeedsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
||||
@WithPackageResources("test.jks")
|
||||
void sslNeedsClientAuthenticationSucceedsWithClientCertificate(@ResourcePath("test.jks") File keyStoreFile)
|
||||
throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
factory.setRegisterDefaultServlet(true);
|
||||
addTestTxtFile(factory);
|
||||
@ -626,7 +642,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.jks"));
|
||||
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(keyStore, "password".toCharArray())
|
||||
@ -636,6 +652,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslNeedsClientAuthenticationFailsWithoutClientCertificate() throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
addTestTxtFile(factory);
|
||||
@ -650,7 +667,9 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void sslWantsClientAuthenticationSucceedsWithClientCertificate() throws Exception {
|
||||
@WithPackageResources("test.jks")
|
||||
void sslWantsClientAuthenticationSucceedsWithClientCertificate(@ResourcePath("test.jks") File keyStoreFile)
|
||||
throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
addTestTxtFile(factory);
|
||||
factory
|
||||
@ -658,7 +677,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
this.webServer = factory.getWebServer();
|
||||
this.webServer.start();
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
loadStore(keyStore, new FileSystemResource("src/test/resources/test.jks"));
|
||||
loadStore(keyStore, new FileSystemResource(keyStoreFile));
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(keyStore, "password".toCharArray())
|
||||
@ -668,6 +687,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithPackageResources("test.jks")
|
||||
void sslWantsClientAuthenticationSucceedsWithoutClientCertificate() throws Exception {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
addTestTxtFile(factory);
|
||||
@ -706,7 +726,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
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) {
|
||||
return getSsl(clientAuth, keyPassword, null, keyStore, trustStore, supportedProtocols, ciphers);
|
||||
}
|
||||
@ -767,17 +787,6 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
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(
|
||||
SSLConnectionSocketFactory socketFactory) {
|
||||
PoolingHttpClientConnectionManager connectionManager = PoolingHttpClientConnectionManagerBuilder.create()
|
||||
@ -949,7 +958,7 @@ public abstract class AbstractServletWebServerFactoryTests {
|
||||
AbstractServletWebServerFactory factory = getFactory();
|
||||
Ssl ssl = new Ssl();
|
||||
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");
|
||||
factory.setSsl(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");
|
||||
* 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.Test;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.web.servlet.View;
|
||||
@ -33,8 +34,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class MustacheViewResolverTests {
|
||||
|
||||
private final String prefix = "classpath:/" + getClass().getPackage().getName().replace(".", "/") + "/";
|
||||
|
||||
private final MustacheViewResolver resolver = new MustacheViewResolver();
|
||||
|
||||
@BeforeEach
|
||||
@ -43,7 +42,7 @@ class MustacheViewResolverTests {
|
||||
applicationContext.refresh();
|
||||
this.resolver.setApplicationContext(applicationContext);
|
||||
this.resolver.setServletContext(new MockServletContext());
|
||||
this.resolver.setPrefix(this.prefix);
|
||||
this.resolver.setPrefix("classpath:");
|
||||
this.resolver.setSuffix(".html");
|
||||
}
|
||||
|
||||
@ -53,11 +52,13 @@ class MustacheViewResolverTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||
void resolveExisting() throws Exception {
|
||||
assertThat(this.resolver.resolveViewName("template", null)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||
void setsContentType() throws Exception {
|
||||
this.resolver.setContentType("application/octet-stream");
|
||||
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");
|
||||
* 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.Test;
|
||||
|
||||
import org.springframework.boot.testsupport.classpath.resources.WithResource;
|
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebApplicationContext;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
@ -37,9 +38,6 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*/
|
||||
class MustacheViewTests {
|
||||
|
||||
private final String templateUrl = "classpath:/" + getClass().getPackage().getName().replace(".", "/")
|
||||
+ "/template.html";
|
||||
|
||||
private final MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
private final MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
@ -55,10 +53,11 @@ class MustacheViewTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithResource(name = "template.html", content = "Hello {{World}}")
|
||||
void viewResolvesHandlebars() throws Exception {
|
||||
MustacheView view = new MustacheView();
|
||||
view.setCompiler(Mustache.compiler());
|
||||
view.setUrl(this.templateUrl);
|
||||
view.setUrl("classpath:template.html");
|
||||
view.setApplicationContext(this.context);
|
||||
view.render(Collections.singletonMap("World", "Spring"), this.request, this.response);
|
||||
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