Merge branch '2.7.x'

Closes gh-32285
This commit is contained in:
Andy Wilkinson 2022-09-09 16:47:06 +01:00
commit aafceb3868
10 changed files with 182 additions and 53 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2022 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.
@ -105,7 +105,11 @@ class ThreadDumpEndpointTests {
.contains(String.format("\t- waiting to lock <%s> (a java.lang.Object) owned by \"%s\" t@%d",
hexIdentityHashCode(contendedMonitor), Thread.currentThread().getName(),
Thread.currentThread().getId()))
.contains(String.format("\t- waiting on <%s> (a java.lang.Object)", hexIdentityHashCode(monitor)))
.satisfiesAnyOf(
(dump) -> dump.contains(String.format("\t- waiting on <%s> (a java.lang.Object)",
hexIdentityHashCode(monitor))),
(dump) -> dump.contains(String.format("\t- parking to wait for <%s> (a java.lang.Object)",
hexIdentityHashCode(monitor))))
.containsPattern(
String.format("Locked ownable synchronizers:%n\t- Locked <[0-9a-z]+> \\(a %s\\$NonfairSync\\)",
ReentrantReadWriteLock.class.getName().replace(".", "\\.")));

View File

@ -59,7 +59,7 @@ class ReactiveWebServerFactoryCustomizerTests {
@Test
void testCustomizeServerAddress() {
ConfigurableReactiveWebServerFactory factory = mock(ConfigurableReactiveWebServerFactory.class);
InetAddress address = mock(InetAddress.class);
InetAddress address = InetAddress.getLoopbackAddress();
this.properties.setAddress(address);
this.customizer.customize(factory);
then(factory).should().setAddress(address);

View File

@ -127,3 +127,7 @@ task zip(type: Zip) {
artifacts {
"documentation" zip
}
toolchain {
maximumCompatibleJavaVersion = JavaLanguageVersion.of(18)
}

View File

@ -21,8 +21,9 @@ import java.util.List;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
@ -35,6 +36,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@ -68,7 +70,7 @@ class ArrayBinderTests {
@Test
void bindToCollectionShouldTriggerOnSuccess() {
this.sources.add(new MockConfigurationPropertySource("foo[0]", "1", "line1"));
BindHandler handler = mock(BindHandler.class, Answers.CALLS_REAL_METHODS);
BindHandler handler = mockBindHandler();
this.binder.bind("foo", INTEGER_LIST, handler);
InOrder inOrder = inOrder(handler);
inOrder.verify(handler).onSuccess(eq(ConfigurationPropertyName.of("foo[0]")), eq(Bindable.of(Integer.class)),
@ -198,7 +200,7 @@ class ArrayBinderTests {
@Test
void bindToArrayShouldTriggerOnSuccess() {
this.sources.add(new MockConfigurationPropertySource("foo[0]", "1", "line1"));
BindHandler handler = mock(BindHandler.class, Answers.CALLS_REAL_METHODS);
BindHandler handler = mockBindHandler();
Bindable<Integer[]> target = INTEGER_ARRAY;
this.binder.bind("foo", target, handler);
InOrder inOrder = inOrder(handler);
@ -285,4 +287,31 @@ class ArrayBinderTests {
IllegalStateException.class);
}
private BindHandler mockBindHandler() {
BindHandler handler = mock(BindHandler.class);
given(handler.onStart(any(), any(), any())).willAnswer(InvocationArgument.index(1));
given(handler.onCreate(any(), any(), any(), any())).willAnswer(InvocationArgument.index(3));
given(handler.onSuccess(any(), any(), any(), any())).willAnswer(InvocationArgument.index(3));
return handler;
}
private static final class InvocationArgument<T> implements Answer<T> {
private final int index;
private InvocationArgument(int index) {
this.index = index;
}
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
return invocation.getArgument(this.index);
}
private static <T> InvocationArgument<T> index(int index) {
return new InvocationArgument<>(index);
}
}
}

View File

@ -26,8 +26,9 @@ import java.util.Map;
import jakarta.validation.Validation;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.boot.context.properties.bind.Bindable.BindRestriction;
import org.springframework.boot.context.properties.bind.validation.ValidationBindHandler;
@ -53,6 +54,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@ -173,7 +175,7 @@ class BinderTests {
@Test
void bindToValueShouldTriggerOnSuccess() {
this.sources.add(new MockConfigurationPropertySource("foo", "1", "line1"));
BindHandler handler = mock(BindHandler.class, Answers.CALLS_REAL_METHODS);
BindHandler handler = mockBindHandler();
Bindable<Integer> target = Bindable.of(Integer.class);
this.binder.bind("foo", target, handler);
InOrder ordered = inOrder(handler);
@ -182,7 +184,7 @@ class BinderTests {
@Test
void bindOrCreateWhenNotBoundShouldTriggerOnCreate() {
BindHandler handler = mock(BindHandler.class, Answers.CALLS_REAL_METHODS);
BindHandler handler = mock(BindHandler.class);
Bindable<JavaBean> target = Bindable.of(JavaBean.class);
this.binder.bindOrCreate("foo", target, handler);
InOrder ordered = inOrder(handler);
@ -218,7 +220,7 @@ class BinderTests {
@Test
void bindToJavaBeanShouldTriggerOnSuccess() {
this.sources.add(new MockConfigurationPropertySource("foo.value", "bar", "line1"));
BindHandler handler = mock(BindHandler.class, Answers.CALLS_REAL_METHODS);
BindHandler handler = mockBindHandler();
Bindable<JavaBean> target = Bindable.of(JavaBean.class);
this.binder.bind("foo", target, handler);
InOrder inOrder = inOrder(handler);
@ -231,7 +233,7 @@ class BinderTests {
@Test
void bindWhenHasCustomDefaultHandlerShouldTriggerOnSuccess() {
this.sources.add(new MockConfigurationPropertySource("foo.value", "bar", "line1"));
BindHandler handler = mock(BindHandler.class, Answers.CALLS_REAL_METHODS);
BindHandler handler = mockBindHandler();
Binder binder = new Binder(this.sources, null, null, null, handler);
Bindable<JavaBean> target = Bindable.of(JavaBean.class);
binder.bind("foo", target);
@ -358,6 +360,14 @@ class BinderTests {
return this.binder.bindOrCreate("foo", bindable);
}
private BindHandler mockBindHandler() {
BindHandler handler = mock(BindHandler.class);
given(handler.onStart(any(), any(), any())).willAnswer(InvocationArgument.index(1));
given(handler.onCreate(any(), any(), any(), any())).willAnswer(InvocationArgument.index(3));
given(handler.onSuccess(any(), any(), any(), any())).willAnswer(InvocationArgument.index(3));
return handler;
}
static class JavaBean {
private String value;
@ -486,4 +496,23 @@ class BinderTests {
}
private static final class InvocationArgument<T> implements Answer<T> {
private final int index;
private InvocationArgument(int index) {
this.index = index;
}
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
return invocation.getArgument(this.index);
}
private static <T> InvocationArgument<T> index(int index) {
return new InvocationArgument<>(index);
}
}
}

View File

@ -27,9 +27,10 @@ import java.util.Properties;
import java.util.stream.Collectors;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.springframework.boot.context.properties.bind.BinderTests.ExampleEnum;
import org.springframework.boot.context.properties.bind.BinderTests.JavaBean;
@ -50,6 +51,7 @@ import static org.assertj.core.api.Assertions.entry;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@ -329,7 +331,7 @@ class MapBinderTests {
@Test
void bindToMapShouldTriggerOnSuccess() {
this.sources.add(new MockConfigurationPropertySource("foo.bar", "1", "line1"));
BindHandler handler = mock(BindHandler.class, Answers.CALLS_REAL_METHODS);
BindHandler handler = mockBindHandler();
Bindable<Map<String, Integer>> target = STRING_INTEGER_MAP;
this.binder.bind("foo", target, handler);
InOrder ordered = inOrder(handler);
@ -341,7 +343,7 @@ class MapBinderTests {
@Test
void bindToMapStringArrayShouldTriggerOnSuccess() {
this.sources.add(new MockConfigurationPropertySource("foo.bar", "a,b,c", "line1"));
BindHandler handler = mock(BindHandler.class, Answers.CALLS_REAL_METHODS);
BindHandler handler = mockBindHandler();
Bindable<Map<String, String[]>> target = STRING_ARRAY_MAP;
this.binder.bind("foo", target, handler);
InOrder ordered = inOrder(handler);
@ -614,6 +616,14 @@ class MapBinderTests {
return Bindable.of(ResolvableType.forClassWithGenerics(List.class, type));
}
private BindHandler mockBindHandler() {
BindHandler handler = mock(BindHandler.class);
given(handler.onStart(any(), any(), any())).willAnswer(InvocationArgument.index(1));
given(handler.onCreate(any(), any(), any(), any())).willAnswer(InvocationArgument.index(3));
given(handler.onSuccess(any(), any(), any(), any())).willAnswer(InvocationArgument.index(3));
return handler;
}
static class Foo {
private String pattern;
@ -734,4 +744,23 @@ class MapBinderTests {
}
private static final class InvocationArgument<T> implements Answer<T> {
private final int index;
private InvocationArgument(int index) {
this.index = index;
}
@Override
public T answer(InvocationOnMock invocation) throws Throwable {
return invocation.getArgument(this.index);
}
private static <T> InvocationArgument<T> index(int index) {
return new InvocationArgument<>(index);
}
}
}

View File

@ -19,11 +19,8 @@ package org.springframework.boot.context.properties.source;
import java.util.Collections;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link AliasedConfigurationPropertySource}.
@ -57,8 +54,7 @@ class AliasedConfigurationPropertySourceTests {
@Test
void containsDescendantOfWhenSourceReturnsUnknownShouldReturnUnknown() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.UNKNOWN);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().unknown(name);
ConfigurationPropertySource aliased = source
.withAliases(new ConfigurationPropertyNameAliases("foo.bar", "foo.bar1"));
assertThat(aliased.containsDescendantOf(name)).isEqualTo(ConfigurationPropertyState.UNKNOWN);
@ -67,10 +63,8 @@ class AliasedConfigurationPropertySourceTests {
@Test
void containsDescendantOfWhenSourceReturnsPresentShouldReturnPresent() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.PRESENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(ConfigurationPropertyState.UNKNOWN);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().present(name)
.unknown(ConfigurationPropertyName.of("bar"));
ConfigurationPropertySource aliased = source
.withAliases(new ConfigurationPropertyNameAliases("foo.bar", "foo.bar1"));
assertThat(aliased.containsDescendantOf(name)).isEqualTo(ConfigurationPropertyState.PRESENT);
@ -79,10 +73,8 @@ class AliasedConfigurationPropertySourceTests {
@Test
void containsDescendantOfWhenAllAreAbsentShouldReturnAbsent() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.ABSENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(ConfigurationPropertyState.ABSENT);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().absent(name)
.absent(ConfigurationPropertyName.of("bar"));
ConfigurationPropertySource aliased = source.withAliases(new ConfigurationPropertyNameAliases("foo", "bar"));
assertThat(aliased.containsDescendantOf(name)).isEqualTo(ConfigurationPropertyState.ABSENT);
}
@ -90,10 +82,8 @@ class AliasedConfigurationPropertySourceTests {
@Test
void containsDescendantOfWhenAnyIsPresentShouldReturnPresent() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.ABSENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(ConfigurationPropertyState.PRESENT);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().absent(name)
.present(ConfigurationPropertyName.of("bar"));
ConfigurationPropertySource aliased = source.withAliases(new ConfigurationPropertyNameAliases("foo", "bar"));
assertThat(aliased.containsDescendantOf(name)).isEqualTo(ConfigurationPropertyState.PRESENT);
}

View File

@ -19,12 +19,9 @@ package org.springframework.boot.context.properties.source;
import java.util.Objects;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Test for {@link FilteredIterableConfigurationPropertiesSource}.
@ -64,8 +61,7 @@ class FilteredConfigurationPropertiesSourceTests {
@Test
void containsDescendantOfWhenSourceReturnsEmptyShouldReturnEmpty() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.UNKNOWN);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().unknown(name);
ConfigurationPropertySource filtered = source.filter((n) -> true);
assertThat(filtered.containsDescendantOf(name)).isEqualTo(ConfigurationPropertyState.UNKNOWN);
}
@ -73,8 +69,7 @@ class FilteredConfigurationPropertiesSourceTests {
@Test
void containsDescendantOfWhenSourceReturnsFalseShouldReturnFalse() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.ABSENT);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().absent(name);
ConfigurationPropertySource filtered = source.filter((n) -> true);
assertThat(filtered.containsDescendantOf(name)).isEqualTo(ConfigurationPropertyState.ABSENT);
}
@ -82,8 +77,7 @@ class FilteredConfigurationPropertiesSourceTests {
@Test
void containsDescendantOfWhenSourceReturnsTrueShouldReturnEmpty() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.PRESENT);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().present(name);
ConfigurationPropertySource filtered = source.filter((n) -> true);
assertThat(filtered.containsDescendantOf(name)).isEqualTo(ConfigurationPropertyState.UNKNOWN);
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 2012-2022 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.context.properties.source;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class KnownAncestorsConfigurationPropertySource implements ConfigurationPropertySource {
private final Map<ConfigurationPropertyName, ConfigurationPropertyState> ancestors = new HashMap<>();
@Override
public ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name) {
return null;
}
@Override
public ConfigurationPropertyState containsDescendantOf(ConfigurationPropertyName name) {
ConfigurationPropertyState state = this.ancestors.get(name);
assertThat(state).isNotNull();
return state;
}
KnownAncestorsConfigurationPropertySource absent(ConfigurationPropertyName name) {
return ancestor(name, ConfigurationPropertyState.ABSENT);
}
KnownAncestorsConfigurationPropertySource present(ConfigurationPropertyName name) {
return ancestor(name, ConfigurationPropertyState.PRESENT);
}
KnownAncestorsConfigurationPropertySource unknown(ConfigurationPropertyName name) {
return ancestor(name, ConfigurationPropertyState.UNKNOWN);
}
private KnownAncestorsConfigurationPropertySource ancestor(ConfigurationPropertyName name,
ConfigurationPropertyState state) {
this.ancestors.put(name, state);
return this;
}
}

View File

@ -17,11 +17,8 @@
package org.springframework.boot.context.properties.source;
import org.junit.jupiter.api.Test;
import org.mockito.Answers;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link PrefixedConfigurationPropertySource}.
@ -45,8 +42,7 @@ class PrefixedConfigurationPropertySourceTests {
@Test
void containsDescendantOfWhenSourceReturnsUnknownShouldReturnUnknown() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.UNKNOWN);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().unknown(name);
ConfigurationPropertySource prefixed = source.withPrefix("my");
assertThat(prefixed.containsDescendantOf(ConfigurationPropertyName.of("foo")))
.isEqualTo(ConfigurationPropertyState.UNKNOWN);
@ -55,10 +51,8 @@ class PrefixedConfigurationPropertySourceTests {
@Test
void containsDescendantOfWhenSourceReturnsPresentShouldReturnPresent() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.PRESENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(ConfigurationPropertyState.UNKNOWN);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().present(name)
.unknown(ConfigurationPropertyName.of("bar"));
ConfigurationPropertySource prefixed = source.withPrefix("my");
assertThat(prefixed.containsDescendantOf(ConfigurationPropertyName.of("foo")))
.isEqualTo(ConfigurationPropertyState.PRESENT);
@ -67,10 +61,8 @@ class PrefixedConfigurationPropertySourceTests {
@Test
void containsDescendantOfWhenSourceReturnsAbsentShouldReturnAbsent() {
ConfigurationPropertyName name = ConfigurationPropertyName.of("my.foo");
ConfigurationPropertySource source = mock(ConfigurationPropertySource.class, Answers.CALLS_REAL_METHODS);
given(source.containsDescendantOf(name)).willReturn(ConfigurationPropertyState.ABSENT);
given(source.containsDescendantOf(ConfigurationPropertyName.of("bar")))
.willReturn(ConfigurationPropertyState.ABSENT);
ConfigurationPropertySource source = new KnownAncestorsConfigurationPropertySource().absent(name)
.absent(ConfigurationPropertyName.of("bar"));
ConfigurationPropertySource prefixed = source.withPrefix("my");
assertThat(prefixed.containsDescendantOf(ConfigurationPropertyName.of("foo")))
.isEqualTo(ConfigurationPropertyState.ABSENT);