Merge branch '2.0.x' into 2.1.x

Closes gh-17078
This commit is contained in:
Andy Wilkinson
2019-06-07 10:50:34 +01:00
2691 changed files with 27746 additions and 46049 deletions

View File

@@ -55,40 +55,36 @@ public class SpringApplicationHierarchyTests {
public void testParent() {
SpringApplicationBuilder builder = new SpringApplicationBuilder(Child.class);
builder.parent(Parent.class);
this.context = builder.run("--server.port=0",
"--management.metrics.use-global-registry=false");
this.context = builder.run("--server.port=0", "--management.metrics.use-global-registry=false");
}
@Test
public void testChild() {
SpringApplicationBuilder builder = new SpringApplicationBuilder(Parent.class);
builder.child(Child.class);
this.context = builder.run("--server.port=0",
"--management.metrics.use-global-registry=false");
this.context = builder.run("--server.port=0", "--management.metrics.use-global-registry=false");
}
@EnableAutoConfiguration(exclude = { ElasticsearchDataAutoConfiguration.class,
ElasticsearchRepositoriesAutoConfiguration.class,
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
FlywayAutoConfiguration.class, JestAutoConfiguration.class,
MetricsAutoConfiguration.class },
@EnableAutoConfiguration(
exclude = { ElasticsearchDataAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class,
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
FlywayAutoConfiguration.class, JestAutoConfiguration.class, MetricsAutoConfiguration.class },
excludeName = {
"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" })
public static class Child {
}
@EnableAutoConfiguration(exclude = { ElasticsearchDataAutoConfiguration.class,
ElasticsearchRepositoriesAutoConfiguration.class,
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
FlywayAutoConfiguration.class, JestAutoConfiguration.class,
MetricsAutoConfiguration.class },
@EnableAutoConfiguration(
exclude = { ElasticsearchDataAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class,
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class,
MongoDataAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
Neo4jDataAutoConfiguration.class, Neo4jRepositoriesAutoConfiguration.class,
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
FlywayAutoConfiguration.class, JestAutoConfiguration.class, MetricsAutoConfiguration.class },
excludeName = {
"org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration" })
public static class Parent {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,21 +36,18 @@ public class RabbitHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(RabbitAutoConfiguration.class,
RabbitHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
RabbitHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(RabbitHealthIndicator.class)
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(RabbitHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.rabbit.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(RabbitHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(RabbitHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,34 +55,28 @@ public class AuditAutoConfigurationTests {
@Test
public void ownAuditEventRepository() {
registerAndRefresh(CustomAuditEventRepositoryConfiguration.class,
AuditAutoConfiguration.class);
assertThat(this.context.getBean(AuditEventRepository.class))
.isInstanceOf(TestAuditEventRepository.class);
registerAndRefresh(CustomAuditEventRepositoryConfiguration.class, AuditAutoConfiguration.class);
assertThat(this.context.getBean(AuditEventRepository.class)).isInstanceOf(TestAuditEventRepository.class);
}
@Test
public void ownAuthenticationAuditListener() {
registerAndRefresh(CustomAuthenticationAuditListenerConfiguration.class,
AuditAutoConfiguration.class);
registerAndRefresh(CustomAuthenticationAuditListenerConfiguration.class, AuditAutoConfiguration.class);
assertThat(this.context.getBean(AbstractAuthenticationAuditListener.class))
.isInstanceOf(TestAuthenticationAuditListener.class);
}
@Test
public void ownAuthorizationAuditListener() {
registerAndRefresh(CustomAuthorizationAuditListenerConfiguration.class,
AuditAutoConfiguration.class);
registerAndRefresh(CustomAuthorizationAuditListenerConfiguration.class, AuditAutoConfiguration.class);
assertThat(this.context.getBean(AbstractAuthorizationAuditListener.class))
.isInstanceOf(TestAuthorizationAuditListener.class);
}
@Test
public void ownAuditListener() {
registerAndRefresh(CustomAuditListenerConfiguration.class,
AuditAutoConfiguration.class);
assertThat(this.context.getBean(AbstractAuditListener.class))
.isInstanceOf(TestAuditListener.class);
registerAndRefresh(CustomAuditListenerConfiguration.class, AuditAutoConfiguration.class);
assertThat(this.context.getBean(AbstractAuditListener.class)).isInstanceOf(TestAuditListener.class);
}
private void registerAndRefresh(Class<?>... annotatedClasses) {
@@ -114,8 +108,7 @@ public class AuditAutoConfigurationTests {
}
protected static class TestAuthenticationAuditListener
extends AbstractAuthenticationAuditListener {
protected static class TestAuthenticationAuditListener extends AbstractAuthenticationAuditListener {
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
@@ -137,8 +130,7 @@ public class AuditAutoConfigurationTests {
}
protected static class TestAuthorizationAuditListener
extends AbstractAuthorizationAuditListener {
protected static class TestAuthorizationAuditListener extends AbstractAuthorizationAuditListener {
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -33,22 +33,18 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class AuditEventsEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(AuditAutoConfiguration.class,
AuditEventsEndpointAutoConfiguration.class));
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
AutoConfigurations.of(AuditAutoConfiguration.class, AuditEventsEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(AuditEventsEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(AuditEventsEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpoint() {
this.contextRunner
.withPropertyValues("management.endpoint.auditevents.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(AuditEventsEndpoint.class));
this.contextRunner.withPropertyValues("management.endpoint.auditevents.enabled:false")
.run((context) -> assertThat(context).doesNotHaveBean(AuditEventsEndpoint.class));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,20 +32,17 @@ import static org.assertj.core.api.Assertions.assertThat;
public class BeansEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(BeansEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(BeansEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner
.run((context) -> assertThat(context).hasSingleBean(BeansEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(BeansEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner.withPropertyValues("management.endpoint.beans.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(BeansEndpoint.class));
.run((context) -> assertThat(context).doesNotHaveBean(BeansEndpoint.class));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,27 +37,24 @@ import static org.mockito.Mockito.mock;
public class CachesEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(CachesEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(CachesEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.withUserConfiguration(CacheConfiguration.class).run(
(context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
this.contextRunner.withUserConfiguration(CacheConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
}
@Test
public void runWithoutCacheManagerShouldHaveEndpointBean() {
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CachesEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner.withPropertyValues("management.endpoint.caches.enabled:false")
.withUserConfiguration(CacheConfiguration.class)
.run((context) -> assertThat(context)
.doesNotHaveBean(CachesEndpoint.class));
.run((context) -> assertThat(context).doesNotHaveBean(CachesEndpoint.class));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,21 +40,18 @@ public class CassandraHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CassandraConfiguration.class,
CassandraHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
CassandraHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(CassandraHealthIndicator.class)
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CassandraHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.cassandra.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(CassandraHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(CassandraHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,24 +40,19 @@ import static org.mockito.Mockito.mock;
public class CassandraReactiveHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(CassandraMockConfiguration.class)
.withConfiguration(AutoConfigurations.of(
CassandraReactiveHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
.withUserConfiguration(CassandraMockConfiguration.class).withConfiguration(AutoConfigurations.of(
CassandraReactiveHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(CassandraReactiveHealthIndicator.class)
.doesNotHaveBean(CassandraHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CassandraReactiveHealthIndicator.class)
.doesNotHaveBean(CassandraHealthIndicator.class).doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.cassandra.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(CassandraReactiveHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(CassandraReactiveHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,50 +32,43 @@ public class CloudFoundryAuthorizationExceptionTests {
@Test
public void statusCodeForInvalidTokenReasonShouldBe401() {
assertThat(createException(Reason.INVALID_TOKEN).getStatusCode())
.isEqualTo(HttpStatus.UNAUTHORIZED);
assertThat(createException(Reason.INVALID_TOKEN).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
@Test
public void statusCodeForInvalidIssuerReasonShouldBe401() {
assertThat(createException(Reason.INVALID_ISSUER).getStatusCode())
.isEqualTo(HttpStatus.UNAUTHORIZED);
assertThat(createException(Reason.INVALID_ISSUER).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
@Test
public void statusCodeForInvalidAudienceReasonShouldBe401() {
assertThat(createException(Reason.INVALID_AUDIENCE).getStatusCode())
.isEqualTo(HttpStatus.UNAUTHORIZED);
assertThat(createException(Reason.INVALID_AUDIENCE).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
@Test
public void statusCodeForInvalidSignatureReasonShouldBe401() {
assertThat(createException(Reason.INVALID_SIGNATURE).getStatusCode())
.isEqualTo(HttpStatus.UNAUTHORIZED);
assertThat(createException(Reason.INVALID_SIGNATURE).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
@Test
public void statusCodeForMissingAuthorizationReasonShouldBe401() {
assertThat(createException(Reason.MISSING_AUTHORIZATION).getStatusCode())
.isEqualTo(HttpStatus.UNAUTHORIZED);
assertThat(createException(Reason.MISSING_AUTHORIZATION).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
@Test
public void statusCodeForUnsupportedSignatureAlgorithmReasonShouldBe401() {
assertThat(createException(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM)
.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
@Test
public void statusCodeForTokenExpiredReasonShouldBe401() {
assertThat(createException(Reason.TOKEN_EXPIRED).getStatusCode())
assertThat(createException(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM).getStatusCode())
.isEqualTo(HttpStatus.UNAUTHORIZED);
}
@Test
public void statusCodeForTokenExpiredReasonShouldBe401() {
assertThat(createException(Reason.TOKEN_EXPIRED).getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED);
}
@Test
public void statusCodeForAccessDeniedReasonShouldBe403() {
assertThat(createException(Reason.ACCESS_DENIED).getStatusCode())
.isEqualTo(HttpStatus.FORBIDDEN);
assertThat(createException(Reason.ACCESS_DENIED).getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
}
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,16 +36,14 @@ public class CloudFoundryEndpointFilterTests {
@Test
public void matchIfDiscovererCloudFoundryShouldReturnFalse() {
DiscoveredEndpoint<?> endpoint = mock(DiscoveredEndpoint.class);
given(endpoint.wasDiscoveredBy(CloudFoundryWebEndpointDiscoverer.class))
.willReturn(true);
given(endpoint.wasDiscoveredBy(CloudFoundryWebEndpointDiscoverer.class)).willReturn(true);
assertThat(this.filter.match(endpoint)).isTrue();
}
@Test
public void matchIfDiscovererNotCloudFoundryShouldReturnFalse() {
DiscoveredEndpoint<?> endpoint = mock(DiscoveredEndpoint.class);
given(endpoint.wasDiscoveredBy(CloudFoundryWebEndpointDiscoverer.class))
.willReturn(false);
given(endpoint.wasDiscoveredBy(CloudFoundryWebEndpointDiscoverer.class)).willReturn(false);
assertThat(this.filter.match(endpoint)).isFalse();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -60,8 +60,8 @@ public class CloudFoundryWebEndpointDiscovererTests {
for (ExposableWebEndpoint endpoint : endpoints) {
if (endpoint.getEndpointId().equals(EndpointId.of("health"))) {
WebOperation operation = findMainReadOperation(endpoint);
assertThat(operation.invoke(new InvocationContext(
mock(SecurityContext.class), Collections.emptyMap())))
assertThat(operation
.invoke(new InvocationContext(mock(SecurityContext.class), Collections.emptyMap())))
.isEqualTo("cf");
}
}
@@ -74,31 +74,24 @@ public class CloudFoundryWebEndpointDiscovererTests {
return operation;
}
}
throw new IllegalStateException(
"No main read operation found from " + endpoint.getOperations());
throw new IllegalStateException("No main read operation found from " + endpoint.getOperations());
}
private void load(Class<?> configuration,
Consumer<CloudFoundryWebEndpointDiscoverer> consumer) {
private void load(Class<?> configuration, Consumer<CloudFoundryWebEndpointDiscoverer> consumer) {
this.load((id) -> null, (id) -> id.toString(), configuration, consumer);
}
private void load(Function<EndpointId, Long> timeToLive,
PathMapper endpointPathMapper, Class<?> configuration,
private void load(Function<EndpointId, Long> timeToLive, PathMapper endpointPathMapper, Class<?> configuration,
Consumer<CloudFoundryWebEndpointDiscoverer> consumer) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(
configuration);
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(configuration);
try {
ConversionServiceParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
DefaultConversionService.getSharedInstance());
EndpointMediaTypes mediaTypes = new EndpointMediaTypes(
Collections.singletonList("application/json"),
EndpointMediaTypes mediaTypes = new EndpointMediaTypes(Collections.singletonList("application/json"),
Collections.singletonList("application/json"));
CloudFoundryWebEndpointDiscoverer discoverer = new CloudFoundryWebEndpointDiscoverer(
context, parameterMapper, mediaTypes,
Collections.singletonList(endpointPathMapper),
Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)),
Collections.emptyList());
CloudFoundryWebEndpointDiscoverer discoverer = new CloudFoundryWebEndpointDiscoverer(context,
parameterMapper, mediaTypes, Collections.singletonList(endpointPathMapper),
Collections.singleton(new CachingOperationInvokerAdvisor(timeToLive)), Collections.emptyList());
consumer.accept(discoverer);
}
finally {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,8 +35,7 @@ public class TokenTests {
@Test
public void invalidJwtShouldThrowException() {
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> new Token("invalid-token"))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> new Token("invalid-token"))
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
@@ -45,8 +44,8 @@ public class TokenTests {
String header = "{\"alg\": \"RS256\", \"kid\": \"key-id\", \"typ\": \"JWT\"}";
String claims = "invalid-claims";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> new Token(Base64Utils.encodeToString(header.getBytes())
+ "." + Base64Utils.encodeToString(claims.getBytes())))
.isThrownBy(() -> new Token(Base64Utils.encodeToString(header.getBytes()) + "."
+ Base64Utils.encodeToString(claims.getBytes())))
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
@@ -55,8 +54,8 @@ public class TokenTests {
String header = "invalid-header";
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> new Token(Base64Utils.encodeToString(header.getBytes())
+ "." + Base64Utils.encodeToString(claims.getBytes())))
.isThrownBy(() -> new Token(Base64Utils.encodeToString(header.getBytes()) + "."
+ Base64Utils.encodeToString(claims.getBytes())))
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
@@ -64,8 +63,7 @@ public class TokenTests {
public void emptyJwtSignatureShouldThrowException() {
String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ0b3B0YWwu"
+ "Y29tIiwiZXhwIjoxNDI2NDIwODAwLCJhd2Vzb21lIjp0cnVlfQ.";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> new Token(token))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> new Token(token))
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
@@ -82,8 +80,7 @@ public class TokenTests {
assertThat(token.getSignatureAlgorithm()).isEqualTo("RS256");
assertThat(token.getKeyId()).isEqualTo("key-id");
assertThat(token.getContent()).isEqualTo(content.getBytes());
assertThat(token.getSignature())
.isEqualTo(Base64Utils.decodeFromString(signature));
assertThat(token.getSignature()).isEqualTo(Base64Utils.decodeFromString(signature));
}
@Test
@@ -92,8 +89,7 @@ public class TokenTests {
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
Token token = createToken(header, claims);
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> token.getSignatureAlgorithm())
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
.isThrownBy(() -> token.getSignatureAlgorithm()).satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
@Test
@@ -101,8 +97,7 @@ public class TokenTests {
String header = "{\"alg\": \"RS256\", \"kid\": \"key-id\", \"typ\": \"JWT\"}";
String claims = "{\"exp\": 2147483647}";
Token token = createToken(header, claims);
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> token.getIssuer())
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> token.getIssuer())
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
@@ -111,8 +106,7 @@ public class TokenTests {
String header = "{\"alg\": \"RS256\", \"typ\": \"JWT\"}";
String claims = "{\"exp\": 2147483647}";
Token token = createToken(header, claims);
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> token.getKeyId())
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> token.getKeyId())
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
@@ -121,20 +115,18 @@ public class TokenTests {
String header = "{\"alg\": \"RS256\", \"kid\": \"key-id\", \"typ\": \"JWT\"}";
String claims = "{\"iss\": \"http://localhost:8080/uaa/oauth/token\"" + "}";
Token token = createToken(header, claims);
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> token.getExpiry())
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(() -> token.getExpiry())
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
private Token createToken(String header, String claims) {
Token token = new Token(Base64Utils.encodeToString(header.getBytes()) + "."
+ Base64Utils.encodeToString(claims.getBytes()) + "."
+ Base64Utils.encodeToString("signature".getBytes()));
Token token = new Token(
Base64Utils.encodeToString(header.getBytes()) + "." + Base64Utils.encodeToString(claims.getBytes())
+ "." + Base64Utils.encodeToString("signature".getBytes()));
return token;
}
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(
Reason reason) {
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(Reason reason) {
return (ex) -> assertThat(ex.getReason()).isEqualTo(reason);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,18 +46,14 @@ public class CloudFoundryReactiveHealthEndpointWebExtensionTests {
private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withPropertyValues("VCAP_APPLICATION={}")
.withConfiguration(AutoConfigurations.of(
ReactiveSecurityAutoConfiguration.class,
ReactiveUserDetailsServiceAutoConfiguration.class,
WebFluxAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
ReactiveUserDetailsServiceAutoConfiguration.class, WebFluxAutoConfiguration.class,
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
ReactiveCloudFoundryActuatorAutoConfigurationTests.WebClientCustomizerConfig.class,
WebClientAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class,
ReactiveCloudFoundryActuatorAutoConfiguration.class));
@Test
@@ -65,8 +61,7 @@ public class CloudFoundryReactiveHealthEndpointWebExtensionTests {
this.contextRunner.run((context) -> {
CloudFoundryReactiveHealthEndpointWebExtension extension = context
.getBean(CloudFoundryReactiveHealthEndpointWebExtension.class);
assertThat(extension.health().block(Duration.ofSeconds(30)).getBody()
.getDetails()).isNotEmpty();
assertThat(extension.health().block(Duration.ofSeconds(30)).getBody().getDetails()).isNotEmpty();
});
}

View File

@@ -70,109 +70,88 @@ import static org.mockito.Mockito.mock;
*/
public class CloudFoundryWebFluxEndpointIntegrationTests {
private static ReactiveTokenValidator tokenValidator = mock(
ReactiveTokenValidator.class);
private static ReactiveTokenValidator tokenValidator = mock(ReactiveTokenValidator.class);
private static ReactiveCloudFoundrySecurityService securityService = mock(
ReactiveCloudFoundrySecurityService.class);
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner(
AnnotationConfigReactiveWebServerApplicationContext::new)
.withConfiguration(
AutoConfigurations.of(WebFluxAutoConfiguration.class,
HttpHandlerAutoConfiguration.class,
ReactiveWebServerFactoryAutoConfiguration.class))
.withUserConfiguration(TestEndpointConfiguration.class)
.withPropertyValues("server.port=0");
.withConfiguration(AutoConfigurations.of(WebFluxAutoConfiguration.class,
HttpHandlerAutoConfiguration.class, ReactiveWebServerFactoryAutoConfiguration.class))
.withUserConfiguration(TestEndpointConfiguration.class).withPropertyValues("server.port=0");
@Test
public void operationWithSecurityInterceptorForbidden() {
given(tokenValidator.validate(any())).willReturn(Mono.empty());
given(securityService.getAccessLevel(any(), eq("app-id")))
.willReturn(Mono.just(AccessLevel.RESTRICTED));
this.contextRunner.run(withWebTestClient((client) -> client.get()
.uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication/test")
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isEqualTo(HttpStatus.FORBIDDEN)));
}
@Test
public void operationWithSecurityInterceptorSuccess() {
given(tokenValidator.validate(any())).willReturn(Mono.empty());
given(securityService.getAccessLevel(any(), eq("app-id")))
.willReturn(Mono.just(AccessLevel.FULL));
this.contextRunner.run(withWebTestClient((client) -> client.get()
.uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication/test")
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isEqualTo(HttpStatus.OK)));
}
@Test
public void responseToOptionsRequestIncludesCorsHeaders() {
this.contextRunner.run(withWebTestClient((client) -> client.options()
.uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Access-Control-Request-Method", "POST")
.header("Origin", "https://example.com").exchange().expectStatus().isOk()
.expectHeader()
.valueEquals("Access-Control-Allow-Origin", "https://example.com")
.expectHeader().valueEquals("Access-Control-Allow-Methods", "GET,POST")));
this.contextRunner.run(withWebTestClient((client) -> client.options().uri("/cfApplication/test")
.accept(MediaType.APPLICATION_JSON).header("Access-Control-Request-Method", "POST")
.header("Origin", "https://example.com").exchange().expectStatus().isOk().expectHeader()
.valueEquals("Access-Control-Allow-Origin", "https://example.com").expectHeader()
.valueEquals("Access-Control-Allow-Methods", "GET,POST")));
}
@Test
public void linksToOtherEndpointsWithFullAccess() {
given(tokenValidator.validate(any())).willReturn(Mono.empty());
given(securityService.getAccessLevel(any(), eq("app-id")))
.willReturn(Mono.just(AccessLevel.FULL));
this.contextRunner.run(withWebTestClient((client) -> client.get()
.uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isOk().expectBody().jsonPath("_links.length()")
.isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false)
.jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false)
.jsonPath("_links.env.href").isNotEmpty().jsonPath("_links.env.templated")
.isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
.jsonPath("_links.test.templated").isEqualTo(false)
.jsonPath("_links.test-part.href").isNotEmpty()
.jsonPath("_links.test-part.templated").isEqualTo(true)));
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.FULL));
this.contextRunner
.run(withWebTestClient((client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
.expectBody().jsonPath("_links.length()").isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env.href").isNotEmpty()
.jsonPath("_links.env.templated").isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
.jsonPath("_links.test.templated").isEqualTo(false).jsonPath("_links.test-part.href")
.isNotEmpty().jsonPath("_links.test-part.templated").isEqualTo(true)));
}
@Test
public void linksToOtherEndpointsForbidden() {
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(
Reason.INVALID_TOKEN, "invalid-token");
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
"invalid-token");
willThrow(exception).given(tokenValidator).validate(any());
this.contextRunner.run(withWebTestClient((client) -> client.get()
.uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
this.contextRunner.run(withWebTestClient((client) -> client.get().uri("/cfApplication")
.accept(MediaType.APPLICATION_JSON).header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isUnauthorized()));
}
@Test
public void linksToOtherEndpointsWithRestrictedAccess() {
given(tokenValidator.validate(any())).willReturn(Mono.empty());
given(securityService.getAccessLevel(any(), eq("app-id")))
.willReturn(Mono.just(AccessLevel.RESTRICTED));
this.contextRunner.run(withWebTestClient((client) -> client.get()
.uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isOk().expectBody().jsonPath("_links.length()")
.isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false)
.jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env")
.doesNotExist().jsonPath("_links.test").doesNotExist()
.jsonPath("_links.test-part").doesNotExist()));
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(Mono.just(AccessLevel.RESTRICTED));
this.contextRunner
.run(withWebTestClient((client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
.expectBody().jsonPath("_links.length()").isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env").doesNotExist()
.jsonPath("_links.test").doesNotExist().jsonPath("_links.test-part").doesNotExist()));
}
private ContextConsumer<AssertableReactiveWebApplicationContext> withWebTestClient(
Consumer<WebTestClient> clientConsumer) {
return (context) -> {
int port = ((AnnotationConfigReactiveWebServerApplicationContext) context
.getSourceApplicationContext()).getWebServer().getPort();
clientConsumer.accept(WebTestClient.bindToServer()
.baseUrl("http://localhost:" + port).build());
int port = ((AnnotationConfigReactiveWebServerApplicationContext) context.getSourceApplicationContext())
.getWebServer().getPort();
clientConsumer.accept(WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build());
};
}
@@ -187,8 +166,7 @@ public class CloudFoundryWebFluxEndpointIntegrationTests {
@Bean
public CloudFoundrySecurityInterceptor interceptor() {
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService,
"app-id");
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
}
@Bean
@@ -199,28 +177,23 @@ public class CloudFoundryWebFluxEndpointIntegrationTests {
@Bean
public CloudFoundryWebFluxEndpointHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
WebEndpointDiscoverer webEndpointDiscoverer,
EndpointMediaTypes endpointMediaTypes,
WebEndpointDiscoverer webEndpointDiscoverer, EndpointMediaTypes endpointMediaTypes,
CloudFoundrySecurityInterceptor interceptor) {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(Arrays.asList("https://example.com"));
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
return new CloudFoundryWebFluxEndpointHandlerMapping(
new EndpointMapping("/cfApplication"),
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes,
corsConfiguration, interceptor,
return new CloudFoundryWebFluxEndpointHandlerMapping(new EndpointMapping("/cfApplication"),
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes, corsConfiguration, interceptor,
new EndpointLinksResolver(webEndpointDiscoverer.getEndpoints()));
}
@Bean
public WebEndpointDiscoverer webEndpointDiscoverer(
ApplicationContext applicationContext,
public WebEndpointDiscoverer webEndpointDiscoverer(ApplicationContext applicationContext,
EndpointMediaTypes endpointMediaTypes) {
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
DefaultConversionService.getSharedInstance());
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
endpointMediaTypes, null, Collections.emptyList(),
Collections.emptyList());
return new WebEndpointDiscoverer(applicationContext, parameterMapper, endpointMediaTypes, null,
Collections.emptyList(), Collections.emptyList());
}
@Bean

View File

@@ -76,17 +76,13 @@ import static org.mockito.Mockito.mock;
public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
ReactiveSecurityAutoConfiguration.class,
ReactiveUserDetailsServiceAutoConfiguration.class,
WebFluxAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
WebClientCustomizerConfig.class, WebClientAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
.withConfiguration(AutoConfigurations.of(ReactiveSecurityAutoConfiguration.class,
ReactiveUserDetailsServiceAutoConfiguration.class, WebFluxAutoConfiguration.class,
JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, WebClientCustomizerConfig.class,
WebClientAutoConfiguration.class, ManagementContextAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class,
ReactiveCloudFoundryActuatorAutoConfiguration.class));
@After
@@ -96,90 +92,67 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@Test
public void cloudFoundryPlatformActive() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils
.getField(handlerMapping, "endpointMapping");
assertThat(endpointMapping.getPath())
.isEqualTo("/cloudfoundryapplication");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping,
"endpointMapping");
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication");
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
.getField(handlerMapping, "corsConfiguration");
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
assertThat(corsConfiguration.getAllowedMethods()).containsAll(
Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
assertThat(corsConfiguration.getAllowedMethods())
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
assertThat(corsConfiguration.getAllowedHeaders())
.containsAll(Arrays.asList("Authorization",
"X-Cf-App-Instance", "Content-Type"));
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type"));
});
}
@Test
public void cloudfoundryapplicationProducesActuatorMediaType() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
WebTestClient webTestClient = WebTestClient
.bindToApplicationContext(context).build();
webTestClient.get().uri("/cloudfoundryapplication").header(
"Content-Type", ActuatorMediaType.V2_JSON + ";charset=UTF-8");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
WebTestClient webTestClient = WebTestClient.bindToApplicationContext(context).build();
webTestClient.get().uri("/cloudfoundryapplication").header("Content-Type",
ActuatorMediaType.V2_JSON + ";charset=UTF-8");
});
}
@Test
public void cloudFoundryPlatformActiveSetsApplicationId() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor");
String applicationId = (String) ReflectionTestUtils
.getField(interceptor, "applicationId");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId");
assertThat(applicationId).isEqualTo("my-app-id");
});
}
@Test
public void cloudFoundryPlatformActiveSetsCloudControllerUrl() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils
.getField(interceptor, "cloudFoundrySecurityService");
String cloudControllerUrl = (String) ReflectionTestUtils
.getField(interceptorSecurityService, "cloudControllerUrl");
assertThat(cloudControllerUrl)
.isEqualTo("https://my-cloud-controller.com");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
"cloudFoundrySecurityService");
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService,
"cloudControllerUrl");
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com");
});
}
@Test
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id").run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context
.getBean("cloudFoundryWebFluxEndpointHandlerMapping",
CloudFoundryWebFluxEndpointHandlerMapping.class);
Object securityInterceptor = ReflectionTestUtils
.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils
.getField(securityInterceptor, "cloudFoundrySecurityService");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
.run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = context.getBean(
"cloudFoundryWebFluxEndpointHandlerMapping",
CloudFoundryWebFluxEndpointHandlerMapping.class);
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor,
"cloudFoundrySecurityService");
assertThat(interceptorSecurityService).isNull();
});
}
@@ -187,28 +160,22 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@Test
@SuppressWarnings("unchecked")
public void cloudFoundryPathsIgnoredBySpringSecurity() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
WebFilterChainProxy chainProxy = context
.getBean(WebFilterChainProxy.class);
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
WebFilterChainProxy chainProxy = context.getBean(WebFilterChainProxy.class);
List<SecurityWebFilterChain> filters = (List<SecurityWebFilterChain>) ReflectionTestUtils
.getField(chainProxy, "filters");
Boolean cfRequestMatches = filters.get(0)
.matches(MockServerWebExchange.from(MockServerHttpRequest
.get("/cloudfoundryapplication/my-path").build()))
.matches(MockServerWebExchange
.from(MockServerHttpRequest.get("/cloudfoundryapplication/my-path").build()))
.block(Duration.ofSeconds(30));
Boolean otherRequestMatches = filters.get(0)
.matches(MockServerWebExchange.from(MockServerHttpRequest
.get("/some-other-path").build()))
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
.block(Duration.ofSeconds(30));
assertThat(cfRequestMatches).isTrue();
assertThat(otherRequestMatches).isFalse();
otherRequestMatches = filters.get(1)
.matches(MockServerWebExchange.from(MockServerHttpRequest
.get("/some-other-path").build()))
.matches(MockServerWebExchange.from(MockServerHttpRequest.get("/some-other-path").build()))
.block(Duration.ofSeconds(30));
assertThat(otherRequestMatches).isTrue();
});
@@ -217,34 +184,24 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@Test
public void cloudFoundryPlatformInactive() {
this.contextRunner.run((context) -> assertThat(
context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping"))
.isFalse());
this.contextRunner.run(
(context) -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")).isFalse());
}
@Test
public void cloudFoundryManagementEndpointsDisabled() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION=---",
"management.cloudfoundry.enabled:false")
.run((context) -> assertThat(
context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping"))
.isFalse());
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false").run(
(context) -> assertThat(context.containsBean("cloudFoundryWebFluxEndpointHandlerMapping")).isFalse());
}
@Test
public void allEndpointsAvailableUnderCloudFoundryWithoutEnablingWebIncludes() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
this.contextRunner.withUserConfiguration(TestConfiguration.class).withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping
.getEndpoints();
List<EndpointId> endpointIds = endpoints.stream()
.map(ExposableEndpoint::getEndpointId)
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
List<EndpointId> endpointIds = endpoints.stream().map(ExposableEndpoint::getEndpointId)
.collect(Collectors.toList());
assertThat(endpointIds).contains(EndpointId.of("test"));
});
@@ -252,112 +209,84 @@ public class ReactiveCloudFoundryActuatorAutoConfigurationTests {
@Test
public void endpointPathCustomizationIsNotApplied() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
this.contextRunner.withUserConfiguration(TestConfiguration.class).withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping
.getEndpoints();
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
ExposableWebEndpoint endpoint = endpoints.stream()
.filter((candidate) -> EndpointId.of("test")
.equals(candidate.getEndpointId()))
.findFirst().get();
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst()
.get();
assertThat(endpoint.getOperations()).hasSize(1);
WebOperation operation = endpoint.getOperations().iterator().next();
assertThat(operation.getRequestPredicate().getPath())
.isEqualTo("test");
assertThat(operation.getRequestPredicate().getPath()).isEqualTo("test");
});
}
@Test
public void healthEndpointInvokerShouldBeCloudFoundryWebExtension() {
this.contextRunner
.withConfiguration(
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
Collection<ExposableWebEndpoint> endpoints = getHandlerMapping(
context).getEndpoints();
Collection<ExposableWebEndpoint> endpoints = getHandlerMapping(context).getEndpoints();
ExposableWebEndpoint endpoint = endpoints.iterator().next();
assertThat(endpoint.getOperations()).hasSize(3);
WebOperation webOperation = findOperationWithRequestPath(endpoint,
"health");
Object invoker = ReflectionTestUtils.getField(webOperation,
"invoker");
WebOperation webOperation = findOperationWithRequestPath(endpoint, "health");
Object invoker = ReflectionTestUtils.getField(webOperation, "invoker");
assertThat(ReflectionTestUtils.getField(invoker, "target"))
.isInstanceOf(
CloudFoundryReactiveHealthEndpointWebExtension.class);
.isInstanceOf(CloudFoundryReactiveHealthEndpointWebExtension.class);
});
}
@Test
public void skipSslValidation() {
this.contextRunner
.withConfiguration(
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com",
"management.cloudfoundry.skip-ssl-validation:true")
.run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils
.getField(interceptor, "cloudFoundrySecurityService");
WebClient webClient = (WebClient) ReflectionTestUtils
.getField(interceptorSecurityService, "webClient");
webClient.get().uri("https://self-signed.badssl.com/").exchange()
.block(Duration.ofSeconds(30));
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
"cloudFoundrySecurityService");
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService,
"webClient");
webClient.get().uri("https://self-signed.badssl.com/").exchange().block(Duration.ofSeconds(30));
});
}
@Test
public void sslValidationNotSkippedByDefault() {
this.contextRunner
.withConfiguration(
AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
this.contextRunner.withConfiguration(AutoConfigurations.of(HealthEndpointAutoConfiguration.class))
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils
.getField(interceptor, "cloudFoundrySecurityService");
WebClient webClient = (WebClient) ReflectionTestUtils
.getField(interceptorSecurityService, "webClient");
assertThatExceptionOfType(RuntimeException.class)
.isThrownBy(() -> webClient.get()
.uri("https://self-signed.badssl.com/").exchange()
.block(Duration.ofSeconds(30)))
CloudFoundryWebFluxEndpointHandlerMapping handlerMapping = getHandlerMapping(context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
"cloudFoundrySecurityService");
WebClient webClient = (WebClient) ReflectionTestUtils.getField(interceptorSecurityService,
"webClient");
assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> webClient.get()
.uri("https://self-signed.badssl.com/").exchange().block(Duration.ofSeconds(30)))
.withCauseInstanceOf(SSLException.class);
});
}
private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(
ApplicationContext context) {
private CloudFoundryWebFluxEndpointHandlerMapping getHandlerMapping(ApplicationContext context) {
return context.getBean("cloudFoundryWebFluxEndpointHandlerMapping",
CloudFoundryWebFluxEndpointHandlerMapping.class);
}
private WebOperation findOperationWithRequestPath(ExposableWebEndpoint endpoint,
String requestPath) {
private WebOperation findOperationWithRequestPath(ExposableWebEndpoint endpoint, String requestPath) {
for (WebOperation operation : endpoint.getOperations()) {
if (operation.getRequestPredicate().getPath().equals(requestPath)) {
return operation;
}
}
throw new IllegalStateException("No operation found with request path "
+ requestPath + " from " + endpoint.getOperations());
throw new IllegalStateException(
"No operation found with request path " + requestPath + " from " + endpoint.getOperations());
}
@Configuration

View File

@@ -54,62 +54,54 @@ public class ReactiveCloudFoundrySecurityInterceptorTests {
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
this.securityService, "my-app-id");
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, "my-app-id");
}
@Test
public void preHandleWhenRequestIsPreFlightShouldBeOk() {
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest
.options("/a").header(HttpHeaders.ORIGIN, "https://example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").build());
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeNextWith(
(response) -> assertThat(response.getStatus()).isEqualTo(HttpStatus.OK))
MockServerWebExchange request = MockServerWebExchange
.from(MockServerHttpRequest.options("/a").header(HttpHeaders.ORIGIN, "https://example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").build());
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
.consumeNextWith((response) -> assertThat(response.getStatus()).isEqualTo(HttpStatus.OK))
.verifyComplete();
}
@Test
public void preHandleWhenTokenIsMissingShouldReturnMissingAuthorization() {
MockServerWebExchange request = MockServerWebExchange
.from(MockServerHttpRequest.get("/a").build());
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
.consumeNextWith((response) -> assertThat(response.getStatus())
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a").build());
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeNextWith(
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
.verifyComplete();
}
@Test
public void preHandleWhenTokenIsNotBearerShouldReturnMissingAuthorization() {
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest
.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
.consumeNextWith((response) -> assertThat(response.getStatus())
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
MockServerWebExchange request = MockServerWebExchange
.from(MockServerHttpRequest.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeNextWith(
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus()))
.verifyComplete();
}
@Test
public void preHandleWhenApplicationIdIsNullShouldReturnError() {
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
this.securityService, null);
MockServerWebExchange request = MockServerWebExchange
.from(MockServerHttpRequest.get("/a")
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
.build());
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeErrorWith(
(ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, null);
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
.consumeErrorWith((ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
.verify();
}
@Test
public void preHandleWhenCloudFoundrySecurityServiceIsNullShouldReturnError() {
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null,
"my-app-id");
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest
.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
StepVerifier.create(this.interceptor.preHandle(request, "/a")).consumeErrorWith(
(ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null, "my-app-id");
MockServerWebExchange request = MockServerWebExchange
.from(MockServerHttpRequest.get("/a").header(HttpHeaders.AUTHORIZATION, mockAccessToken()).build());
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
.consumeErrorWith((ex) -> assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
.verify();
}
@@ -119,33 +111,25 @@ public class ReactiveCloudFoundrySecurityInterceptorTests {
given(this.securityService.getAccessLevel(mockAccessToken(), "my-app-id"))
.willReturn(Mono.just(AccessLevel.RESTRICTED));
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
MockServerWebExchange request = MockServerWebExchange
.from(MockServerHttpRequest.get("/a")
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
.build());
MockServerWebExchange request = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
StepVerifier.create(this.interceptor.preHandle(request, "/a"))
.consumeNextWith((response) -> assertThat(response.getStatus())
.isEqualTo(Reason.ACCESS_DENIED.getStatus()))
.consumeNextWith(
(response) -> assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus()))
.verifyComplete();
}
@Test
public void preHandleSuccessfulWithFullAccess() {
String accessToken = mockAccessToken();
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(Mono.just(AccessLevel.FULL));
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(Mono.just(AccessLevel.FULL));
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
MockServerWebExchange exchange = MockServerWebExchange
.from(MockServerHttpRequest.get("/a")
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
.build());
StepVerifier.create(this.interceptor.preHandle(exchange, "/a"))
.consumeNextWith((response) -> {
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
assertThat((AccessLevel) exchange
.getAttribute("cloudFoundryAccessLevel"))
.isEqualTo(AccessLevel.FULL);
}).verifyComplete();
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/a")
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
StepVerifier.create(this.interceptor.preHandle(exchange, "/a")).consumeNextWith((response) -> {
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
assertThat((AccessLevel) exchange.getAttribute("cloudFoundryAccessLevel")).isEqualTo(AccessLevel.FULL);
}).verifyComplete();
}
@Test
@@ -154,17 +138,13 @@ public class ReactiveCloudFoundrySecurityInterceptorTests {
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(Mono.just(AccessLevel.RESTRICTED));
given(this.tokenValidator.validate(any())).willReturn(Mono.empty());
MockServerWebExchange exchange = MockServerWebExchange
.from(MockServerHttpRequest.get("/info")
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken())
.build());
StepVerifier.create(this.interceptor.preHandle(exchange, "info"))
.consumeNextWith((response) -> {
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
assertThat((AccessLevel) exchange
.getAttribute("cloudFoundryAccessLevel"))
.isEqualTo(AccessLevel.RESTRICTED);
}).verifyComplete();
MockServerWebExchange exchange = MockServerWebExchange.from(MockServerHttpRequest.get("/info")
.header(HttpHeaders.AUTHORIZATION, "bearer " + mockAccessToken()).build());
StepVerifier.create(this.interceptor.preHandle(exchange, "info")).consumeNextWith((response) -> {
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
assertThat((AccessLevel) exchange.getAttribute("cloudFoundryAccessLevel"))
.isEqualTo(AccessLevel.RESTRICTED);
}).verifyComplete();
}
private String mockAccessToken() {

View File

@@ -43,8 +43,7 @@ public class ReactiveCloudFoundrySecurityServiceTests {
private static final String CLOUD_CONTROLLER = "/my-cloud-controller.com";
private static final String CLOUD_CONTROLLER_PERMISSIONS = CLOUD_CONTROLLER
+ "/v2/apps/my-app-id/permissions";
private static final String CLOUD_CONTROLLER_PERMISSIONS = CLOUD_CONTROLLER + "/v2/apps/my-app-id/permissions";
private static final String UAA_URL = "https://my-cloud-controller.com/uaa";
@@ -58,8 +57,7 @@ public class ReactiveCloudFoundrySecurityServiceTests {
public void setup() {
this.server = new MockWebServer();
this.builder = WebClient.builder().baseUrl(this.server.url("/").toString());
this.securityService = new ReactiveCloudFoundrySecurityService(this.builder,
CLOUD_CONTROLLER, false);
this.securityService = new ReactiveCloudFoundrySecurityService(this.builder, CLOUD_CONTROLLER, false);
}
@After
@@ -70,36 +68,25 @@ public class ReactiveCloudFoundrySecurityServiceTests {
@Test
public void getAccessLevelWhenSpaceDeveloperShouldReturnFull() throws Exception {
String responseBody = "{\"read_sensitive_data\": true,\"read_basic_data\": true}";
prepareResponse((response) -> response.setBody(responseBody)
.setHeader("Content-Type", "application/json"));
StepVerifier
.create(this.securityService.getAccessLevel("my-access-token",
"my-app-id"))
.consumeNextWith((accessLevel) -> assertThat(accessLevel)
.isEqualTo(AccessLevel.FULL))
.expectComplete().verify();
prepareResponse((response) -> response.setBody(responseBody).setHeader("Content-Type", "application/json"));
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.consumeNextWith((accessLevel) -> assertThat(accessLevel).isEqualTo(AccessLevel.FULL)).expectComplete()
.verify();
expectRequest((request) -> {
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
.isEqualTo("bearer my-access-token");
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
});
}
@Test
public void getAccessLevelWhenNotSpaceDeveloperShouldReturnRestricted()
throws Exception {
public void getAccessLevelWhenNotSpaceDeveloperShouldReturnRestricted() throws Exception {
String responseBody = "{\"read_sensitive_data\": false,\"read_basic_data\": true}";
prepareResponse((response) -> response.setBody(responseBody)
.setHeader("Content-Type", "application/json"));
StepVerifier
.create(this.securityService.getAccessLevel("my-access-token",
"my-app-id"))
.consumeNextWith((accessLevel) -> assertThat(accessLevel)
.isEqualTo(AccessLevel.RESTRICTED))
prepareResponse((response) -> response.setBody(responseBody).setHeader("Content-Type", "application/json"));
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.consumeNextWith((accessLevel) -> assertThat(accessLevel).isEqualTo(AccessLevel.RESTRICTED))
.expectComplete().verify();
expectRequest((request) -> {
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
.isEqualTo("bearer my-access-token");
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
});
}
@@ -107,18 +94,14 @@ public class ReactiveCloudFoundrySecurityServiceTests {
@Test
public void getAccessLevelWhenTokenIsNotValidShouldThrowException() throws Exception {
prepareResponse((response) -> response.setResponseCode(401));
StepVerifier.create(
this.securityService.getAccessLevel("my-access-token", "my-app-id"))
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.consumeErrorWith((throwable) -> {
assertThat(throwable)
.isInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(
((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.INVALID_TOKEN);
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.INVALID_TOKEN);
}).verify();
expectRequest((request) -> {
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
.isEqualTo("bearer my-access-token");
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
});
}
@@ -126,45 +109,35 @@ public class ReactiveCloudFoundrySecurityServiceTests {
@Test
public void getAccessLevelWhenForbiddenShouldThrowException() throws Exception {
prepareResponse((response) -> response.setResponseCode(403));
StepVerifier.create(
this.securityService.getAccessLevel("my-access-token", "my-app-id"))
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.consumeErrorWith((throwable) -> {
assertThat(throwable)
.isInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(
((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.ACCESS_DENIED);
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.ACCESS_DENIED);
}).verify();
expectRequest((request) -> {
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
.isEqualTo("bearer my-access-token");
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
});
}
@Test
public void getAccessLevelWhenCloudControllerIsNotReachableThrowsException()
throws Exception {
public void getAccessLevelWhenCloudControllerIsNotReachableThrowsException() throws Exception {
prepareResponse((response) -> response.setResponseCode(500));
StepVerifier.create(
this.securityService.getAccessLevel("my-access-token", "my-app-id"))
StepVerifier.create(this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.consumeErrorWith((throwable) -> {
assertThat(throwable)
.isInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(
((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
}).verify();
expectRequest((request) -> {
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION))
.isEqualTo("bearer my-access-token");
assertThat(request.getHeader(HttpHeaders.AUTHORIZATION)).isEqualTo("bearer my-access-token");
assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER_PERMISSIONS);
});
}
@Test
public void fetchTokenKeysWhenSuccessfulShouldReturnListOfKeysFromUAA()
throws Exception {
public void fetchTokenKeysWhenSuccessfulShouldReturnListOfKeysFromUAA() throws Exception {
String tokenKeyValue = "-----BEGIN PUBLIC KEY-----\n"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0m59l2u9iDnMbrXHfqkO\n"
+ "rn2dVQ3vfBJqcDuFUK03d+1PZGbVlNCqnkpIJ8syFppW8ljnWweP7+LiWpRoz0I7\n"
@@ -177,20 +150,17 @@ public class ReactiveCloudFoundrySecurityServiceTests {
response.setBody("{\"token_endpoint\":\"/my-uaa.com\"}");
response.setHeader("Content-Type", "application/json");
});
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \""
+ tokenKeyValue.replace("\n", "\\n") + "\"} ]}";
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \"" + tokenKeyValue.replace("\n", "\\n")
+ "\"} ]}";
prepareResponse((response) -> {
response.setBody(responseBody);
response.setHeader("Content-Type", "application/json");
});
StepVerifier.create(this.securityService.fetchTokenKeys())
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys.get("test-key"))
.isEqualTo(tokenKeyValue))
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys.get("test-key")).isEqualTo(tokenKeyValue))
.expectComplete().verify();
expectRequest((request) -> assertThat(request.getPath())
.isEqualTo("/my-cloud-controller.com/info"));
expectRequest((request) -> assertThat(request.getPath())
.isEqualTo("/my-uaa.com/token_keys"));
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
}
@Test
@@ -205,12 +175,9 @@ public class ReactiveCloudFoundrySecurityServiceTests {
response.setHeader("Content-Type", "application/json");
});
StepVerifier.create(this.securityService.fetchTokenKeys())
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys).hasSize(0))
.expectComplete().verify();
expectRequest((request) -> assertThat(request.getPath())
.isEqualTo("/my-cloud-controller.com/info"));
expectRequest((request) -> assertThat(request.getPath())
.isEqualTo("/my-uaa.com/token_keys"));
.consumeNextWith((tokenKeys) -> assertThat(tokenKeys).hasSize(0)).expectComplete().verify();
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
}
@Test
@@ -221,14 +188,12 @@ public class ReactiveCloudFoundrySecurityServiceTests {
});
prepareResponse((response) -> response.setResponseCode(500));
StepVerifier.create(this.securityService.fetchTokenKeys())
.consumeErrorWith((throwable) -> assertThat(
((CloudFoundryAuthorizationException) throwable).getReason())
.consumeErrorWith(
(throwable) -> assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.SERVICE_UNAVAILABLE))
.verify();
expectRequest((request) -> assertThat(request.getPath())
.isEqualTo("/my-cloud-controller.com/info"));
expectRequest((request) -> assertThat(request.getPath())
.isEqualTo("/my-uaa.com/token_keys"));
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-cloud-controller.com/info"));
expectRequest((request) -> assertThat(request.getPath()).isEqualTo("/my-uaa.com/token_keys"));
}
@Test
@@ -238,29 +203,22 @@ public class ReactiveCloudFoundrySecurityServiceTests {
response.setHeader("Content-Type", "application/json");
});
StepVerifier.create(this.securityService.getUaaUrl())
.consumeNextWith((uaaUrl) -> assertThat(uaaUrl).isEqualTo(UAA_URL))
.expectComplete().verify();
.consumeNextWith((uaaUrl) -> assertThat(uaaUrl).isEqualTo(UAA_URL)).expectComplete().verify();
// this.securityService.getUaaUrl().block(); //FIXME subscribe again to check that
// it isn't called again
expectRequest((request) -> assertThat(request.getPath())
.isEqualTo(CLOUD_CONTROLLER + "/info"));
expectRequest((request) -> assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER + "/info"));
expectRequestCount(1);
}
@Test
public void getUaaUrlWhenCloudControllerUrlIsNotReachableShouldThrowException()
throws Exception {
public void getUaaUrlWhenCloudControllerUrlIsNotReachableShouldThrowException() throws Exception {
prepareResponse((response) -> response.setResponseCode(500));
StepVerifier.create(this.securityService.getUaaUrl())
.consumeErrorWith((throwable) -> {
assertThat(throwable)
.isInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(
((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
}).verify();
expectRequest((request) -> assertThat(request.getPath())
.isEqualTo(CLOUD_CONTROLLER + "/info"));
StepVerifier.create(this.securityService.getUaaUrl()).consumeErrorWith((throwable) -> {
assertThat(throwable).isInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) throwable).getReason())
.isEqualTo(Reason.SERVICE_UNAVAILABLE);
}).verify();
expectRequest((request) -> assertThat(request.getPath()).isEqualTo(CLOUD_CONTROLLER + "/info"));
}
private void prepareResponse(Consumer<MockResponse> consumer) {
@@ -269,8 +227,7 @@ public class ReactiveCloudFoundrySecurityServiceTests {
this.server.enqueue(response);
}
private void expectRequest(Consumer<RecordedRequest> consumer)
throws InterruptedException {
private void expectRequest(Consumer<RecordedRequest> consumer) throws InterruptedException {
consumer.accept(this.server.takeRequest());
}

View File

@@ -92,90 +92,66 @@ public class ReactiveTokenValidatorTests {
}
@Test
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException()
throws Exception {
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
.of(Mono.just(VALID_KEYS));
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException() throws Exception {
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", VALID_KEYS);
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{\"alg\": \"RS256\", \"kid\": \"invalid-key\",\"typ\": \"JWT\"}";
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.consumeErrorWith((ex) -> {
assertThat(ex).isExactlyInstanceOf(
CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.INVALID_KEY_ID);
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_KEY_ID);
}).verify();
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys",
VALID_KEYS);
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
fetchTokenKeys.assertWasSubscribed();
}
@Test
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt()
throws Exception {
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
.of(Mono.just(VALID_KEYS));
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys",
INVALID_KEYS);
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt() throws Exception {
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", INVALID_KEYS);
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.verifyComplete();
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys",
VALID_KEYS);
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
fetchTokenKeys.assertWasSubscribed();
}
@Test
public void validateTokenWhenCacheIsEmptyShouldFetchTokenKeys() throws Exception {
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
.of(Mono.just(VALID_KEYS));
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.verifyComplete();
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys",
VALID_KEYS);
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
fetchTokenKeys.assertWasSubscribed();
}
@Test
public void validateTokenWhenCacheEmptyAndInvalidKeyShouldThrowException()
throws Exception {
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe
.of(Mono.just(VALID_KEYS));
public void validateTokenWhenCacheEmptyAndInvalidKeyShouldThrowException() throws Exception {
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.of(Mono.just(VALID_KEYS));
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{\"alg\": \"RS256\", \"kid\": \"invalid-key\",\"typ\": \"JWT\"}";
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.consumeErrorWith((ex) -> {
assertThat(ex).isExactlyInstanceOf(
CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.INVALID_KEY_ID);
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_KEY_ID);
}).verify();
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys",
VALID_KEYS);
assertThat(this.tokenValidator).hasFieldOrPropertyWithValue("cachedTokenKeys", VALID_KEYS);
fetchTokenKeys.assertWasSubscribed();
}
@@ -184,13 +160,11 @@ public class ReactiveTokenValidatorTests {
PublisherProbe<Map<String, String>> fetchTokenKeys = PublisherProbe.empty();
ReflectionTestUtils.setField(this.tokenValidator, "cachedTokenKeys", VALID_KEYS);
given(this.securityService.fetchTokenKeys()).willReturn(fetchTokenKeys.mono());
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.verifyComplete();
fetchTokenKeys.assertWasNotSubscribed();
}
@@ -199,35 +173,28 @@ public class ReactiveTokenValidatorTests {
public void validateTokenWhenSignatureInvalidShouldThrowException() throws Exception {
Map<String, String> KEYS = Collections.singletonMap("valid-key", INVALID_KEY);
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(KEYS));
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.consumeErrorWith((ex) -> {
assertThat(ex).isExactlyInstanceOf(
CloudFoundryAuthorizationException.class);
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.INVALID_SIGNATURE);
}).verify();
}
@Test
public void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException()
throws Exception {
public void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException() throws Exception {
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(VALID_KEYS));
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{ \"alg\": \"HS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.consumeErrorWith((ex) -> {
assertThat(ex).isExactlyInstanceOf(
CloudFoundryAuthorizationException.class);
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM);
}).verify();
@@ -236,53 +203,41 @@ public class ReactiveTokenValidatorTests {
@Test
public void validateTokenWhenExpiredShouldThrowException() throws Exception {
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(VALID_KEYS));
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
String claims = "{ \"jti\": \"0236399c350c47f3ae77e67a75e75e7d\", \"exp\": 1477509977, \"scope\": [\"actuator.read\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.consumeErrorWith((ex) -> {
assertThat(ex).isExactlyInstanceOf(
CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.TOKEN_EXPIRED);
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.TOKEN_EXPIRED);
}).verify();
}
@Test
public void validateTokenWhenIssuerIsNotValidShouldThrowException() throws Exception {
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(VALID_KEYS));
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("https://other-uaa.com"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("https://other-uaa.com"));
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\", \"scope\": [\"actuator.read\"]}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.consumeErrorWith((ex) -> {
assertThat(ex).isExactlyInstanceOf(
CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.INVALID_ISSUER);
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason()).isEqualTo(Reason.INVALID_ISSUER);
}).verify();
}
@Test
public void validateTokenWhenAudienceIsNotValidShouldThrowException()
throws Exception {
public void validateTokenWhenAudienceIsNotValidShouldThrowException() throws Exception {
given(this.securityService.fetchTokenKeys()).willReturn(Mono.just(VALID_KEYS));
given(this.securityService.getUaaUrl())
.willReturn(Mono.just("http://localhost:8080/uaa"));
given(this.securityService.getUaaUrl()).willReturn(Mono.just("http://localhost:8080/uaa"));
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
StepVerifier
.create(this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.create(this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.consumeErrorWith((ex) -> {
assertThat(ex).isExactlyInstanceOf(
CloudFoundryAuthorizationException.class);
assertThat(ex).isExactlyInstanceOf(CloudFoundryAuthorizationException.class);
assertThat(((CloudFoundryAuthorizationException) ex).getReason())
.isEqualTo(Reason.INVALID_AUDIENCE);
}).verify();
@@ -292,17 +247,15 @@ public class ReactiveTokenValidatorTests {
PrivateKey privateKey = getPrivateKey();
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(privateKey);
byte[] content = dotConcat(Base64Utils.encodeUrlSafe(header),
Base64Utils.encode(claims));
byte[] content = dotConcat(Base64Utils.encodeUrlSafe(header), Base64Utils.encode(claims));
signature.update(content);
byte[] crypto = signature.sign();
byte[] token = dotConcat(Base64Utils.encodeUrlSafe(header),
Base64Utils.encodeUrlSafe(claims), Base64Utils.encodeUrlSafe(crypto));
byte[] token = dotConcat(Base64Utils.encodeUrlSafe(header), Base64Utils.encodeUrlSafe(claims),
Base64Utils.encodeUrlSafe(crypto));
return new String(token, StandardCharsets.UTF_8);
}
private PrivateKey getPrivateKey()
throws InvalidKeySpecException, NoSuchAlgorithmException {
private PrivateKey getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
String signingKey = "-----BEGIN PRIVATE KEY-----\n"
+ "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSbn2Xa72IOcxu\n"
+ "tcd+qQ6ufZ1VDe98EmpwO4VQrTd37U9kZtWU0KqeSkgnyzIWmlbyWOdbB4/v4uJa\n"

View File

@@ -69,108 +69,77 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class CloudFoundryActuatorAutoConfigurationTests {
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class,
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
RestTemplateAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
CloudFoundryActuatorAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
@Test
public void cloudFoundryPlatformActive() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils
.getField(handlerMapping, "endpointMapping");
assertThat(endpointMapping.getPath())
.isEqualTo("/cloudfoundryapplication");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
EndpointMapping endpointMapping = (EndpointMapping) ReflectionTestUtils.getField(handlerMapping,
"endpointMapping");
assertThat(endpointMapping.getPath()).isEqualTo("/cloudfoundryapplication");
CorsConfiguration corsConfiguration = (CorsConfiguration) ReflectionTestUtils
.getField(handlerMapping, "corsConfiguration");
assertThat(corsConfiguration.getAllowedOrigins()).contains("*");
assertThat(corsConfiguration.getAllowedMethods()).containsAll(
Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
assertThat(corsConfiguration.getAllowedMethods())
.containsAll(Arrays.asList(HttpMethod.GET.name(), HttpMethod.POST.name()));
assertThat(corsConfiguration.getAllowedHeaders())
.containsAll(Arrays.asList("Authorization",
"X-Cf-App-Instance", "Content-Type"));
.containsAll(Arrays.asList("Authorization", "X-Cf-App-Instance", "Content-Type"));
});
}
@Test
public void cloudfoundryapplicationProducesActuatorMediaType() throws Exception {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).build();
mockMvc.perform(get("/cloudfoundryapplication"))
.andExpect(header().string("Content-Type",
ActuatorMediaType.V2_JSON + ";charset=UTF-8"));
.andExpect(header().string("Content-Type", ActuatorMediaType.V2_JSON + ";charset=UTF-8"));
});
}
@Test
public void cloudFoundryPlatformActiveSetsApplicationId() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor");
String applicationId = (String) ReflectionTestUtils
.getField(interceptor, "applicationId");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
String applicationId = (String) ReflectionTestUtils.getField(interceptor, "applicationId");
assertThat(applicationId).isEqualTo("my-app-id");
});
}
@Test
public void cloudFoundryPlatformActiveSetsCloudControllerUrl() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils
.getField(interceptor, "cloudFoundrySecurityService");
String cloudControllerUrl = (String) ReflectionTestUtils
.getField(interceptorSecurityService, "cloudControllerUrl");
assertThat(cloudControllerUrl)
.isEqualTo("https://my-cloud-controller.com");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com").run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
"cloudFoundrySecurityService");
String cloudControllerUrl = (String) ReflectionTestUtils.getField(interceptorSecurityService,
"cloudControllerUrl");
assertThat(cloudControllerUrl).isEqualTo("https://my-cloud-controller.com");
});
}
@Test
public void skipSslValidation() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com",
"management.cloudfoundry.skip-ssl-validation:true")
.run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping,
"securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils
.getField(interceptor, "cloudFoundrySecurityService");
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
.getField(interceptorSecurityService, "restTemplate");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com",
"management.cloudfoundry.skip-ssl-validation:true").run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
Object interceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(interceptor,
"cloudFoundrySecurityService");
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils.getField(interceptorSecurityService,
"restTemplate");
assertThat(restTemplate.getRequestFactory())
.isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
});
@@ -178,26 +147,23 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test
public void cloudFoundryPlatformActiveAndCloudControllerUrlNotPresent() {
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id").run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Object securityInterceptor = ReflectionTestUtils
.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils
.getField(securityInterceptor, "cloudFoundrySecurityService");
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
.run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
Object securityInterceptor = ReflectionTestUtils.getField(handlerMapping, "securityInterceptor");
Object interceptorSecurityService = ReflectionTestUtils.getField(securityInterceptor,
"cloudFoundrySecurityService");
assertThat(interceptorSecurityService).isNull();
});
}
@Test
public void cloudFoundryPathsIgnoredBySpringSecurity() {
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id").run((context) -> {
this.contextRunner.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id")
.run((context) -> {
FilterChainProxy securityFilterChain = (FilterChainProxy) context
.getBean(BeanIds.SPRING_SECURITY_FILTER_CHAIN);
SecurityFilterChain chain = securityFilterChain.getFilterChains()
.get(0);
SecurityFilterChain chain = securityFilterChain.getFilterChains().get(0);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setServletPath("/cloudfoundryapplication/my-path");
assertThat(chain.getFilters()).isEmpty();
@@ -210,72 +176,54 @@ public class CloudFoundryActuatorAutoConfigurationTests {
@Test
public void cloudFoundryPlatformInactive() {
this.contextRunner.withPropertyValues()
.run((context) -> assertThat(context
.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
.isFalse());
.run((context) -> assertThat(context.containsBean("cloudFoundryWebEndpointServletHandlerMapping"))
.isFalse());
}
@Test
public void cloudFoundryManagementEndpointsDisabled() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION=---",
"management.cloudfoundry.enabled:false")
.run((context) -> assertThat(
context.containsBean("cloudFoundryEndpointHandlerMapping"))
.isFalse());
this.contextRunner.withPropertyValues("VCAP_APPLICATION=---", "management.cloudfoundry.enabled:false")
.run((context) -> assertThat(context.containsBean("cloudFoundryEndpointHandlerMapping")).isFalse());
}
@Test
public void allEndpointsAvailableUnderCloudFoundryWithoutExposeAllOnWeb() {
this.contextRunner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
this.contextRunner.withUserConfiguration(TestConfiguration.class).withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id", "vcap.application.cf_api:https://my-cloud-controller.com")
.run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping
.getEndpoints();
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
assertThat(endpoints.stream()
.filter((candidate) -> EndpointId.of("test")
.equals(candidate.getEndpointId()))
.findFirst()).isNotEmpty();
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst())
.isNotEmpty();
});
}
@Test
public void endpointPathCustomizationIsNotApplied() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com",
"management.endpoints.web.path-mapping.test=custom")
.withUserConfiguration(TestConfiguration.class).run((context) -> {
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(
context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping
.getEndpoints();
CloudFoundryWebEndpointServletHandlerMapping handlerMapping = getHandlerMapping(context);
Collection<ExposableWebEndpoint> endpoints = handlerMapping.getEndpoints();
ExposableWebEndpoint endpoint = endpoints.stream()
.filter((candidate) -> EndpointId.of("test")
.equals(candidate.getEndpointId()))
.findFirst().get();
.filter((candidate) -> EndpointId.of("test").equals(candidate.getEndpointId())).findFirst()
.get();
Collection<WebOperation> operations = endpoint.getOperations();
assertThat(operations).hasSize(1);
assertThat(
operations.iterator().next().getRequestPredicate().getPath())
.isEqualTo("test");
assertThat(operations.iterator().next().getRequestPredicate().getPath()).isEqualTo("test");
});
}
@Test
public void healthEndpointInvokerShouldBeCloudFoundryWebExtension() {
this.contextRunner
.withPropertyValues("VCAP_APPLICATION:---",
"vcap.application.application_id:my-app-id",
.withPropertyValues("VCAP_APPLICATION:---", "vcap.application.application_id:my-app-id",
"vcap.application.cf_api:https://my-cloud-controller.com")
.withConfiguration(
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class))
.run((context) -> {
Collection<ExposableWebEndpoint> endpoints = context
.getBean("cloudFoundryWebEndpointServletHandlerMapping",
@@ -283,30 +231,26 @@ public class CloudFoundryActuatorAutoConfigurationTests {
.getEndpoints();
ExposableWebEndpoint endpoint = endpoints.iterator().next();
assertThat(endpoint.getOperations()).hasSize(3);
WebOperation webOperation = findOperationWithRequestPath(endpoint,
"health");
Object invoker = ReflectionTestUtils.getField(webOperation,
"invoker");
WebOperation webOperation = findOperationWithRequestPath(endpoint, "health");
Object invoker = ReflectionTestUtils.getField(webOperation, "invoker");
assertThat(ReflectionTestUtils.getField(invoker, "target"))
.isInstanceOf(CloudFoundryHealthEndpointWebExtension.class);
});
}
private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping(
ApplicationContext context) {
private CloudFoundryWebEndpointServletHandlerMapping getHandlerMapping(ApplicationContext context) {
return context.getBean("cloudFoundryWebEndpointServletHandlerMapping",
CloudFoundryWebEndpointServletHandlerMapping.class);
}
private WebOperation findOperationWithRequestPath(ExposableWebEndpoint endpoint,
String requestPath) {
private WebOperation findOperationWithRequestPath(ExposableWebEndpoint endpoint, String requestPath) {
for (WebOperation operation : endpoint.getOperations()) {
if (operation.getRequestPredicate().getPath().equals(requestPath)) {
return operation;
}
}
throw new IllegalStateException("No operation found with request path "
+ requestPath + " from " + endpoint.getOperations());
throw new IllegalStateException(
"No operation found with request path " + requestPath + " from " + endpoint.getOperations());
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -45,18 +45,13 @@ public class CloudFoundryHealthEndpointWebExtensionTests {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withPropertyValues("VCAP_APPLICATION={}")
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class,
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class,
RestTemplateAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class,
CloudFoundryActuatorAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(SecurityAutoConfiguration.class, WebMvcAutoConfiguration.class,
JacksonAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
RestTemplateAutoConfiguration.class, ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class, CloudFoundryActuatorAutoConfiguration.class));
@Test
public void healthDetailsAlwaysPresent() {

View File

@@ -67,92 +67,74 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
private static TokenValidator tokenValidator = mock(TokenValidator.class);
private static CloudFoundrySecurityService securityService = mock(
CloudFoundrySecurityService.class);
private static CloudFoundrySecurityService securityService = mock(CloudFoundrySecurityService.class);
@Test
public void operationWithSecurityInterceptorForbidden() {
given(securityService.getAccessLevel(any(), eq("app-id")))
.willReturn(AccessLevel.RESTRICTED);
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
load(TestEndpointConfiguration.class,
(client) -> client.get().uri("/cfApplication/test")
.accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isEqualTo(HttpStatus.FORBIDDEN));
(client) -> client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
.isEqualTo(HttpStatus.FORBIDDEN));
}
@Test
public void operationWithSecurityInterceptorSuccess() {
given(securityService.getAccessLevel(any(), eq("app-id")))
.willReturn(AccessLevel.FULL);
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
load(TestEndpointConfiguration.class,
(client) -> client.get().uri("/cfApplication/test")
.accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isEqualTo(HttpStatus.OK));
(client) -> client.get().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
.isEqualTo(HttpStatus.OK));
}
@Test
public void responseToOptionsRequestIncludesCorsHeaders() {
load(TestEndpointConfiguration.class, (client) -> client.options()
.uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Access-Control-Request-Method", "POST")
.header("Origin", "https://example.com").exchange().expectStatus().isOk()
.expectHeader()
.valueEquals("Access-Control-Allow-Origin", "https://example.com")
.expectHeader().valueEquals("Access-Control-Allow-Methods", "GET,POST"));
load(TestEndpointConfiguration.class,
(client) -> client.options().uri("/cfApplication/test").accept(MediaType.APPLICATION_JSON)
.header("Access-Control-Request-Method", "POST").header("Origin", "https://example.com")
.exchange().expectStatus().isOk().expectHeader()
.valueEquals("Access-Control-Allow-Origin", "https://example.com").expectHeader()
.valueEquals("Access-Control-Allow-Methods", "GET,POST"));
}
@Test
public void linksToOtherEndpointsWithFullAccess() {
given(securityService.getAccessLevel(any(), eq("app-id")))
.willReturn(AccessLevel.FULL);
load(TestEndpointConfiguration.class, (client) -> client.get()
.uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isOk().expectBody().jsonPath("_links.length()")
.isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false)
.jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false)
.jsonPath("_links.env.href").isNotEmpty().jsonPath("_links.env.templated")
.isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
.jsonPath("_links.test.templated").isEqualTo(false)
.jsonPath("_links.test-part.href").isNotEmpty()
.jsonPath("_links.test-part.templated").isEqualTo(true));
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.FULL);
load(TestEndpointConfiguration.class,
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
.expectBody().jsonPath("_links.length()").isEqualTo(5).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env.href").isNotEmpty()
.jsonPath("_links.env.templated").isEqualTo(false).jsonPath("_links.test.href").isNotEmpty()
.jsonPath("_links.test.templated").isEqualTo(false).jsonPath("_links.test-part.href")
.isNotEmpty().jsonPath("_links.test-part.templated").isEqualTo(true));
}
@Test
public void linksToOtherEndpointsForbidden() {
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(
Reason.INVALID_TOKEN, "invalid-token");
CloudFoundryAuthorizationException exception = new CloudFoundryAuthorizationException(Reason.INVALID_TOKEN,
"invalid-token");
willThrow(exception).given(tokenValidator).validate(any());
load(TestEndpointConfiguration.class,
(client) -> client.get().uri("/cfApplication")
.accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isUnauthorized());
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus()
.isUnauthorized());
}
@Test
public void linksToOtherEndpointsWithRestrictedAccess() {
given(securityService.getAccessLevel(any(), eq("app-id")))
.willReturn(AccessLevel.RESTRICTED);
given(securityService.getAccessLevel(any(), eq("app-id"))).willReturn(AccessLevel.RESTRICTED);
load(TestEndpointConfiguration.class,
(client) -> client.get().uri("/cfApplication")
.accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange()
.expectStatus().isOk().expectBody().jsonPath("_links.length()")
.isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false)
.jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false)
.jsonPath("_links.env").doesNotExist().jsonPath("_links.test")
.doesNotExist().jsonPath("_links.test-part").doesNotExist());
(client) -> client.get().uri("/cfApplication").accept(MediaType.APPLICATION_JSON)
.header("Authorization", "bearer " + mockAccessToken()).exchange().expectStatus().isOk()
.expectBody().jsonPath("_links.length()").isEqualTo(2).jsonPath("_links.self.href").isNotEmpty()
.jsonPath("_links.self.templated").isEqualTo(false).jsonPath("_links.info.href").isNotEmpty()
.jsonPath("_links.info.templated").isEqualTo(false).jsonPath("_links.env").doesNotExist()
.jsonPath("_links.test").doesNotExist().jsonPath("_links.test-part").doesNotExist());
}
private AnnotationConfigServletWebServerApplicationContext createApplicationContext(
Class<?>... config) {
private AnnotationConfigServletWebServerApplicationContext createApplicationContext(Class<?>... config) {
return new AnnotationConfigServletWebServerApplicationContext(config);
}
@@ -161,13 +143,12 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
}
private void load(Class<?> configuration, Consumer<WebTestClient> clientConsumer) {
BiConsumer<ApplicationContext, WebTestClient> consumer = (context,
client) -> clientConsumer.accept(client);
AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(
configuration, CloudFoundryMvcConfiguration.class);
BiConsumer<ApplicationContext, WebTestClient> consumer = (context, client) -> clientConsumer.accept(client);
AnnotationConfigServletWebServerApplicationContext context = createApplicationContext(configuration,
CloudFoundryMvcConfiguration.class);
try {
consumer.accept(context, WebTestClient.bindToServer()
.baseUrl("http://localhost:" + getPort(context)).build());
consumer.accept(context,
WebTestClient.bindToServer().baseUrl("http://localhost:" + getPort(context)).build());
}
finally {
context.close();
@@ -186,8 +167,7 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
@Bean
public CloudFoundrySecurityInterceptor interceptor() {
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService,
"app-id");
return new CloudFoundrySecurityInterceptor(tokenValidator, securityService, "app-id");
}
@Bean
@@ -198,28 +178,23 @@ public class CloudFoundryMvcWebEndpointIntegrationTests {
@Bean
public CloudFoundryWebEndpointServletHandlerMapping cloudFoundryWebEndpointServletHandlerMapping(
WebEndpointDiscoverer webEndpointDiscoverer,
EndpointMediaTypes endpointMediaTypes,
WebEndpointDiscoverer webEndpointDiscoverer, EndpointMediaTypes endpointMediaTypes,
CloudFoundrySecurityInterceptor interceptor) {
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowedOrigins(Arrays.asList("https://example.com"));
corsConfiguration.setAllowedMethods(Arrays.asList("GET", "POST"));
return new CloudFoundryWebEndpointServletHandlerMapping(
new EndpointMapping("/cfApplication"),
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes,
corsConfiguration, interceptor,
return new CloudFoundryWebEndpointServletHandlerMapping(new EndpointMapping("/cfApplication"),
webEndpointDiscoverer.getEndpoints(), endpointMediaTypes, corsConfiguration, interceptor,
new EndpointLinksResolver(webEndpointDiscoverer.getEndpoints()));
}
@Bean
public WebEndpointDiscoverer webEndpointDiscoverer(
ApplicationContext applicationContext,
public WebEndpointDiscoverer webEndpointDiscoverer(ApplicationContext applicationContext,
EndpointMediaTypes endpointMediaTypes) {
ParameterValueMapper parameterMapper = new ConversionServiceParameterValueMapper(
DefaultConversionService.getSharedInstance());
return new WebEndpointDiscoverer(applicationContext, parameterMapper,
endpointMediaTypes, null, Collections.emptyList(),
Collections.emptyList());
return new WebEndpointDiscoverer(applicationContext, parameterMapper, endpointMediaTypes, null,
Collections.emptyList(), Collections.emptyList());
}
@Bean

View File

@@ -56,8 +56,7 @@ public class CloudFoundrySecurityInterceptorTests {
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
this.securityService, "my-app-id");
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, "my-app-id");
this.request = new MockHttpServletRequest();
}
@@ -66,58 +65,45 @@ public class CloudFoundrySecurityInterceptorTests {
this.request.setMethod("OPTIONS");
this.request.addHeader(HttpHeaders.ORIGIN, "https://example.com");
this.request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
SecurityResponse response = this.interceptor.preHandle(this.request,
EndpointId.of("test"));
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
}
@Test
public void preHandleWhenTokenIsMissingShouldReturnFalse() {
SecurityResponse response = this.interceptor.preHandle(this.request,
EndpointId.of("test"));
assertThat(response.getStatus())
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
}
@Test
public void preHandleWhenTokenIsNotBearerShouldReturnFalse() {
this.request.addHeader("Authorization", mockAccessToken());
SecurityResponse response = this.interceptor.preHandle(this.request,
EndpointId.of("test"));
assertThat(response.getStatus())
.isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
assertThat(response.getStatus()).isEqualTo(Reason.MISSING_AUTHORIZATION.getStatus());
}
@Test
public void preHandleWhenApplicationIdIsNullShouldReturnFalse() {
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator,
this.securityService, null);
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, this.securityService, null);
this.request.addHeader("Authorization", "bearer " + mockAccessToken());
SecurityResponse response = this.interceptor.preHandle(this.request,
EndpointId.of("test"));
assertThat(response.getStatus())
.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
assertThat(response.getStatus()).isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
}
@Test
public void preHandleWhenCloudFoundrySecurityServiceIsNullShouldReturnFalse() {
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null,
"my-app-id");
this.interceptor = new CloudFoundrySecurityInterceptor(this.tokenValidator, null, "my-app-id");
this.request.addHeader("Authorization", "bearer " + mockAccessToken());
SecurityResponse response = this.interceptor.preHandle(this.request,
EndpointId.of("test"));
assertThat(response.getStatus())
.isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
assertThat(response.getStatus()).isEqualTo(Reason.SERVICE_UNAVAILABLE.getStatus());
}
@Test
public void preHandleWhenAccessIsNotAllowedShouldReturnFalse() {
String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "bearer " + accessToken);
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.RESTRICTED);
SecurityResponse response = this.interceptor.preHandle(this.request,
EndpointId.of("test"));
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(AccessLevel.RESTRICTED);
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
assertThat(response.getStatus()).isEqualTo(Reason.ACCESS_DENIED.getStatus());
}
@@ -125,34 +111,28 @@ public class CloudFoundrySecurityInterceptorTests {
public void preHandleSuccessfulWithFullAccess() {
String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "Bearer " + accessToken);
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.FULL);
SecurityResponse response = this.interceptor.preHandle(this.request,
EndpointId.of("test"));
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(AccessLevel.FULL);
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("test"));
ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
Token token = tokenArgumentCaptor.getValue();
assertThat(token.toString()).isEqualTo(accessToken);
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
assertThat(this.request.getAttribute("cloudFoundryAccessLevel"))
.isEqualTo(AccessLevel.FULL);
assertThat(this.request.getAttribute("cloudFoundryAccessLevel")).isEqualTo(AccessLevel.FULL);
}
@Test
public void preHandleSuccessfulWithRestrictedAccess() {
String accessToken = mockAccessToken();
this.request.addHeader("Authorization", "Bearer " + accessToken);
given(this.securityService.getAccessLevel(accessToken, "my-app-id"))
.willReturn(AccessLevel.RESTRICTED);
SecurityResponse response = this.interceptor.preHandle(this.request,
EndpointId.of("info"));
given(this.securityService.getAccessLevel(accessToken, "my-app-id")).willReturn(AccessLevel.RESTRICTED);
SecurityResponse response = this.interceptor.preHandle(this.request, EndpointId.of("info"));
ArgumentCaptor<Token> tokenArgumentCaptor = ArgumentCaptor.forClass(Token.class);
verify(this.tokenValidator).validate(tokenArgumentCaptor.capture());
Token token = tokenArgumentCaptor.getValue();
assertThat(token.toString()).isEqualTo(accessToken);
assertThat(response.getStatus()).isEqualTo(HttpStatus.OK);
assertThat(this.request.getAttribute("cloudFoundryAccessLevel"))
.isEqualTo(AccessLevel.RESTRICTED);
assertThat(this.request.getAttribute("cloudFoundryAccessLevel")).isEqualTo(AccessLevel.RESTRICTED);
}
private String mockAccessToken() {

View File

@@ -51,8 +51,7 @@ public class CloudFoundrySecurityServiceTests {
private static final String CLOUD_CONTROLLER = "https://my-cloud-controller.com";
private static final String CLOUD_CONTROLLER_PERMISSIONS = CLOUD_CONTROLLER
+ "/v2/apps/my-app-id/permissions";
private static final String CLOUD_CONTROLLER_PERMISSIONS = CLOUD_CONTROLLER + "/v2/apps/my-app-id/permissions";
private static final String UAA_URL = "https://my-uaa.com";
@@ -64,31 +63,24 @@ public class CloudFoundrySecurityServiceTests {
public void setup() {
MockServerRestTemplateCustomizer mockServerCustomizer = new MockServerRestTemplateCustomizer();
RestTemplateBuilder builder = new RestTemplateBuilder(mockServerCustomizer);
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
false);
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER, false);
this.server = mockServerCustomizer.getServer();
}
@Test
public void skipSslValidationWhenTrue() {
RestTemplateBuilder builder = new RestTemplateBuilder();
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
true);
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
.getField(this.securityService, "restTemplate");
assertThat(restTemplate.getRequestFactory())
.isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER, true);
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils.getField(this.securityService, "restTemplate");
assertThat(restTemplate.getRequestFactory()).isInstanceOf(SkipSslVerificationHttpRequestFactory.class);
}
@Test
public void doNotskipSslValidationWhenFalse() {
RestTemplateBuilder builder = new RestTemplateBuilder();
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER,
false);
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils
.getField(this.securityService, "restTemplate");
assertThat(restTemplate.getRequestFactory())
.isNotInstanceOf(SkipSslVerificationHttpRequestFactory.class);
this.securityService = new CloudFoundrySecurityService(builder, CLOUD_CONTROLLER, false);
RestTemplate restTemplate = (RestTemplate) ReflectionTestUtils.getField(this.securityService, "restTemplate");
assertThat(restTemplate.getRequestFactory()).isNotInstanceOf(SkipSslVerificationHttpRequestFactory.class);
}
@Test
@@ -97,8 +89,7 @@ public class CloudFoundrySecurityServiceTests {
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
.andExpect(header("Authorization", "bearer my-access-token"))
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token",
"my-app-id");
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token", "my-app-id");
this.server.verify();
assertThat(accessLevel).isEqualTo(AccessLevel.FULL);
}
@@ -109,8 +100,7 @@ public class CloudFoundrySecurityServiceTests {
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
.andExpect(header("Authorization", "bearer my-access-token"))
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token",
"my-app-id");
AccessLevel accessLevel = this.securityService.getAccessLevel("my-access-token", "my-app-id");
this.server.verify();
assertThat(accessLevel).isEqualTo(AccessLevel.RESTRICTED);
}
@@ -118,10 +108,9 @@ public class CloudFoundrySecurityServiceTests {
@Test
public void getAccessLevelWhenTokenIsNotValidShouldThrowException() {
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
.andExpect(header("Authorization", "bearer my-access-token"))
.andRespond(withUnauthorizedRequest());
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.andExpect(header("Authorization", "bearer my-access-token")).andRespond(withUnauthorizedRequest());
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.satisfies(reasonRequirement(Reason.INVALID_TOKEN));
}
@@ -130,26 +119,24 @@ public class CloudFoundrySecurityServiceTests {
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
.andExpect(header("Authorization", "bearer my-access-token"))
.andRespond(withStatus(HttpStatus.FORBIDDEN));
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.satisfies(reasonRequirement(Reason.ACCESS_DENIED));
}
@Test
public void getAccessLevelWhenCloudControllerIsNotReachableThrowsException() {
this.server.expect(requestTo(CLOUD_CONTROLLER_PERMISSIONS))
.andExpect(header("Authorization", "bearer my-access-token"))
.andRespond(withServerError());
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.andExpect(header("Authorization", "bearer my-access-token")).andRespond(withServerError());
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.securityService.getAccessLevel("my-access-token", "my-app-id"))
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
}
@Test
public void fetchTokenKeysWhenSuccessfulShouldReturnListOfKeysFromUAA() {
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
.andRespond(withSuccess("{\"token_endpoint\":\"https://my-uaa.com\"}",
MediaType.APPLICATION_JSON));
.andRespond(withSuccess("{\"token_endpoint\":\"https://my-uaa.com\"}", MediaType.APPLICATION_JSON));
String tokenKeyValue = "-----BEGIN PUBLIC KEY-----\n"
+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0m59l2u9iDnMbrXHfqkO\n"
+ "rn2dVQ3vfBJqcDuFUK03d+1PZGbVlNCqnkpIJ8syFppW8ljnWweP7+LiWpRoz0I7\n"
@@ -158,8 +145,8 @@ public class CloudFoundrySecurityServiceTests {
+ "kqwIn7Glry9n9Suxygbf8g5AzpWcusZgDLIIZ7JTUldBb8qU2a0Dl4mvLZOn4wPo\n"
+ "jfj9Cw2QICsc5+Pwf21fP+hzf+1WSRHbnYv8uanRO0gZ8ekGaghM/2H6gqJbo2nI\n"
+ "JwIDAQAB\n-----END PUBLIC KEY-----";
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \""
+ tokenKeyValue.replace("\n", "\\n") + "\"} ]}";
String responseBody = "{\"keys\" : [ {\"kid\":\"test-key\",\"value\" : \"" + tokenKeyValue.replace("\n", "\\n")
+ "\"} ]}";
this.server.expect(requestTo(UAA_URL + "/token_keys"))
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
Map<String, String> tokenKeys = this.securityService.fetchTokenKeys();
@@ -169,8 +156,8 @@ public class CloudFoundrySecurityServiceTests {
@Test
public void fetchTokenKeysWhenNoKeysReturnedFromUAA() {
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withSuccess(
"{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
String responseBody = "{\"keys\": []}";
this.server.expect(requestTo(UAA_URL + "/token_keys"))
.andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON));
@@ -181,10 +168,9 @@ public class CloudFoundrySecurityServiceTests {
@Test
public void fetchTokenKeysWhenUnsuccessfulShouldThrowException() {
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withSuccess(
"{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
this.server.expect(requestTo(UAA_URL + "/token_keys"))
.andRespond(withServerError());
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
this.server.expect(requestTo(UAA_URL + "/token_keys")).andRespond(withServerError());
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.securityService.fetchTokenKeys())
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
@@ -192,8 +178,8 @@ public class CloudFoundrySecurityServiceTests {
@Test
public void getUaaUrlShouldCallCloudControllerInfoOnlyOnce() {
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withSuccess(
"{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
.andRespond(withSuccess("{\"token_endpoint\":\"" + UAA_URL + "\"}", MediaType.APPLICATION_JSON));
String uaaUrl = this.securityService.getUaaUrl();
this.server.verify();
assertThat(uaaUrl).isEqualTo(UAA_URL);
@@ -204,15 +190,13 @@ public class CloudFoundrySecurityServiceTests {
@Test
public void getUaaUrlWhenCloudControllerUrlIsNotReachableShouldThrowException() {
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info"))
.andRespond(withServerError());
this.server.expect(requestTo(CLOUD_CONTROLLER + "/info")).andRespond(withServerError());
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.securityService.getUaaUrl())
.satisfies(reasonRequirement(Reason.SERVICE_UNAVAILABLE));
}
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(
Reason reason) {
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(Reason reason) {
return (ex) -> assertThat(ex.getReason()).isEqualTo(reason);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,8 +54,7 @@ public class SkipSslVerificationHttpRequestFactoryTests {
SkipSslVerificationHttpRequestFactory requestFactory = new SkipSslVerificationHttpRequestFactory();
RestTemplate restTemplate = new RestTemplate(requestFactory);
RestTemplate otherRestTemplate = new RestTemplate();
ResponseEntity<String> responseEntity = restTemplate.getForEntity(httpsUrl,
String.class);
ResponseEntity<String> responseEntity = restTemplate.getForEntity(httpsUrl, String.class);
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThatExceptionOfType(ResourceAccessException.class)
.isThrownBy(() -> otherRestTemplate.getForEntity(httpsUrl, String.class))
@@ -65,8 +64,7 @@ public class SkipSslVerificationHttpRequestFactoryTests {
private String getHttpsUrl() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory(0);
factory.setSsl(getSsl("password", "classpath:test.jks"));
this.webServer = factory.getWebServer(
new ServletRegistrationBean<>(new ExampleServlet(), "/hello"));
this.webServer = factory.getWebServer(new ServletRegistrationBean<>(new ExampleServlet(), "/hello"));
this.webServer.start();
return "https://localhost:" + this.webServer.getPort() + "/hello";
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -79,11 +79,9 @@ public class TokenValidatorTests {
+ "r3F7aM9YpErzeYLrl0GhQr9BVJxOvXcVd4kmY+XkiCcrkyS1cnghnllh+LCwQu1s\n"
+ "YwIDAQAB\n-----END PUBLIC KEY-----";
private static final Map<String, String> INVALID_KEYS = Collections
.singletonMap("invalid-key", INVALID_KEY);
private static final Map<String, String> INVALID_KEYS = Collections.singletonMap("invalid-key", INVALID_KEY);
private static final Map<String, String> VALID_KEYS = Collections
.singletonMap("valid-key", VALID_KEY);
private static final Map<String, String> VALID_KEYS = Collections.singletonMap("valid-key", VALID_KEY);
@Before
public void setup() {
@@ -92,28 +90,24 @@ public class TokenValidatorTests {
}
@Test
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException()
throws Exception {
public void validateTokenWhenKidValidationFailsTwiceShouldThrowException() throws Exception {
ReflectionTestUtils.setField(this.tokenValidator, "tokenKeys", INVALID_KEYS);
given(this.securityService.fetchTokenKeys()).willReturn(INVALID_KEYS);
String header = "{\"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{\"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.satisfies(reasonRequirement(Reason.INVALID_KEY_ID));
}
@Test
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt()
throws Exception {
public void validateTokenWhenKidValidationSucceedsInTheSecondAttempt() throws Exception {
ReflectionTestUtils.setField(this.tokenValidator, "tokenKeys", INVALID_KEYS);
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes())));
this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes())));
verify(this.securityService).fetchTokenKeys();
}
@@ -123,8 +117,7 @@ public class TokenValidatorTests {
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes())));
this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes())));
verify(this.securityService).fetchTokenKeys();
}
@@ -134,8 +127,7 @@ public class TokenValidatorTests {
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes())));
this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes())));
verify(this.securityService, Mockito.never()).fetchTokenKeys();
}
@@ -146,21 +138,18 @@ public class TokenValidatorTests {
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\",\"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.satisfies(reasonRequirement(Reason.INVALID_SIGNATURE));
}
@Test
public void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException()
throws Exception {
public void validateTokenWhenTokenAlgorithmIsNotRS256ShouldThrowException() throws Exception {
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
String header = "{ \"alg\": \"HS256\", \"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"actuator.read\"]}";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.satisfies(reasonRequirement(Reason.UNSUPPORTED_TOKEN_SIGNING_ALGORITHM));
}
@@ -170,9 +159,8 @@ public class TokenValidatorTests {
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
String claims = "{ \"jti\": \"0236399c350c47f3ae77e67a75e75e7d\", \"exp\": 1477509977, \"scope\": [\"actuator.read\"]}";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.satisfies(reasonRequirement(Reason.TOKEN_EXPIRED));
}
@@ -182,22 +170,19 @@ public class TokenValidatorTests {
given(this.securityService.getUaaUrl()).willReturn("https://other-uaa.com");
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\", \"scope\": [\"actuator.read\"]}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\"}";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.satisfies(reasonRequirement(Reason.INVALID_ISSUER));
}
@Test
public void validateTokenWhenAudienceIsNotValidShouldThrowException()
throws Exception {
public void validateTokenWhenAudienceIsNotValidShouldThrowException() throws Exception {
given(this.securityService.fetchTokenKeys()).willReturn(VALID_KEYS);
given(this.securityService.getUaaUrl()).willReturn("http://localhost:8080/uaa");
String header = "{ \"alg\": \"RS256\", \"kid\": \"valid-key\", \"typ\": \"JWT\"}";
String claims = "{ \"exp\": 2147483647, \"iss\": \"http://localhost:8080/uaa/oauth/token\", \"scope\": [\"foo.bar\"]}";
assertThatExceptionOfType(CloudFoundryAuthorizationException.class)
.isThrownBy(() -> this.tokenValidator.validate(
new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
assertThatExceptionOfType(CloudFoundryAuthorizationException.class).isThrownBy(
() -> this.tokenValidator.validate(new Token(getSignedToken(header.getBytes(), claims.getBytes()))))
.satisfies(reasonRequirement(Reason.INVALID_AUDIENCE));
}
@@ -205,17 +190,15 @@ public class TokenValidatorTests {
PrivateKey privateKey = getPrivateKey();
Signature signature = Signature.getInstance("SHA256WithRSA");
signature.initSign(privateKey);
byte[] content = dotConcat(Base64Utils.encodeUrlSafe(header),
Base64Utils.encode(claims));
byte[] content = dotConcat(Base64Utils.encodeUrlSafe(header), Base64Utils.encode(claims));
signature.update(content);
byte[] crypto = signature.sign();
byte[] token = dotConcat(Base64Utils.encodeUrlSafe(header),
Base64Utils.encodeUrlSafe(claims), Base64Utils.encodeUrlSafe(crypto));
byte[] token = dotConcat(Base64Utils.encodeUrlSafe(header), Base64Utils.encodeUrlSafe(claims),
Base64Utils.encodeUrlSafe(crypto));
return new String(token, StandardCharsets.UTF_8);
}
private PrivateKey getPrivateKey()
throws InvalidKeySpecException, NoSuchAlgorithmException {
private PrivateKey getPrivateKey() throws InvalidKeySpecException, NoSuchAlgorithmException {
String signingKey = "-----BEGIN PRIVATE KEY-----\n"
+ "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDSbn2Xa72IOcxu\n"
+ "tcd+qQ6ufZ1VDe98EmpwO4VQrTd37U9kZtWU0KqeSkgnyzIWmlbyWOdbB4/v4uJa\n"
@@ -263,8 +246,7 @@ public class TokenValidatorTests {
return result.toByteArray();
}
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(
Reason reason) {
private Consumer<CloudFoundryAuthorizationException> reasonRequirement(Reason reason) {
return (ex) -> assertThat(ex.getReason()).isEqualTo(reason);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -31,21 +31,17 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ConditionsReportEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations
.of(ConditionsReportEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(ConditionsReportEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(ConditionsReportEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ConditionsReportEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner
.withPropertyValues("management.endpoint.conditions.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(ConditionsReportEndpoint.class));
this.contextRunner.withPropertyValues("management.endpoint.conditions.enabled:false")
.run((context) -> assertThat(context).doesNotHaveBean(ConditionsReportEndpoint.class));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,17 +47,14 @@ public class ConditionsReportEndpointTests {
@Test
public void invoke() {
new ApplicationContextRunner().withUserConfiguration(Config.class)
.run((context) -> {
ContextConditionEvaluation report = context
.getBean(ConditionsReportEndpoint.class)
.applicationConditionEvaluation().getContexts()
.get(context.getId());
assertThat(report.getPositiveMatches()).isEmpty();
assertThat(report.getNegativeMatches()).containsKey("a");
assertThat(report.getUnconditionalClasses()).contains("b");
assertThat(report.getExclusions()).contains("com.foo.Bar");
});
new ApplicationContextRunner().withUserConfiguration(Config.class).run((context) -> {
ContextConditionEvaluation report = context.getBean(ConditionsReportEndpoint.class)
.applicationConditionEvaluation().getContexts().get(context.getId());
assertThat(report.getPositiveMatches()).isEmpty();
assertThat(report.getNegativeMatches()).containsKey("a");
assertThat(report.getUnconditionalClasses()).contains("b");
assertThat(report.getExclusions()).contains("com.foo.Bar");
});
}
@Configuration
@@ -72,11 +69,9 @@ public class ConditionsReportEndpointTests {
@PostConstruct
public void setupAutoConfigurationReport() {
ConditionEvaluationReport report = ConditionEvaluationReport
.get(this.context.getBeanFactory());
ConditionEvaluationReport report = ConditionEvaluationReport.get(this.context.getBeanFactory());
report.recordEvaluationCandidates(Arrays.asList("a", "b"));
report.recordConditionEvaluation("a", mock(Condition.class),
mock(ConditionOutcome.class));
report.recordConditionEvaluation("a", mock(Condition.class), mock(ConditionOutcome.class));
report.recordExclusions(Collections.singletonList("com.foo.Bar"));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,22 +32,18 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ShutdownEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(ShutdownEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(ShutdownEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.withPropertyValues("management.endpoint.shutdown.enabled:true")
.run((context) -> assertThat(context)
.hasSingleBean(ShutdownEndpoint.class));
.run((context) -> assertThat(context).hasSingleBean(ShutdownEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner
.withPropertyValues("management.endpoint.shutdown.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(ShutdownEndpoint.class));
this.contextRunner.withPropertyValues("management.endpoint.shutdown.enabled:false")
.run((context) -> assertThat(context).doesNotHaveBean(ShutdownEndpoint.class));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -41,42 +41,35 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ConfigurationPropertiesReportEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations
.of(ConfigurationPropertiesReportEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(ConfigurationPropertiesReportEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.withUserConfiguration(Config.class)
.run(validateTestProperties("******", "654321"));
this.contextRunner.withUserConfiguration(Config.class).run(validateTestProperties("******", "654321"));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner
.withPropertyValues("management.endpoint.configprops.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(ConfigurationPropertiesReportEndpoint.class));
this.contextRunner.withPropertyValues("management.endpoint.configprops.enabled:false")
.run((context) -> assertThat(context).doesNotHaveBean(ConfigurationPropertiesReportEndpoint.class));
}
@Test
public void keysToSanitizeCanBeConfiguredViaTheEnvironment() {
this.contextRunner.withUserConfiguration(Config.class).withPropertyValues(
"management.endpoint.configprops.keys-to-sanitize: .*pass.*, property")
this.contextRunner.withUserConfiguration(Config.class)
.withPropertyValues("management.endpoint.configprops.keys-to-sanitize: .*pass.*, property")
.run(validateTestProperties("******", "******"));
}
private ContextConsumer<AssertableApplicationContext> validateTestProperties(
String dbPassword, String myTestProperty) {
private ContextConsumer<AssertableApplicationContext> validateTestProperties(String dbPassword,
String myTestProperty) {
return (context) -> {
assertThat(context)
.hasSingleBean(ConfigurationPropertiesReportEndpoint.class);
assertThat(context).hasSingleBean(ConfigurationPropertiesReportEndpoint.class);
ConfigurationPropertiesReportEndpoint endpoint = context
.getBean(ConfigurationPropertiesReportEndpoint.class);
ApplicationConfigurationProperties properties = endpoint
.configurationProperties();
Map<String, Object> nestedProperties = properties.getContexts()
.get(context.getId()).getBeans().get("testProperties")
.getProperties();
ApplicationConfigurationProperties properties = endpoint.configurationProperties();
Map<String, Object> nestedProperties = properties.getContexts().get(context.getId()).getBeans()
.get("testProperties").getProperties();
assertThat(nestedProperties).isNotNull();
assertThat(nestedProperties.get("dbPassword")).isEqualTo(dbPassword);
assertThat(nestedProperties.get("myTestProperty")).isEqualTo(myTestProperty);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,14 +39,12 @@ import static org.mockito.Mockito.mock;
public class CouchbaseHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(CouchbaseMockConfiguration.class).withConfiguration(
AutoConfigurations.of(CouchbaseHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
.withUserConfiguration(CouchbaseMockConfiguration.class).withConfiguration(AutoConfigurations
.of(CouchbaseHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(CouchbaseHealthIndicator.class)
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CouchbaseHealthIndicator.class)
.doesNotHaveBean(CouchbaseReactiveHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@@ -54,8 +52,7 @@ public class CouchbaseHealthIndicatorAutoConfigurationTests {
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.couchbase.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(CouchbaseHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,24 +38,19 @@ import static org.mockito.Mockito.mock;
public class CouchbaseReactiveHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(CouchbaseMockConfiguration.class)
.withConfiguration(AutoConfigurations.of(
CouchbaseReactiveHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
.withUserConfiguration(CouchbaseMockConfiguration.class).withConfiguration(AutoConfigurations.of(
CouchbaseReactiveHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(CouchbaseReactiveHealthIndicator.class)
.doesNotHaveBean(CouchbaseHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CouchbaseReactiveHealthIndicator.class)
.doesNotHaveBean(CouchbaseHealthIndicator.class).doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.couchbase.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(CouchbaseReactiveHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseReactiveHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,19 +42,15 @@ import static org.mockito.Mockito.mock;
*/
public class ElasticsearchHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ElasticsearchAutoConfiguration.class,
ElasticSearchClientHealthIndicatorAutoConfiguration.class,
ElasticSearchJestHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(AutoConfigurations
.of(ElasticsearchAutoConfiguration.class, ElasticSearchClientHealthIndicatorAutoConfiguration.class,
ElasticSearchJestHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner
.withPropertyValues("spring.data.elasticsearch.cluster-nodes:localhost:0")
this.contextRunner.withPropertyValues("spring.data.elasticsearch.cluster-nodes:localhost:0")
.withSystemProperties("es.set.netty.runtime.available.processors=false")
.run((context) -> assertThat(context)
.hasSingleBean(ElasticsearchHealthIndicator.class)
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchHealthIndicator.class)
.doesNotHaveBean(ElasticsearchJestHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@@ -63,18 +59,15 @@ public class ElasticsearchHealthIndicatorAutoConfigurationTests {
public void runWhenUsingJestClientShouldCreateIndicator() {
this.contextRunner.withUserConfiguration(JestClientConfiguration.class)
.withSystemProperties("es.set.netty.runtime.available.processors=false")
.run((context) -> assertThat(context)
.hasSingleBean(ElasticsearchJestHealthIndicator.class)
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchJestHealthIndicator.class)
.doesNotHaveBean(ElasticsearchHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner
.withPropertyValues("management.health.elasticsearch.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(ElasticsearchHealthIndicator.class)
this.contextRunner.withPropertyValues("management.health.elasticsearch.enabled:false")
.run((context) -> assertThat(context).doesNotHaveBean(ElasticsearchHealthIndicator.class)
.doesNotHaveBean(ElasticsearchJestHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,8 +35,7 @@ public class EndpointIdTimeToLivePropertyFunctionTests {
private final MockEnvironment environment = new MockEnvironment();
private final Function<EndpointId, Long> timeToLive = new EndpointIdTimeToLivePropertyFunction(
this.environment);
private final Function<EndpointId, Long> timeToLive = new EndpointIdTimeToLivePropertyFunction(this.environment);
@Test
public void defaultConfiguration() {
@@ -46,16 +45,14 @@ public class EndpointIdTimeToLivePropertyFunctionTests {
@Test
public void userConfiguration() {
this.environment.setProperty("management.endpoint.test.cache.time-to-live",
"500");
this.environment.setProperty("management.endpoint.test.cache.time-to-live", "500");
Long result = this.timeToLive.apply(EndpointId.of("test"));
assertThat(result).isEqualTo(500L);
}
@Test
public void mixedCaseUserConfiguration() {
this.environment.setProperty(
"management.endpoint.another-test.cache.time-to-live", "500");
this.environment.setProperty("management.endpoint.another-test.cache.time-to-live", "500");
Long result = this.timeToLive.apply(EndpointId.of("anotherTest"));
assertThat(result).isEqualTo(500L);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -48,32 +48,28 @@ public class ExposeExcludePropertyEndpointFilterTests {
@Test
public void createWhenEndpointTypeIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(null,
new MockEnvironment(), "foo"))
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(null, new MockEnvironment(), "foo"))
.withMessageContaining("EndpointType must not be null");
}
@Test
public void createWhenEnvironmentIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(
ExposableEndpoint.class, null, "foo"))
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(ExposableEndpoint.class, null, "foo"))
.withMessageContaining("Environment must not be null");
}
@Test
public void createWhenPrefixIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(
ExposableEndpoint.class, new MockEnvironment(), null))
assertThatIllegalArgumentException().isThrownBy(
() -> new ExposeExcludePropertyEndpointFilter<>(ExposableEndpoint.class, new MockEnvironment(), null))
.withMessageContaining("Prefix must not be empty");
}
@Test
public void createWhenPrefixIsEmptyShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new ExposeExcludePropertyEndpointFilter<>(
ExposableEndpoint.class, new MockEnvironment(), ""))
assertThatIllegalArgumentException().isThrownBy(
() -> new ExposeExcludePropertyEndpointFilter<>(ExposableEndpoint.class, new MockEnvironment(), ""))
.withMessageContaining("Prefix must not be empty");
}
@@ -124,8 +120,8 @@ public class ExposeExcludePropertyEndpointFilterTests {
MockEnvironment environment = new MockEnvironment();
environment.setProperty("foo.include", "bar");
environment.setProperty("foo.exclude", "");
this.filter = new ExposeExcludePropertyEndpointFilter<>(
DifferentTestExposableWebEndpoint.class, environment, "foo");
this.filter = new ExposeExcludePropertyEndpointFilter<>(DifferentTestExposableWebEndpoint.class, environment,
"foo");
assertThat(match(EndpointId.of("baz"))).isTrue();
}
@@ -155,8 +151,8 @@ public class ExposeExcludePropertyEndpointFilterTests {
MockEnvironment environment = new MockEnvironment();
environment.setProperty("foo.include", include);
environment.setProperty("foo.exclude", exclude);
this.filter = new ExposeExcludePropertyEndpointFilter<>(
TestExposableWebEndpoint.class, environment, "foo", "def");
this.filter = new ExposeExcludePropertyEndpointFilter<>(TestExposableWebEndpoint.class, environment, "foo",
"def");
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -166,13 +162,11 @@ public class ExposeExcludePropertyEndpointFilterTests {
return ((EndpointFilter) this.filter).match(endpoint);
}
private abstract static class TestExposableWebEndpoint
implements ExposableWebEndpoint {
private abstract static class TestExposableWebEndpoint implements ExposableWebEndpoint {
}
private abstract static class DifferentTestExposableWebEndpoint
implements ExposableWebEndpoint {
private abstract static class DifferentTestExposableWebEndpoint implements ExposableWebEndpoint {
}

View File

@@ -41,8 +41,7 @@ public class ConditionalOnEnabledEndpointTests {
@Test
public void outcomeWhenEndpointEnabledPropertyIsTrueShouldMatch() {
this.contextRunner.withPropertyValues("management.endpoint.foo.enabled=true")
.withUserConfiguration(
FooEndpointEnabledByDefaultFalseConfiguration.class)
.withUserConfiguration(FooEndpointEnabledByDefaultFalseConfiguration.class)
.run((context) -> assertThat(context).hasBean("foo"));
}
@@ -55,51 +54,40 @@ public class ConditionalOnEnabledEndpointTests {
@Test
public void outcomeWhenNoEndpointPropertyAndUserDefinedDefaultIsTrueShouldMatch() {
this.contextRunner
.withPropertyValues("management.endpoints.enabled-by-default=true")
.withUserConfiguration(
FooEndpointEnabledByDefaultFalseConfiguration.class)
this.contextRunner.withPropertyValues("management.endpoints.enabled-by-default=true")
.withUserConfiguration(FooEndpointEnabledByDefaultFalseConfiguration.class)
.run((context) -> assertThat(context).hasBean("foo"));
}
@Test
public void outcomeWhenNoEndpointPropertyAndUserDefinedDefaultIsFalseShouldNotMatch() {
this.contextRunner
.withPropertyValues("management.endpoints.enabled-by-default=false")
this.contextRunner.withPropertyValues("management.endpoints.enabled-by-default=false")
.withUserConfiguration(FooEndpointEnabledByDefaultTrueConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean("foo"));
}
@Test
public void outcomeWhenNoPropertiesAndAnnotationIsEnabledByDefaultShouldMatch() {
this.contextRunner
.withUserConfiguration(FooEndpointEnabledByDefaultTrueConfiguration.class)
this.contextRunner.withUserConfiguration(FooEndpointEnabledByDefaultTrueConfiguration.class)
.run((context) -> assertThat(context).hasBean("foo"));
}
@Test
public void outcomeWhenNoPropertiesAndAnnotationIsNotEnabledByDefaultShouldNotMatch() {
this.contextRunner
.withUserConfiguration(
FooEndpointEnabledByDefaultFalseConfiguration.class)
this.contextRunner.withUserConfiguration(FooEndpointEnabledByDefaultFalseConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean("foo"));
}
@Test
public void outcomeWhenNoPropertiesAndExtensionAnnotationIsEnabledByDefaultShouldMatch() {
this.contextRunner
.withUserConfiguration(
FooEndpointAndExtensionEnabledByDefaultTrueConfiguration.class)
this.contextRunner.withUserConfiguration(FooEndpointAndExtensionEnabledByDefaultTrueConfiguration.class)
.run((context) -> assertThat(context).hasBean("foo").hasBean("fooExt"));
}
@Test
public void outcomeWhenNoPropertiesAndExtensionAnnotationIsNotEnabledByDefaultShouldNotMatch() {
this.contextRunner
.withUserConfiguration(
FooEndpointAndExtensionEnabledByDefaultFalseConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean("foo")
.doesNotHaveBean("fooExt"));
this.contextRunner.withUserConfiguration(FooEndpointAndExtensionEnabledByDefaultFalseConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean("foo").doesNotHaveBean("fooExt"));
}
@Test
@@ -128,31 +116,25 @@ public class ConditionalOnEnabledEndpointTests {
@Test
public void outcomeWithNoReferenceShouldFail() {
this.contextRunner
.withUserConfiguration(
ComponentWithNoEndpointReferenceConfiguration.class)
.run((context) -> {
assertThat(context).hasFailed();
assertThat(context.getStartupFailure().getCause().getMessage())
.contains(
"No endpoint is specified and the return type of the @Bean method "
+ "is neither an @Endpoint, nor an @EndpointExtension");
});
this.contextRunner.withUserConfiguration(ComponentWithNoEndpointReferenceConfiguration.class).run((context) -> {
assertThat(context).hasFailed();
assertThat(context.getStartupFailure().getCause().getMessage())
.contains("No endpoint is specified and the return type of the @Bean method "
+ "is neither an @Endpoint, nor an @EndpointExtension");
});
}
@Test
public void outcomeWhenEndpointEnabledPropertyIsTrueAndMixedCaseShouldMatch() {
this.contextRunner.withPropertyValues("management.endpoint.foo-bar.enabled=true")
.withUserConfiguration(
FooBarEndpointEnabledByDefaultFalseConfiguration.class)
.withUserConfiguration(FooBarEndpointEnabledByDefaultFalseConfiguration.class)
.run((context) -> assertThat(context).hasBean("fooBar"));
}
@Test
public void outcomeWhenEndpointEnabledPropertyIsFalseOnClassShouldNotMatch() {
this.contextRunner.withPropertyValues("management.endpoint.foo.enabled=false")
.withUserConfiguration(
FooEndpointEnabledByDefaultTrueOnConfigurationConfiguration.class)
.withUserConfiguration(FooEndpointEnabledByDefaultTrueOnConfigurationConfiguration.class)
.run((context) -> assertThat(context).doesNotHaveBean("foo"));
}
@@ -171,14 +153,12 @@ public class ConditionalOnEnabledEndpointTests {
}
@EndpointExtension(endpoint = FooEndpointEnabledByDefaultTrue.class,
filter = TestFilter.class)
@EndpointExtension(endpoint = FooEndpointEnabledByDefaultTrue.class, filter = TestFilter.class)
static class FooEndpointExtensionEnabledByDefaultTrue {
}
@EndpointExtension(endpoint = FooEndpointEnabledByDefaultFalse.class,
filter = TestFilter.class)
@EndpointExtension(endpoint = FooEndpointEnabledByDefaultFalse.class, filter = TestFilter.class)
static class FooEndpointExtensionEnabledByDefaultFalse {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,8 +43,7 @@ public class DefaultEndpointObjectNameFactoryTests {
private final MockEnvironment environment = new MockEnvironment();
private final JmxEndpointProperties properties = new JmxEndpointProperties(
this.environment);
private final JmxEndpointProperties properties = new JmxEndpointProperties(this.environment);
private final MBeanServer mBeanServer = mock(MBeanServer.class);
@@ -53,24 +52,20 @@ public class DefaultEndpointObjectNameFactoryTests {
@Test
public void generateObjectName() {
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
assertThat(objectName.toString())
.isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
assertThat(objectName.toString()).isEqualTo("org.springframework.boot:type=Endpoint,name=Test");
}
@Test
public void generateObjectNameWithCapitalizedId() {
ObjectName objectName = generateObjectName(
endpoint(EndpointId.of("testEndpoint")));
assertThat(objectName.toString())
.isEqualTo("org.springframework.boot:type=Endpoint,name=TestEndpoint");
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("testEndpoint")));
assertThat(objectName.toString()).isEqualTo("org.springframework.boot:type=Endpoint,name=TestEndpoint");
}
@Test
public void generateObjectNameWithCustomDomain() {
this.properties.setDomain("com.example.acme");
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
assertThat(objectName.toString())
.isEqualTo("com.example.acme:type=Endpoint,name=Test");
assertThat(objectName.toString()).isEqualTo("com.example.acme:type=Endpoint,name=Test");
}
@Test
@@ -90,8 +85,7 @@ public class DefaultEndpointObjectNameFactoryTests {
ExposableJmxEndpoint endpoint = endpoint(EndpointId.of("test"));
String id = ObjectUtils.getIdentityHexString(endpoint);
ObjectName objectName = generateObjectName(endpoint);
assertThat(objectName.toString()).isEqualTo(
"org.springframework.boot:type=Endpoint,name=Test,identity=" + id);
assertThat(objectName.toString()).isEqualTo("org.springframework.boot:type=Endpoint,name=Test,identity=" + id);
}
@Test
@@ -99,8 +93,7 @@ public class DefaultEndpointObjectNameFactoryTests {
public void generateObjectNameWithUniqueNamesDeprecatedPropertyMismatchMainProperty() {
this.environment.setProperty("spring.jmx.unique-names", "false");
this.properties.setUniqueNames(true);
assertThatIllegalArgumentException()
.isThrownBy(() -> generateObjectName(endpoint(EndpointId.of("test"))))
assertThatIllegalArgumentException().isThrownBy(() -> generateObjectName(endpoint(EndpointId.of("test"))))
.withMessageContaining("spring.jmx.unique-names")
.withMessageContaining("management.endpoints.jmx.unique-names");
}
@@ -112,28 +105,24 @@ public class DefaultEndpointObjectNameFactoryTests {
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
assertThat(objectName.getKeyProperty("counter")).isEqualTo("42");
assertThat(objectName.getKeyProperty("foo")).isEqualTo("bar");
assertThat(objectName.toString())
.startsWith("org.springframework.boot:type=Endpoint,name=Test,");
assertThat(objectName.toString()).startsWith("org.springframework.boot:type=Endpoint,name=Test,");
}
@Test
public void generateObjectNameWithDuplicate() throws MalformedObjectNameException {
this.contextId = "testContext";
given(this.mBeanServer.queryNames(
new ObjectName("org.springframework.boot:type=Endpoint,name=Test,*"),
null)).willReturn(
Collections.singleton(new ObjectName(
"org.springframework.boot:type=Endpoint,name=Test")));
given(this.mBeanServer.queryNames(new ObjectName("org.springframework.boot:type=Endpoint,name=Test,*"), null))
.willReturn(Collections.singleton(new ObjectName("org.springframework.boot:type=Endpoint,name=Test")));
ObjectName objectName = generateObjectName(endpoint(EndpointId.of("test")));
assertThat(objectName.toString()).isEqualTo(
"org.springframework.boot:type=Endpoint,name=Test,context=testContext");
assertThat(objectName.toString())
.isEqualTo("org.springframework.boot:type=Endpoint,name=Test,context=testContext");
}
private ObjectName generateObjectName(ExposableJmxEndpoint endpoint) {
try {
return new DefaultEndpointObjectNameFactory(this.properties, this.environment,
this.mBeanServer, this.contextId).getObjectName(endpoint);
return new DefaultEndpointObjectNameFactory(this.properties, this.environment, this.mBeanServer,
this.contextId).getObjectName(endpoint);
}
catch (MalformedObjectNameException ex) {
throw new AssertionError("Invalid object name", ex);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -34,34 +34,31 @@ public class MappingWebEndpointPathMapperTests {
@Test
public void defaultConfiguration() {
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
Collections.emptyMap());
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
EndpointId.of("test"))).isEqualTo("test");
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(Collections.emptyMap());
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper), EndpointId.of("test"))).isEqualTo("test");
}
@Test
public void userConfiguration() {
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
Collections.singletonMap("test", "custom"));
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
EndpointId.of("test"))).isEqualTo("custom");
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper), EndpointId.of("test")))
.isEqualTo("custom");
}
@Test
public void mixedCaseDefaultConfiguration() {
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
Collections.emptyMap());
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
EndpointId.of("testEndpoint"))).isEqualTo("testEndpoint");
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(Collections.emptyMap());
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper), EndpointId.of("testEndpoint")))
.isEqualTo("testEndpoint");
}
@Test
public void mixedCaseUserConfiguration() {
MappingWebEndpointPathMapper mapper = new MappingWebEndpointPathMapper(
Collections.singletonMap("test-endpoint", "custom"));
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper),
EndpointId.of("testEndpoint"))).isEqualTo("custom");
assertThat(PathMapper.getRootPath(Collections.singletonList(mapper), EndpointId.of("testEndpoint")))
.isEqualTo("custom");
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,20 +52,17 @@ public class ServletEndpointManagementContextConfigurationTests {
FilteredClassLoader classLoader = new FilteredClassLoader(ResourceConfig.class);
this.contextRunner.withClassLoader(classLoader).run((context) -> {
assertThat(context).hasSingleBean(ServletEndpointRegistrar.class);
ServletEndpointRegistrar bean = context
.getBean(ServletEndpointRegistrar.class);
ServletEndpointRegistrar bean = context.getBean(ServletEndpointRegistrar.class);
assertThat(bean).hasFieldOrPropertyWithValue("basePath", "/test/actuator");
});
}
@Test
public void contextWhenJerseyShouldContainServletEndpointRegistrar() {
FilteredClassLoader classLoader = new FilteredClassLoader(
DispatcherServlet.class);
FilteredClassLoader classLoader = new FilteredClassLoader(DispatcherServlet.class);
this.contextRunner.withClassLoader(classLoader).run((context) -> {
assertThat(context).hasSingleBean(ServletEndpointRegistrar.class);
ServletEndpointRegistrar bean = context
.getBean(ServletEndpointRegistrar.class);
ServletEndpointRegistrar bean = context.getBean(ServletEndpointRegistrar.class);
assertThat(bean).hasFieldOrPropertyWithValue("basePath", "/jersey/actuator");
});
}
@@ -73,8 +70,7 @@ public class ServletEndpointManagementContextConfigurationTests {
@Test
public void contextWhenNoServletBasedShouldNotContainServletEndpointRegistrar() {
new ApplicationContextRunner().withUserConfiguration(TestConfig.class)
.run((context) -> assertThat(context)
.doesNotHaveBean(ServletEndpointRegistrar.class));
.run((context) -> assertThat(context).doesNotHaveBean(ServletEndpointRegistrar.class));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,8 +51,8 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class WebEndpointAutoConfigurationTests {
private static final AutoConfigurations CONFIGURATIONS = AutoConfigurations
.of(EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class);
private static final AutoConfigurations CONFIGURATIONS = AutoConfigurations.of(EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class);
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(CONFIGURATIONS);
@@ -60,22 +60,17 @@ public class WebEndpointAutoConfigurationTests {
@Test
public void webApplicationConfiguresEndpointMediaTypes() {
this.contextRunner.run((context) -> {
EndpointMediaTypes endpointMediaTypes = context
.getBean(EndpointMediaTypes.class);
assertThat(endpointMediaTypes.getConsumed())
.containsExactly(ActuatorMediaType.V2_JSON, "application/json");
EndpointMediaTypes endpointMediaTypes = context.getBean(EndpointMediaTypes.class);
assertThat(endpointMediaTypes.getConsumed()).containsExactly(ActuatorMediaType.V2_JSON, "application/json");
});
}
@Test
public void webApplicationConfiguresPathMapper() {
this.contextRunner
.withPropertyValues(
"management.endpoints.web.path-mapping.health=healthcheck")
this.contextRunner.withPropertyValues("management.endpoints.web.path-mapping.health=healthcheck")
.run((context) -> {
assertThat(context).hasSingleBean(PathMapper.class);
String pathMapping = context.getBean(PathMapper.class)
.getRootPath(EndpointId.of("health"));
String pathMapping = context.getBean(PathMapper.class).getRootPath(EndpointId.of("health"));
assertThat(pathMapping).isEqualTo("healthcheck");
});
}
@@ -85,17 +80,13 @@ public class WebEndpointAutoConfigurationTests {
this.contextRunner
.withPropertyValues("management.endpoints.web.exposure.include=*",
"management.endpoints.web.path-mapping.testanotherone=foo")
.withUserConfiguration(TestPathMatcher.class, TestOneEndpoint.class,
TestAnotherOneEndpoint.class, TestTwoEndpoint.class)
.withUserConfiguration(TestPathMatcher.class, TestOneEndpoint.class, TestAnotherOneEndpoint.class,
TestTwoEndpoint.class)
.run((context) -> {
WebEndpointDiscoverer discoverer = context
.getBean(WebEndpointDiscoverer.class);
Collection<ExposableWebEndpoint> endpoints = discoverer
.getEndpoints();
ExposableWebEndpoint[] webEndpoints = endpoints
.toArray(new ExposableWebEndpoint[0]);
List<String> paths = Arrays.stream(webEndpoints)
.map(PathMappedEndpoint::getRootPath)
WebEndpointDiscoverer discoverer = context.getBean(WebEndpointDiscoverer.class);
Collection<ExposableWebEndpoint> endpoints = discoverer.getEndpoints();
ExposableWebEndpoint[] webEndpoints = endpoints.toArray(new ExposableWebEndpoint[0]);
List<String> paths = Arrays.stream(webEndpoints).map(PathMappedEndpoint::getRootPath)
.collect(Collectors.toList());
assertThat(paths).containsOnly("1/testone", "foo", "testtwo");
});
@@ -111,23 +102,20 @@ public class WebEndpointAutoConfigurationTests {
@Test
public void webApplicationConfiguresExposeExcludePropertyEndpointFilter() {
this.contextRunner.run((context) -> assertThat(context)
.getBeans(ExposeExcludePropertyEndpointFilter.class)
.containsKeys("webExposeExcludePropertyEndpointFilter",
"controllerExposeExcludePropertyEndpointFilter"));
this.contextRunner
.run((context) -> assertThat(context).getBeans(ExposeExcludePropertyEndpointFilter.class).containsKeys(
"webExposeExcludePropertyEndpointFilter", "controllerExposeExcludePropertyEndpointFilter"));
}
@Test
public void contextShouldConfigureServletEndpointDiscoverer() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(ServletEndpointDiscoverer.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ServletEndpointDiscoverer.class));
}
@Test
public void contextWhenNotServletShouldNotConfigureServletEndpointDiscoverer() {
new ApplicationContextRunner().withConfiguration(CONFIGURATIONS)
.run((context) -> assertThat(context)
.doesNotHaveBean(ServletEndpointDiscoverer.class));
.run((context) -> assertThat(context).doesNotHaveBean(ServletEndpointDiscoverer.class));
}
@Component

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,8 +46,7 @@ public class WebEndpointPropertiesTests {
@Test
public void basePathMustStartWithSlash() {
WebEndpointProperties properties = new WebEndpointProperties();
assertThatIllegalArgumentException()
.isThrownBy(() -> properties.setBasePath("admin"))
assertThatIllegalArgumentException().isThrownBy(() -> properties.setBasePath("admin"))
.withMessageContaining("Base path must start with '/' or be empty");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,15 +56,12 @@ import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWit
* @author Andy Wilkinson
*/
@TestPropertySource(properties = { "spring.jackson.serialization.indent_output=true",
"management.endpoints.web.exposure.include=*",
"spring.jackson.default-property-inclusion=non_null" })
"management.endpoints.web.exposure.include=*", "spring.jackson.default-property-inclusion=non_null" })
public abstract class AbstractEndpointDocumentationTests {
protected String describeEnumValues(Class<? extends Enum<?>> enumType) {
return StringUtils
.collectionToDelimitedString(Stream.of(enumType.getEnumConstants())
.map((constant) -> "`" + constant.name() + "`")
.collect(Collectors.toList()), ", ");
return StringUtils.collectionToDelimitedString(Stream.of(enumType.getEnumConstants())
.map((constant) -> "`" + constant.name() + "`").collect(Collectors.toList()), ", ");
}
protected OperationPreprocessor limit(String... keys) {
@@ -74,8 +71,7 @@ public abstract class AbstractEndpointDocumentationTests {
@SuppressWarnings("unchecked")
protected <T> OperationPreprocessor limit(Predicate<T> filter, String... keys) {
return new ContentModifyingOperationPreprocessor((content, mediaType) -> {
ObjectMapper objectMapper = new ObjectMapper()
.enable(SerializationFeature.INDENT_OUTPUT);
ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
try {
Map<String, Object> payload = objectMapper.readValue(content, Map.class);
Object target = payload;
@@ -90,12 +86,10 @@ public abstract class AbstractEndpointDocumentationTests {
}
}
if (target instanceof Map) {
parent.put(keys[keys.length - 1],
select((Map<String, Object>) target, filter));
parent.put(keys[keys.length - 1], select((Map<String, Object>) target, filter));
}
else {
parent.put(keys[keys.length - 1],
select((List<Object>) target, filter));
parent.put(keys[keys.length - 1], select((List<Object>) target, filter));
}
return objectMapper.writeValueAsBytes(payload);
}
@@ -106,36 +100,30 @@ public abstract class AbstractEndpointDocumentationTests {
}
protected FieldDescriptor parentIdField() {
return fieldWithPath("contexts.*.parentId")
.description("Id of the parent application context, if any.").optional()
.type(JsonFieldType.STRING);
return fieldWithPath("contexts.*.parentId").description("Id of the parent application context, if any.")
.optional().type(JsonFieldType.STRING);
}
@SuppressWarnings("unchecked")
private <T> Map<String, Object> select(Map<String, Object> candidates,
Predicate<T> filter) {
private <T> Map<String, Object> select(Map<String, Object> candidates, Predicate<T> filter) {
Map<String, Object> selected = new HashMap<>();
candidates.entrySet().stream().filter((candidate) -> filter.test((T) candidate))
.limit(3)
candidates.entrySet().stream().filter((candidate) -> filter.test((T) candidate)).limit(3)
.forEach((entry) -> selected.put(entry.getKey(), entry.getValue()));
return selected;
}
@SuppressWarnings("unchecked")
private <T> List<Object> select(List<Object> candidates, Predicate<T> filter) {
return candidates.stream().filter((candidate) -> filter.test((T) candidate))
.limit(3).collect(Collectors.toList());
return candidates.stream().filter((candidate) -> filter.test((T) candidate)).limit(3)
.collect(Collectors.toList());
}
@Configuration
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class,
DispatcherServletAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
WebMvcEndpointManagementContextConfiguration.class,
WebFluxEndpointManagementContextConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, WebFluxAutoConfiguration.class,
HttpHandlerAutoConfiguration.class })
@ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class, WebMvcEndpointManagementContextConfiguration.class,
WebFluxEndpointManagementContextConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class })
static class BaseDocumentationConfiguration {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,8 +47,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class AuditEventsEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class AuditEventsEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@MockBean
private AuditEventRepository repository;
@@ -56,41 +55,33 @@ public class AuditEventsEndpointDocumentationTests
@Test
public void allAuditEvents() throws Exception {
String queryTimestamp = "2017-11-07T09:37Z";
given(this.repository.find(any(), any(), any())).willReturn(
Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap())));
this.mockMvc.perform(get("/actuator/auditevents").param("after", queryTimestamp))
.andExpect(status().isOk())
given(this.repository.find(any(), any(), any()))
.willReturn(Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap())));
this.mockMvc.perform(get("/actuator/auditevents").param("after", queryTimestamp)).andExpect(status().isOk())
.andDo(document("auditevents/all", responseFields(
fieldWithPath("events").description("An array of audit events."),
fieldWithPath("events.[].timestamp")
.description("The timestamp of when the event occurred."),
fieldWithPath("events.[].principal")
.description("The principal that triggered the event."),
fieldWithPath("events.[].type")
.description("The type of the event."))));
fieldWithPath("events.[].timestamp").description("The timestamp of when the event occurred."),
fieldWithPath("events.[].principal").description("The principal that triggered the event."),
fieldWithPath("events.[].type").description("The type of the event."))));
}
@Test
public void filteredAuditEvents() throws Exception {
OffsetDateTime now = OffsetDateTime.now();
String queryTimestamp = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(now);
given(this.repository.find("alice", now.toInstant(), "logout")).willReturn(
Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap())));
given(this.repository.find("alice", now.toInstant(), "logout"))
.willReturn(Arrays.asList(new AuditEvent("alice", "logout", Collections.emptyMap())));
this.mockMvc
.perform(get("/actuator/auditevents").param("principal", "alice")
.param("after", queryTimestamp).param("type", "logout"))
.perform(get("/actuator/auditevents")
.param("principal", "alice").param("after", queryTimestamp).param("type", "logout"))
.andExpect(status().isOk())
.andDo(document("auditevents/filtered",
requestParameters(
parameterWithName("after").description(
"Restricts the events to those that occurred "
+ "after the given time. Optional."),
parameterWithName("principal").description(
"Restricts the events to those with the given "
+ "principal. Optional."),
parameterWithName("type").description(
"Restricts the events to those with the given "
+ "type. Optional."))));
.andDo(document("auditevents/filtered", requestParameters(
parameterWithName("after").description(
"Restricts the events to those that occurred " + "after the given time. Optional."),
parameterWithName("principal")
.description("Restricts the events to those with the given " + "principal. Optional."),
parameterWithName("type")
.description("Restricts the events to those with the given " + "type. Optional."))));
verify(this.repository).find("alice", now.toInstant(), "logout");
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,32 +49,25 @@ public class BeansEndpointDocumentationTests extends MockMvcEndpointDocumentatio
@Test
public void beans() throws Exception {
List<FieldDescriptor> beanFields = Arrays.asList(
fieldWithPath("aliases").description("Names of any aliases."),
List<FieldDescriptor> beanFields = Arrays.asList(fieldWithPath("aliases").description("Names of any aliases."),
fieldWithPath("scope").description("Scope of the bean."),
fieldWithPath("type").description("Fully qualified type of the bean."),
fieldWithPath("resource")
.description("Resource in which the bean was defined, if any.")
.optional(),
fieldWithPath("resource").description("Resource in which the bean was defined, if any.").optional(),
fieldWithPath("dependencies").description("Names of any dependencies."));
ResponseFieldsSnippet responseFields = responseFields(
fieldWithPath("contexts")
.description("Application contexts keyed by id."),
parentIdField(),
fieldWithPath("contexts.*.beans")
.description("Beans in the application context keyed by name."))
.andWithPrefix("contexts.*.beans.*.", beanFields);
fieldWithPath("contexts").description("Application contexts keyed by id."), parentIdField(),
fieldWithPath("contexts.*.beans").description("Beans in the application context keyed by name."))
.andWithPrefix("contexts.*.beans.*.", beanFields);
this.mockMvc.perform(get("/actuator/beans")).andExpect(status().isOk())
.andDo(document("beans",
preprocessResponse(limit(this::isIndependentBean, "contexts",
getApplicationContext().getId(), "beans")),
preprocessResponse(
limit(this::isIndependentBean, "contexts", getApplicationContext().getId(), "beans")),
responseFields));
}
private boolean isIndependentBean(Entry<String, Map<String, Object>> bean) {
return CollectionUtils.isEmpty((Collection<?>) bean.getValue().get("aliases"))
&& CollectionUtils
.isEmpty((Collection<?>) bean.getValue().get("dependencies"));
&& CollectionUtils.isEmpty((Collection<?>) bean.getValue().get("dependencies"));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,34 +53,28 @@ public class CachesEndpointDocumentationTests extends MockMvcEndpointDocumentati
private static final List<FieldDescriptor> levelFields = Arrays.asList(
fieldWithPath("name").description("Cache name."),
fieldWithPath("cacheManager").description("Cache manager name."),
fieldWithPath("target")
.description("Fully qualified name of the native cache."));
fieldWithPath("target").description("Fully qualified name of the native cache."));
private static final List<ParameterDescriptor> requestParameters = Collections
.singletonList(parameterWithName("cacheManager")
.description("Name of the cacheManager to qualify the cache. May be "
+ "omitted if the cache name is unique.")
.singletonList(parameterWithName("cacheManager").description(
"Name of the cacheManager to qualify the cache. May be " + "omitted if the cache name is unique.")
.optional());
@Test
public void allCaches() throws Exception {
this.mockMvc.perform(get("/actuator/caches")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("caches/all", responseFields(
fieldWithPath("cacheManagers")
.description("Cache managers keyed by id."),
fieldWithPath("cacheManagers.*.caches").description(
"Caches in the application context keyed by " + "name."))
.andWithPrefix("cacheManagers.*.caches.*.",
fieldWithPath("target").description(
"Fully qualified name of the native cache."))));
.andDo(MockMvcRestDocumentation.document("caches/all",
responseFields(fieldWithPath("cacheManagers").description("Cache managers keyed by id."),
fieldWithPath("cacheManagers.*.caches")
.description("Caches in the application context keyed by " + "name."))
.andWithPrefix("cacheManagers.*.caches.*.", fieldWithPath("target")
.description("Fully qualified name of the native cache."))));
}
@Test
public void namedCache() throws Exception {
this.mockMvc.perform(get("/actuator/caches/cities")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("caches/named",
requestParameters(requestParameters),
responseFields(levelFields)));
this.mockMvc.perform(get("/actuator/caches/cities")).andExpect(status().isOk()).andDo(MockMvcRestDocumentation
.document("caches/named", requestParameters(requestParameters), responseFields(levelFields)));
}
@Test
@@ -91,12 +85,9 @@ public class CachesEndpointDocumentationTests extends MockMvcEndpointDocumentati
@Test
public void evictNamedCache() throws Exception {
this.mockMvc
.perform(delete(
"/actuator/caches/countries?cacheManager=anotherCacheManager"))
this.mockMvc.perform(delete("/actuator/caches/countries?cacheManager=anotherCacheManager"))
.andExpect(status().isNoContent())
.andDo(MockMvcRestDocumentation.document("caches/evict-named",
requestParameters(requestParameters)));
.andDo(MockMvcRestDocumentation.document("caches/evict-named", requestParameters(requestParameters)));
}
@Configuration
@@ -106,10 +97,8 @@ public class CachesEndpointDocumentationTests extends MockMvcEndpointDocumentati
@Bean
public CachesEndpoint endpoint() {
Map<String, CacheManager> cacheManagers = new HashMap<>();
cacheManagers.put("cacheManager",
new ConcurrentMapCacheManager("countries", "cities"));
cacheManagers.put("anotherCacheManager",
new ConcurrentMapCacheManager("countries"));
cacheManagers.put("cacheManager", new ConcurrentMapCacheManager("countries", "cities"));
cacheManagers.put("anotherCacheManager", new ConcurrentMapCacheManager("countries"));
return new CachesEndpoint(cacheManagers);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -50,8 +50,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class ConditionsReportEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class ConditionsReportEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Rule
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
@@ -65,53 +64,36 @@ public class ConditionsReportEndpointDocumentationTests
@Before
public void before() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.applicationContext)
.apply(MockMvcRestDocumentation
.documentationConfiguration(this.restDocumentation).uris())
.build();
.apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation).uris()).build();
}
@Test
public void conditions() throws Exception {
List<FieldDescriptor> positiveMatchFields = Arrays.asList(
fieldWithPath("").description(
"Classes and methods with conditions that were " + "matched."),
fieldWithPath("").description("Classes and methods with conditions that were " + "matched."),
fieldWithPath(".*.[].condition").description("Name of the condition."),
fieldWithPath(".*.[].message")
.description("Details of why the condition was matched."));
fieldWithPath(".*.[].message").description("Details of why the condition was matched."));
List<FieldDescriptor> negativeMatchFields = Arrays.asList(
fieldWithPath("").description("Classes and methods with conditions that "
+ "were not matched."),
fieldWithPath(".*.notMatched")
.description("Conditions that were matched."),
fieldWithPath(".*.notMatched.[].condition")
.description("Name of the condition."),
fieldWithPath(".*.notMatched.[].message").description(
"Details of why the condition was" + " not matched."),
fieldWithPath("").description("Classes and methods with conditions that " + "were not matched."),
fieldWithPath(".*.notMatched").description("Conditions that were matched."),
fieldWithPath(".*.notMatched.[].condition").description("Name of the condition."),
fieldWithPath(".*.notMatched.[].message")
.description("Details of why the condition was" + " not matched."),
fieldWithPath(".*.matched").description("Conditions that were matched."),
fieldWithPath(".*.matched.[].condition")
.description("Name of the condition.").type(JsonFieldType.STRING)
.optional(),
fieldWithPath(".*.matched.[].message")
.description("Details of why the condition was matched.")
fieldWithPath(".*.matched.[].condition").description("Name of the condition.")
.type(JsonFieldType.STRING).optional(),
fieldWithPath(".*.matched.[].message").description("Details of why the condition was matched.")
.type(JsonFieldType.STRING).optional());
FieldDescriptor unconditionalClassesField = fieldWithPath(
"contexts.*.unconditionalClasses").description(
"Names of unconditional auto-configuration classes if any.");
FieldDescriptor unconditionalClassesField = fieldWithPath("contexts.*.unconditionalClasses")
.description("Names of unconditional auto-configuration classes if any.");
this.mockMvc.perform(get("/actuator/conditions")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("conditions",
preprocessResponse(
limit("contexts", getApplicationContext()
.getId(), "positiveMatches"),
limit("contexts", getApplicationContext().getId(),
"negativeMatches")),
responseFields(fieldWithPath("contexts")
.description("Application contexts keyed by id."))
.andWithPrefix("contexts.*.positiveMatches",
positiveMatchFields)
.andWithPrefix("contexts.*.negativeMatches",
negativeMatchFields)
.and(unconditionalClassesField,
parentIdField())));
preprocessResponse(limit("contexts", getApplicationContext().getId(), "positiveMatches"),
limit("contexts", getApplicationContext().getId(), "negativeMatches")),
responseFields(fieldWithPath("contexts").description("Application contexts keyed by id."))
.andWithPrefix("contexts.*.positiveMatches", positiveMatchFields)
.andWithPrefix("contexts.*.negativeMatches", negativeMatchFields)
.and(unconditionalClassesField, parentIdField())));
}
@Configuration
@@ -119,12 +101,11 @@ public class ConditionsReportEndpointDocumentationTests
static class TestConfiguration {
@Bean
public ConditionsReportEndpoint autoConfigurationReportEndpoint(
ConfigurableApplicationContext context) {
public ConditionsReportEndpoint autoConfigurationReportEndpoint(ConfigurableApplicationContext context) {
ConditionEvaluationReport conditionEvaluationReport = ConditionEvaluationReport
.get(context.getBeanFactory());
conditionEvaluationReport.recordEvaluationCandidates(
Arrays.asList(PropertyPlaceholderAutoConfiguration.class.getName()));
conditionEvaluationReport
.recordEvaluationCandidates(Arrays.asList(PropertyPlaceholderAutoConfiguration.class.getName()));
return new ConditionsReportEndpoint(context);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,25 +37,20 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class ConfigurationPropertiesReportEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class ConfigurationPropertiesReportEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void configProps() throws Exception {
this.mockMvc.perform(get("/actuator/configprops")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("configprops",
preprocessResponse(limit("contexts",
getApplicationContext().getId(), "beans")),
responseFields(
fieldWithPath("contexts")
.description("Application contexts keyed by id."),
fieldWithPath("contexts.*.beans.*").description(
"`@ConfigurationProperties` beans keyed by bean name."),
fieldWithPath("contexts.*.beans.*.prefix").description(
"Prefix applied to the names of the bean's properties."),
preprocessResponse(limit("contexts", getApplicationContext().getId(), "beans")),
responseFields(fieldWithPath("contexts").description("Application contexts keyed by id."),
fieldWithPath("contexts.*.beans.*")
.description("`@ConfigurationProperties` beans keyed by bean name."),
fieldWithPath("contexts.*.beans.*.prefix")
.description("Prefix applied to the names of the bean's properties."),
subsectionWithPath("contexts.*.beans.*.properties")
.description(
"Properties of the bean as name-value pairs."),
.description("Properties of the bean as name-value pairs."),
parentIdField())));
}

View File

@@ -57,61 +57,49 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*/
@TestPropertySource(
properties = "spring.config.location=classpath:/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/")
public class EnvironmentEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class EnvironmentEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
private static final FieldDescriptor activeProfiles = fieldWithPath("activeProfiles")
.description("Names of the active profiles, if any.");
private static final FieldDescriptor propertySources = fieldWithPath(
"propertySources").description("Property sources in order of precedence.");
private static final FieldDescriptor propertySources = fieldWithPath("propertySources")
.description("Property sources in order of precedence.");
private static final FieldDescriptor propertySourceName = fieldWithPath(
"propertySources.[].name").description("Name of the property source.");
private static final FieldDescriptor propertySourceName = fieldWithPath("propertySources.[].name")
.description("Name of the property source.");
@Test
public void env() throws Exception {
this.mockMvc.perform(get("/actuator/env")).andExpect(status().isOk()).andDo(
document("env/all", preprocessResponse(replacePattern(Pattern.compile(
"org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/"),
this.mockMvc.perform(get("/actuator/env")).andExpect(status().isOk())
.andDo(document("env/all", preprocessResponse(replacePattern(
Pattern.compile("org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/"),
""), filterProperties()),
responseFields(activeProfiles, propertySources,
propertySourceName,
responseFields(activeProfiles, propertySources, propertySourceName,
fieldWithPath("propertySources.[].properties")
.description(
"Properties in the property source keyed by property name."),
.description("Properties in the property source keyed by property name."),
fieldWithPath("propertySources.[].properties.*.value")
.description("Value of the property."),
fieldWithPath("propertySources.[].properties.*.origin")
.description("Origin of the property, if any.")
.optional())));
.description("Origin of the property, if any.").optional())));
}
@Test
public void singlePropertyFromEnv() throws Exception {
this.mockMvc.perform(get("/actuator/env/com.example.cache.max-size"))
.andExpect(status().isOk())
.andDo(document("env/single",
preprocessResponse(replacePattern(Pattern.compile(
"org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/"),
"")),
responseFields(
fieldWithPath("property").description(
"Property from the environment, if found.")
.optional(),
fieldWithPath("property.source").description(
"Name of the source of the property."),
fieldWithPath("property.value")
.description("Value of the property."),
activeProfiles, propertySources, propertySourceName,
fieldWithPath("propertySources.[].property").description(
"Property in the property source, if any.")
.optional(),
fieldWithPath("propertySources.[].property.value")
.description("Value of the property."),
fieldWithPath("propertySources.[].property.origin")
.description("Origin of the property, if any.")
.optional())));
this.mockMvc.perform(get("/actuator/env/com.example.cache.max-size")).andExpect(status().isOk()).andDo(document(
"env/single",
preprocessResponse(replacePattern(
Pattern.compile("org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/"),
"")),
responseFields(
fieldWithPath("property").description("Property from the environment, if found.").optional(),
fieldWithPath("property.source").description("Name of the source of the property."),
fieldWithPath("property.value").description("Value of the property."), activeProfiles,
propertySources, propertySourceName,
fieldWithPath("propertySources.[].property")
.description("Property in the property source, if any.").optional(),
fieldWithPath("propertySources.[].property.value").description("Value of the property."),
fieldWithPath("propertySources.[].property.origin")
.description("Origin of the property, if any.").optional())));
}
private OperationPreprocessor filterProperties() {
@@ -120,17 +108,14 @@ public class EnvironmentEndpointDocumentationTests
@SuppressWarnings("unchecked")
private byte[] filterProperties(byte[] content, MediaType mediaType) {
ObjectMapper objectMapper = new ObjectMapper()
.enable(SerializationFeature.INDENT_OUTPUT);
ObjectMapper objectMapper = new ObjectMapper().enable(SerializationFeature.INDENT_OUTPUT);
try {
Map<String, Object> payload = objectMapper.readValue(content, Map.class);
List<Map<String, Object>> propertySources = (List<Map<String, Object>>) payload
.get("propertySources");
List<Map<String, Object>> propertySources = (List<Map<String, Object>>) payload.get("propertySources");
for (Map<String, Object> propertySource : propertySources) {
Map<String, String> properties = (Map<String, String>) propertySource
.get("properties");
Set<String> filteredKeys = properties.keySet().stream()
.filter(this::retainKey).limit(3).collect(Collectors.toSet());
Map<String, String> properties = (Map<String, String>) propertySource.get("properties");
Set<String> filteredKeys = properties.keySet().stream().filter(this::retainKey).limit(3)
.collect(Collectors.toSet());
properties.keySet().retainAll(filteredKeys);
}
return objectMapper.writeValueAsBytes(payload);
@@ -141,8 +126,7 @@ public class EnvironmentEndpointDocumentationTests
}
private boolean retainKey(String key) {
return key.startsWith("java.") || key.equals("JAVA_HOME")
|| key.startsWith("com.example");
return key.startsWith("java.") || key.equals("JAVA_HOME") || key.startsWith("com.example");
}
@Configuration
@@ -154,17 +138,14 @@ public class EnvironmentEndpointDocumentationTests
return new EnvironmentEndpoint(new AbstractEnvironment() {
@Override
protected void customizePropertySources(
MutablePropertySources propertySources) {
environment.getPropertySources().stream()
.filter(this::includedPropertySource)
protected void customizePropertySources(MutablePropertySources propertySources) {
environment.getPropertySources().stream().filter(this::includedPropertySource)
.forEach(propertySources::addLast);
}
private boolean includedPropertySource(PropertySource<?> propertySource) {
return propertySource instanceof EnumerablePropertySource
&& !"Inlined Test Properties"
.equals(propertySource.getName());
&& !"Inlined Test Properties".equals(propertySource.getName());
}
});

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,49 +52,35 @@ public class FlywayEndpointDocumentationTests extends MockMvcEndpointDocumentati
@Test
public void flyway() throws Exception {
this.mockMvc.perform(get("/actuator/flyway")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("flyway", responseFields(
fieldWithPath("contexts")
.description("Application contexts keyed by id"),
fieldWithPath("contexts.*.flywayBeans.*.migrations").description(
"Migrations performed by the Flyway instance, keyed by"
+ " Flyway bean name.")).andWithPrefix(
"contexts.*.flywayBeans.*.migrations.[].",
migrationFieldDescriptors())
.andDo(MockMvcRestDocumentation.document("flyway",
responseFields(fieldWithPath("contexts").description("Application contexts keyed by id"),
fieldWithPath("contexts.*.flywayBeans.*.migrations").description(
"Migrations performed by the Flyway instance, keyed by" + " Flyway bean name."))
.andWithPrefix("contexts.*.flywayBeans.*.migrations.[].",
migrationFieldDescriptors())
.and(parentIdField())));
}
private List<FieldDescriptor> migrationFieldDescriptors() {
return Arrays.asList(
fieldWithPath("checksum")
.description("Checksum of the migration, if any.").optional(),
fieldWithPath("description")
.description("Description of the migration, if any.").optional(),
fieldWithPath("executionTime")
.description(
"Execution time in milliseconds of an applied migration.")
return Arrays.asList(fieldWithPath("checksum").description("Checksum of the migration, if any.").optional(),
fieldWithPath("description").description("Description of the migration, if any.").optional(),
fieldWithPath("executionTime").description("Execution time in milliseconds of an applied migration.")
.optional(),
fieldWithPath("installedBy")
.description("User that installed the applied migration, if any.")
fieldWithPath("installedBy").description("User that installed the applied migration, if any.")
.optional(),
fieldWithPath("installedOn").description(
"Timestamp of when the applied migration was installed, "
+ "if any.")
fieldWithPath("installedOn")
.description("Timestamp of when the applied migration was installed, " + "if any.").optional(),
fieldWithPath("installedRank")
.description("Rank of the applied migration, if any. Later migrations have " + "higher ranks.")
.optional(),
fieldWithPath("installedRank").description(
"Rank of the applied migration, if any. Later migrations have "
+ "higher ranks.")
fieldWithPath("script").description("Name of the script used to execute the migration, if any.")
.optional(),
fieldWithPath("script").description(
"Name of the script used to execute the migration, if any.")
.optional(),
fieldWithPath("state").description("State of the migration. ("
+ describeEnumValues(MigrationState.class) + ")"),
fieldWithPath("type").description("Type of the migration. ("
+ describeEnumValues(MigrationType.class) + ")"),
fieldWithPath("version").description(
"Version of the database after applying the migration, "
+ "if any.")
.optional());
fieldWithPath("state")
.description("State of the migration. (" + describeEnumValues(MigrationState.class) + ")"),
fieldWithPath("type")
.description("Type of the migration. (" + describeEnumValues(MigrationType.class) + ")"),
fieldWithPath("version")
.description("Version of the database after applying the migration, " + "if any.").optional());
}
@Configuration
@@ -104,9 +90,8 @@ public class FlywayEndpointDocumentationTests extends MockMvcEndpointDocumentati
@Bean
public DataSource dataSource() {
return new EmbeddedDatabaseBuilder().generateUniqueName(true).setType(
EmbeddedDatabaseConnection.get(getClass().getClassLoader()).getType())
.build();
return new EmbeddedDatabaseBuilder().generateUniqueName(true)
.setType(EmbeddedDatabaseConnection.get(getClass().getClassLoader()).getType()).build();
}
@Bean

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -58,25 +58,20 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
private static final List<FieldDescriptor> componentFields = Arrays.asList(
fieldWithPath("status")
.description("Status of a specific part of the application"),
subsectionWithPath("details").description(
"Details of the health of a specific part of the" + " application."));
fieldWithPath("status").description("Status of a specific part of the application"),
subsectionWithPath("details")
.description("Details of the health of a specific part of the" + " application."));
@Test
public void health() throws Exception {
this.mockMvc.perform(get("/actuator/health")).andExpect(status().isOk())
.andDo(document("health", responseFields(
fieldWithPath("status")
.description("Overall status of the application."),
fieldWithPath("details").description(
"Details of the health of the application. Presence is controlled by "
this.mockMvc.perform(get("/actuator/health")).andExpect(status().isOk()).andDo(document("health",
responseFields(fieldWithPath("status").description("Overall status of the application."),
fieldWithPath("details")
.description("Details of the health of the application. Presence is controlled by "
+ "`management.endpoint.health.show-details`)."),
fieldWithPath("details.*.status").description(
"Status of a specific part of the application."),
subsectionWithPath("details.*.details").description(
"Details of the health of a specific part of the"
+ " application."))));
fieldWithPath("details.*.status").description("Status of a specific part of the application."),
subsectionWithPath("details.*.details")
.description("Details of the health of a specific part of the" + " application."))));
}
@Test
@@ -87,8 +82,7 @@ public class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentati
@Test
public void healthComponentInstance() throws Exception {
this.mockMvc.perform(get("/actuator/health/broker/us1"))
.andExpect(status().isOk())
this.mockMvc.perform(get("/actuator/health/broker/us1")).andExpect(status().isOk())
.andDo(document("health/instance", responseFields(componentFields)));
}
@@ -99,9 +93,8 @@ public class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentati
@Bean
public HealthEndpoint endpoint(Map<String, HealthIndicator> healthIndicators) {
return new HealthEndpoint(new CompositeHealthIndicator(
new OrderedHealthAggregator(), new HealthIndicatorRegistryFactory()
.createHealthIndicatorRegistry(healthIndicators)));
return new HealthEndpoint(new CompositeHealthIndicator(new OrderedHealthAggregator(),
new HealthIndicatorRegistryFactory().createHealthIndicatorRegistry(healthIndicators)));
}
@Bean
@@ -117,12 +110,9 @@ public class HealthEndpointDocumentationTests extends MockMvcEndpointDocumentati
@Bean
public CompositeHealthIndicator brokerHealthIndicator() {
Map<String, HealthIndicator> indicators = new LinkedHashMap<>();
indicators.put("us1",
() -> Health.up().withDetail("version", "1.0.2").build());
indicators.put("us2",
() -> Health.up().withDetail("version", "1.0.4").build());
return new CompositeHealthIndicator(new OrderedHealthAggregator(),
indicators);
indicators.put("us1", () -> Health.up().withDetail("version", "1.0.2").build());
indicators.put("us2", () -> Health.up().withDetail("version", "1.0.4").build());
return new CompositeHealthIndicator(new OrderedHealthAggregator(), indicators);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,24 +39,21 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class HeapDumpWebEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class HeapDumpWebEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void heapDump() throws Exception {
this.mockMvc.perform(get("/actuator/heapdump")).andExpect(status().isOk())
.andDo(document("heapdump",
new CurlRequestSnippet(CliDocumentation.multiLineFormat()) {
.andDo(document("heapdump", new CurlRequestSnippet(CliDocumentation.multiLineFormat()) {
@Override
protected Map<String, Object> createModel(
Operation operation) {
Map<String, Object> model = super.createModel(operation);
model.put("options", "-O");
return model;
}
@Override
protected Map<String, Object> createModel(Operation operation) {
Map<String, Object> model = super.createModel(operation);
model.put("options", "-O");
return model;
}
}));
}));
}
@Configuration
@@ -68,10 +65,8 @@ public class HeapDumpWebEndpointDocumentationTests
return new HeapDumpWebEndpoint() {
@Override
protected HeapDumper createHeapDumper()
throws HeapDumperUnavailableException {
return (file, live) -> FileCopyUtils.copy("<<binary content>>",
new FileWriter(file));
protected HeapDumper createHeapDumper() throws HeapDumperUnavailableException {
return (file, live) -> FileCopyUtils.copy("<<binary content>>", new FileWriter(file));
}
};

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,8 +52,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class HttpTraceEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class HttpTraceEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@MockBean
private HttpTraceRepository repository;
@@ -63,55 +62,43 @@ public class HttpTraceEndpointDocumentationTests
TraceableRequest request = mock(TraceableRequest.class);
given(request.getUri()).willReturn(URI.create("https://api.example.com"));
given(request.getMethod()).willReturn("GET");
given(request.getHeaders()).willReturn(Collections
.singletonMap(HttpHeaders.ACCEPT, Arrays.asList("application/json")));
given(request.getHeaders())
.willReturn(Collections.singletonMap(HttpHeaders.ACCEPT, Arrays.asList("application/json")));
TraceableResponse response = mock(TraceableResponse.class);
given(response.getStatus()).willReturn(200);
given(response.getHeaders()).willReturn(Collections.singletonMap(
HttpHeaders.CONTENT_TYPE, Arrays.asList("application/json")));
given(response.getHeaders())
.willReturn(Collections.singletonMap(HttpHeaders.CONTENT_TYPE, Arrays.asList("application/json")));
Principal principal = mock(Principal.class);
given(principal.getName()).willReturn("alice");
HttpExchangeTracer tracer = new HttpExchangeTracer(EnumSet.allOf(Include.class));
HttpTrace trace = tracer.receivedRequest(request);
tracer.sendingResponse(trace, response, () -> principal,
() -> UUID.randomUUID().toString());
tracer.sendingResponse(trace, response, () -> principal, () -> UUID.randomUUID().toString());
given(this.repository.findAll()).willReturn(Arrays.asList(trace));
this.mockMvc.perform(get("/actuator/httptrace")).andExpect(status().isOk())
.andDo(document("httptrace", responseFields(
fieldWithPath("traces").description(
"An array of traced HTTP request-response exchanges."),
fieldWithPath("traces.[].timestamp").description(
"Timestamp of when the traced exchange occurred."),
fieldWithPath("traces.[].principal")
.description("Principal of the exchange, if any.")
fieldWithPath("traces").description("An array of traced HTTP request-response exchanges."),
fieldWithPath("traces.[].timestamp")
.description("Timestamp of when the traced exchange occurred."),
fieldWithPath("traces.[].principal").description("Principal of the exchange, if any.")
.optional(),
fieldWithPath("traces.[].principal.name")
.description("Name of the principal.").optional(),
fieldWithPath("traces.[].request.method")
.description("HTTP method of the request."),
fieldWithPath("traces.[].request.remoteAddress").description(
"Remote address from which the request was received, if known.")
.optional().type(JsonFieldType.STRING),
fieldWithPath("traces.[].request.uri")
.description("URI of the request."),
fieldWithPath("traces.[].request.headers").description(
"Headers of the request, keyed by header name."),
fieldWithPath("traces.[].request.headers.*.[]")
.description("Values of the header"),
fieldWithPath("traces.[].response.status")
.description("Status of the response"),
fieldWithPath("traces.[].response.headers").description(
"Headers of the response, keyed by header name."),
fieldWithPath("traces.[].response.headers.*.[]")
.description("Values of the header"),
fieldWithPath("traces.[].session")
.description(
"Session associated with the exchange, if any.")
fieldWithPath("traces.[].principal.name").description("Name of the principal.").optional(),
fieldWithPath("traces.[].request.method").description("HTTP method of the request."),
fieldWithPath("traces.[].request.remoteAddress")
.description("Remote address from which the request was received, if known.").optional()
.type(JsonFieldType.STRING),
fieldWithPath("traces.[].request.uri").description("URI of the request."),
fieldWithPath("traces.[].request.headers")
.description("Headers of the request, keyed by header name."),
fieldWithPath("traces.[].request.headers.*.[]").description("Values of the header"),
fieldWithPath("traces.[].response.status").description("Status of the response"),
fieldWithPath("traces.[].response.headers")
.description("Headers of the response, keyed by header name."),
fieldWithPath("traces.[].response.headers.*.[]").description("Values of the header"),
fieldWithPath("traces.[].session").description("Session associated with the exchange, if any.")
.optional(),
fieldWithPath("traces.[].session.id")
.description("ID of the session."),
fieldWithPath("traces.[].timeTaken").description(
"Time, in milliseconds, taken to handle the exchange."))));
fieldWithPath("traces.[].session.id").description("ID of the session."),
fieldWithPath("traces.[].timeTaken")
.description("Time, in milliseconds, taken to handle the exchange."))));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,33 +51,20 @@ public class InfoEndpointDocumentationTests extends MockMvcEndpointDocumentation
this.mockMvc.perform(get("/actuator/info")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("info",
responseFields(beneathPath("git"),
fieldWithPath("branch")
.description("Name of the Git branch, if any."),
fieldWithPath("commit").description(
"Details of the Git commit, if any."),
fieldWithPath("commit.time")
.description("Timestamp of the commit, if any.")
fieldWithPath("branch").description("Name of the Git branch, if any."),
fieldWithPath("commit").description("Details of the Git commit, if any."),
fieldWithPath("commit.time").description("Timestamp of the commit, if any.")
.type(JsonFieldType.VARIES),
fieldWithPath("commit.id")
.description("ID of the commit, if any.")),
fieldWithPath("commit.id").description("ID of the commit, if any.")),
responseFields(beneathPath("build"),
fieldWithPath("artifact")
.description(
"Artifact ID of the application, if any.")
fieldWithPath("artifact").description("Artifact ID of the application, if any.")
.optional(),
fieldWithPath("group")
.description(
"Group ID of the application, if any.")
.optional(),
fieldWithPath("name")
.description("Name of the application, if any.")
fieldWithPath("group").description("Group ID of the application, if any.").optional(),
fieldWithPath("name").description("Name of the application, if any.")
.type(JsonFieldType.STRING).optional(),
fieldWithPath("version")
.description(
"Version of the application, if any.")
.optional(),
fieldWithPath("time").description(
"Timestamp of when the application was built, if any.")
fieldWithPath("version").description("Version of the application, if any.").optional(),
fieldWithPath("time")
.description("Timestamp of when the application was built, if any.")
.type(JsonFieldType.VARIES).optional())));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,8 +35,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Tim Ysewyn
*/
public class IntegrationGraphEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class IntegrationGraphEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void graph() throws Exception {
@@ -46,8 +45,7 @@ public class IntegrationGraphEndpointDocumentationTests
@Test
public void rebuild() throws Exception {
this.mockMvc.perform(post("/actuator/integrationgraph"))
.andExpect(status().isNoContent())
this.mockMvc.perform(post("/actuator/integrationgraph")).andExpect(status().isNoContent())
.andDo(MockMvcRestDocumentation.document("integrationgraph/rebuild"));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,50 +43,37 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class LiquibaseEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class LiquibaseEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void liquibase() throws Exception {
FieldDescriptor changeSetsField = fieldWithPath(
"contexts.*.liquibaseBeans.*.changeSets")
.description("Change sets made by the Liquibase beans, keyed by "
+ "bean name.");
FieldDescriptor changeSetsField = fieldWithPath("contexts.*.liquibaseBeans.*.changeSets")
.description("Change sets made by the Liquibase beans, keyed by " + "bean name.");
this.mockMvc.perform(get("/actuator/liquibase")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("liquibase",
responseFields(
fieldWithPath("contexts")
.description("Application contexts keyed by id"),
changeSetsField).andWithPrefix(
"contexts.*.liquibaseBeans.*.changeSets[].",
getChangeSetFieldDescriptors())
responseFields(fieldWithPath("contexts").description("Application contexts keyed by id"),
changeSetsField)
.andWithPrefix("contexts.*.liquibaseBeans.*.changeSets[].",
getChangeSetFieldDescriptors())
.and(parentIdField())));
}
private List<FieldDescriptor> getChangeSetFieldDescriptors() {
return Arrays.asList(
fieldWithPath("author").description("Author of the change set."),
fieldWithPath("changeLog")
.description("Change log that contains the change set."),
return Arrays.asList(fieldWithPath("author").description("Author of the change set."),
fieldWithPath("changeLog").description("Change log that contains the change set."),
fieldWithPath("comments").description("Comments on the change set."),
fieldWithPath("contexts").description("Contexts of the change set."),
fieldWithPath("dateExecuted")
.description("Timestamp of when the change set was executed."),
fieldWithPath("deploymentId")
.description("ID of the deployment that ran the change set."),
fieldWithPath("description")
.description("Description of the change set."),
fieldWithPath("execType").description("Execution type of the change set ("
+ describeEnumValues(ExecType.class) + ")."),
fieldWithPath("dateExecuted").description("Timestamp of when the change set was executed."),
fieldWithPath("deploymentId").description("ID of the deployment that ran the change set."),
fieldWithPath("description").description("Description of the change set."),
fieldWithPath("execType")
.description("Execution type of the change set (" + describeEnumValues(ExecType.class) + ")."),
fieldWithPath("id").description("ID of the change set."),
fieldWithPath("labels")
.description("Labels associated with the change set."),
fieldWithPath("labels").description("Labels associated with the change set."),
fieldWithPath("checksum").description("Checksum of the change set."),
fieldWithPath("orderExecuted")
.description("Order of the execution of the change set."),
fieldWithPath("tag")
.description("Tag associated with the change set, if any.")
.optional().type(JsonFieldType.STRING));
fieldWithPath("orderExecuted").description("Order of the execution of the change set."),
fieldWithPath("tag").description("Tag associated with the change set, if any.").optional()
.type(JsonFieldType.STRING));
}
@Configuration

View File

@@ -36,8 +36,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*/
@TestPropertySource(
properties = "logging.file=src/test/resources/org/springframework/boot/actuate/autoconfigure/endpoint/web/documentation/sample.log")
public class LogFileWebEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class LogFileWebEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void logFile() throws Exception {
@@ -48,8 +47,7 @@ public class LogFileWebEndpointDocumentationTests
@Test
public void logFileRange() throws Exception {
this.mockMvc.perform(get("/actuator/logfile").header("Range", "bytes=0-1023"))
.andExpect(status().isPartialContent())
.andDo(MockMvcRestDocumentation.document("logfile/range"));
.andExpect(status().isPartialContent()).andDo(MockMvcRestDocumentation.document("logfile/range"));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,60 +51,49 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
public class LoggersEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
private static final List<FieldDescriptor> levelFields = Arrays.asList(
fieldWithPath("configuredLevel")
.description("Configured level of the logger, if any.").optional(),
fieldWithPath("effectiveLevel")
.description("Effective level of the logger."));
fieldWithPath("configuredLevel").description("Configured level of the logger, if any.").optional(),
fieldWithPath("effectiveLevel").description("Effective level of the logger."));
@MockBean
private LoggingSystem loggingSystem;
@Test
public void allLoggers() throws Exception {
given(this.loggingSystem.getSupportedLogLevels())
.willReturn(EnumSet.allOf(LogLevel.class));
given(this.loggingSystem.getLoggerConfigurations()).willReturn(Arrays.asList(
new LoggerConfiguration("ROOT", LogLevel.INFO, LogLevel.INFO),
new LoggerConfiguration("com.example", LogLevel.DEBUG, LogLevel.DEBUG)));
given(this.loggingSystem.getSupportedLogLevels()).willReturn(EnumSet.allOf(LogLevel.class));
given(this.loggingSystem.getLoggerConfigurations())
.willReturn(Arrays.asList(new LoggerConfiguration("ROOT", LogLevel.INFO, LogLevel.INFO),
new LoggerConfiguration("com.example", LogLevel.DEBUG, LogLevel.DEBUG)));
this.mockMvc.perform(get("/actuator/loggers")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("loggers/all", responseFields(
fieldWithPath("levels")
.description("Levels support by the logging system."),
fieldWithPath("loggers").description("Loggers keyed by name."))
.andWithPrefix("loggers.*.", levelFields)));
.andDo(MockMvcRestDocumentation.document("loggers/all",
responseFields(fieldWithPath("levels").description("Levels support by the logging system."),
fieldWithPath("loggers").description("Loggers keyed by name."))
.andWithPrefix("loggers.*.", levelFields)));
}
@Test
public void logger() throws Exception {
given(this.loggingSystem.getLoggerConfiguration("com.example")).willReturn(
new LoggerConfiguration("com.example", LogLevel.INFO, LogLevel.INFO));
this.mockMvc.perform(get("/actuator/loggers/com.example"))
.andExpect(status().isOk()).andDo(MockMvcRestDocumentation
.document("loggers/single", responseFields(levelFields)));
given(this.loggingSystem.getLoggerConfiguration("com.example"))
.willReturn(new LoggerConfiguration("com.example", LogLevel.INFO, LogLevel.INFO));
this.mockMvc.perform(get("/actuator/loggers/com.example")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("loggers/single", responseFields(levelFields)));
}
@Test
public void setLogLevel() throws Exception {
this.mockMvc
.perform(post("/actuator/loggers/com.example")
.content("{\"configuredLevel\":\"debug\"}")
.perform(post("/actuator/loggers/com.example").content("{\"configuredLevel\":\"debug\"}")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNoContent()).andDo(
MockMvcRestDocumentation.document("loggers/set",
requestFields(fieldWithPath("configuredLevel")
.description("Level for the logger. May be"
+ " omitted to clear the level.")
.optional())));
.andExpect(status().isNoContent())
.andDo(MockMvcRestDocumentation.document("loggers/set", requestFields(fieldWithPath("configuredLevel")
.description("Level for the logger. May be" + " omitted to clear the level.").optional())));
verify(this.loggingSystem).setLogLevel("com.example", LogLevel.DEBUG);
}
@Test
public void clearLogLevel() throws Exception {
this.mockMvc
.perform(post("/actuator/loggers/com.example").content("{}")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNoContent())
.andDo(MockMvcRestDocumentation.document("loggers/clear"));
.perform(post("/actuator/loggers/com.example").content("{}").contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isNoContent()).andDo(MockMvcRestDocumentation.document("loggers/clear"));
verify(this.loggingSystem).setLogLevel("com.example", null);
}

View File

@@ -62,10 +62,8 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r
* @author Andy Wilkinson
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT,
properties = "spring.main.web-application-type=reactive")
public class MappingsEndpointReactiveDocumentationTests
extends AbstractEndpointDocumentationTests {
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = "spring.main.web-application-type=reactive")
public class MappingsEndpointReactiveDocumentationTests extends AbstractEndpointDocumentationTests {
@Rule
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
@@ -77,92 +75,61 @@ public class MappingsEndpointReactiveDocumentationTests
@Before
public void webTestClient() {
this.client = WebTestClient
.bindToServer().filter(documentationConfiguration(this.restDocumentation)
.snippets().withDefaults())
this.client = WebTestClient.bindToServer()
.filter(documentationConfiguration(this.restDocumentation).snippets().withDefaults())
.baseUrl("http://localhost:" + this.port).build();
}
@Test
public void mappings() throws Exception {
List<FieldDescriptor> requestMappingConditions = Arrays.asList(
requestMappingConditionField("")
.description("Details of the request mapping conditions.")
.optional(),
requestMappingConditionField(".consumes")
.description("Details of the consumes condition"),
requestMappingConditionField(".consumes.[].mediaType")
.description("Consumed media type."),
requestMappingConditionField(".consumes.[].negated")
.description("Whether the media type is negated."),
requestMappingConditionField(".headers")
.description("Details of the headers condition."),
requestMappingConditionField(".headers.[].name")
.description("Name of the header."),
requestMappingConditionField(".headers.[].value")
.description("Required value of the header, if any."),
requestMappingConditionField(".headers.[].negated")
.description("Whether the value is negated."),
requestMappingConditionField(".methods")
.description("HTTP methods that are handled."),
requestMappingConditionField(".params")
.description("Details of the params condition."),
requestMappingConditionField(".params.[].name")
.description("Name of the parameter."),
requestMappingConditionField("").description("Details of the request mapping conditions.").optional(),
requestMappingConditionField(".consumes").description("Details of the consumes condition"),
requestMappingConditionField(".consumes.[].mediaType").description("Consumed media type."),
requestMappingConditionField(".consumes.[].negated").description("Whether the media type is negated."),
requestMappingConditionField(".headers").description("Details of the headers condition."),
requestMappingConditionField(".headers.[].name").description("Name of the header."),
requestMappingConditionField(".headers.[].value").description("Required value of the header, if any."),
requestMappingConditionField(".headers.[].negated").description("Whether the value is negated."),
requestMappingConditionField(".methods").description("HTTP methods that are handled."),
requestMappingConditionField(".params").description("Details of the params condition."),
requestMappingConditionField(".params.[].name").description("Name of the parameter."),
requestMappingConditionField(".params.[].value")
.description("Required value of the parameter, if any."),
requestMappingConditionField(".params.[].negated")
.description("Whether the value is negated."),
requestMappingConditionField(".patterns").description(
"Patterns identifying the paths handled by the mapping."),
requestMappingConditionField(".produces")
.description("Details of the produces condition."),
requestMappingConditionField(".produces.[].mediaType")
.description("Produced media type."),
requestMappingConditionField(".produces.[].negated")
.description("Whether the media type is negated."));
requestMappingConditionField(".params.[].negated").description("Whether the value is negated."),
requestMappingConditionField(".patterns")
.description("Patterns identifying the paths handled by the mapping."),
requestMappingConditionField(".produces").description("Details of the produces condition."),
requestMappingConditionField(".produces.[].mediaType").description("Produced media type."),
requestMappingConditionField(".produces.[].negated").description("Whether the media type is negated."));
List<FieldDescriptor> handlerMethod = Arrays.asList(
fieldWithPath("*.[].details.handlerMethod").optional()
.type(JsonFieldType.OBJECT)
.description("Details of the method, if any, "
+ "that will handle requests to this mapping."),
fieldWithPath("*.[].details.handlerMethod.className")
.type(JsonFieldType.STRING)
fieldWithPath("*.[].details.handlerMethod").optional().type(JsonFieldType.OBJECT)
.description("Details of the method, if any, " + "that will handle requests to this mapping."),
fieldWithPath("*.[].details.handlerMethod.className").type(JsonFieldType.STRING)
.description("Fully qualified name of the class of the method."),
fieldWithPath("*.[].details.handlerMethod.name")
.type(JsonFieldType.STRING).description("Name of the method."),
fieldWithPath("*.[].details.handlerMethod.descriptor")
.type(JsonFieldType.STRING)
.description("Descriptor of the method as specified in the Java "
+ "Language Specification."));
fieldWithPath("*.[].details.handlerMethod.name").type(JsonFieldType.STRING)
.description("Name of the method."),
fieldWithPath("*.[].details.handlerMethod.descriptor").type(JsonFieldType.STRING)
.description("Descriptor of the method as specified in the Java " + "Language Specification."));
List<FieldDescriptor> handlerFunction = Arrays.asList(
fieldWithPath("*.[].details.handlerFunction").optional()
.type(JsonFieldType.OBJECT)
.description("Details of the function, if any, that will handle "
+ "requests to this mapping."),
fieldWithPath("*.[].details.handlerFunction.className")
.type(JsonFieldType.STRING).description(
"Fully qualified name of the class of the function."));
fieldWithPath("*.[].details.handlerFunction").optional().type(JsonFieldType.OBJECT).description(
"Details of the function, if any, that will handle " + "requests to this mapping."),
fieldWithPath("*.[].details.handlerFunction.className").type(JsonFieldType.STRING)
.description("Fully qualified name of the class of the function."));
List<FieldDescriptor> dispatcherHandlerFields = new ArrayList<>(Arrays.asList(
fieldWithPath("*")
.description("Dispatcher handler mappings, if any, keyed by "
+ "dispatcher handler bean name."),
fieldWithPath("*").description(
"Dispatcher handler mappings, if any, keyed by " + "dispatcher handler bean name."),
fieldWithPath("*.[].details").optional().type(JsonFieldType.OBJECT)
.description("Additional implementation-specific "
+ "details about the mapping. Optional."),
.description("Additional implementation-specific " + "details about the mapping. Optional."),
fieldWithPath("*.[].handler").description("Handler for the mapping."),
fieldWithPath("*.[].predicate")
.description("Predicate for the mapping.")));
fieldWithPath("*.[].predicate").description("Predicate for the mapping.")));
dispatcherHandlerFields.addAll(requestMappingConditions);
dispatcherHandlerFields.addAll(handlerMethod);
dispatcherHandlerFields.addAll(handlerFunction);
this.client.get().uri("/actuator/mappings").exchange().expectStatus().isOk()
.expectBody()
.consumeWith(document("mappings",
responseFields(
beneathPath("contexts.*.mappings.dispatcherHandlers")
.withSubsectionId("dispatcher-handlers"),
dispatcherHandlerFields)));
this.client.get().uri("/actuator/mappings").exchange().expectStatus().isOk().expectBody()
.consumeWith(document("mappings", responseFields(
beneathPath("contexts.*.mappings.dispatcherHandlers").withSubsectionId("dispatcher-handlers"),
dispatcherHandlerFields)));
}
private FieldDescriptor requestMappingConditionField(String path) {
@@ -184,8 +151,7 @@ public class MappingsEndpointReactiveDocumentationTests
}
@Bean
public MappingsEndpoint mappingsEndpoint(
Collection<MappingDescriptionProvider> descriptionProviders,
public MappingsEndpoint mappingsEndpoint(Collection<MappingDescriptionProvider> descriptionProviders,
ConfigurableApplicationContext context) {
return new MappingsEndpoint(descriptionProviders, context);
}
@@ -205,10 +171,8 @@ public class MappingsEndpointReactiveDocumentationTests
@RestController
private static class ExampleController {
@PostMapping(path = "/",
consumes = { MediaType.APPLICATION_JSON_VALUE, "!application/xml" },
produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo",
params = "a!=alpha")
@PostMapping(path = "/", consumes = { MediaType.APPLICATION_JSON_VALUE, "!application/xml" },
produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo", params = "a!=alpha")
public String example() {
return "Hello World";
}

View File

@@ -63,8 +63,7 @@ import static org.springframework.restdocs.webtestclient.WebTestClientRestDocume
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class MappingsEndpointServletDocumentationTests
extends AbstractEndpointDocumentationTests {
public class MappingsEndpointServletDocumentationTests extends AbstractEndpointDocumentationTests {
@Rule
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
@@ -76,115 +75,76 @@ public class MappingsEndpointServletDocumentationTests
@Before
public void webTestClient() {
this.client = WebTestClient.bindToServer()
.filter(documentationConfiguration(this.restDocumentation))
this.client = WebTestClient.bindToServer().filter(documentationConfiguration(this.restDocumentation))
.baseUrl("http://localhost:" + this.port).build();
}
@Test
public void mappings() throws Exception {
ResponseFieldsSnippet commonResponseFields = responseFields(
fieldWithPath("contexts")
.description("Application contexts keyed by id."),
fieldWithPath("contexts.*.mappings")
.description("Mappings in the context, keyed by mapping type."),
fieldWithPath("contexts").description("Application contexts keyed by id."),
fieldWithPath("contexts.*.mappings").description("Mappings in the context, keyed by mapping type."),
subsectionWithPath("contexts.*.mappings.dispatcherServlets")
.description("Dispatcher servlet mappings, if any."),
subsectionWithPath("contexts.*.mappings.servletFilters")
.description("Servlet filter mappings, if any."),
subsectionWithPath("contexts.*.mappings.servlets")
.description("Servlet mappings, if any."),
subsectionWithPath("contexts.*.mappings.servlets").description("Servlet mappings, if any."),
subsectionWithPath("contexts.*.mappings.dispatcherHandlers")
.description("Dispatcher handler mappings, if any.").optional()
.type(JsonFieldType.OBJECT),
.description("Dispatcher handler mappings, if any.").optional().type(JsonFieldType.OBJECT),
parentIdField());
List<FieldDescriptor> dispatcherServletFields = new ArrayList<>(Arrays.asList(
fieldWithPath("*")
.description("Dispatcher servlet mappings, if any, keyed by "
+ "dispatcher servlet bean name."),
fieldWithPath("*").description(
"Dispatcher servlet mappings, if any, keyed by " + "dispatcher servlet bean name."),
fieldWithPath("*.[].details").optional().type(JsonFieldType.OBJECT)
.description("Additional implementation-specific "
+ "details about the mapping. Optional."),
.description("Additional implementation-specific " + "details about the mapping. Optional."),
fieldWithPath("*.[].handler").description("Handler for the mapping."),
fieldWithPath("*.[].predicate")
.description("Predicate for the mapping.")));
fieldWithPath("*.[].predicate").description("Predicate for the mapping.")));
List<FieldDescriptor> requestMappingConditions = Arrays.asList(
requestMappingConditionField("")
.description("Details of the request mapping conditions.")
.optional(),
requestMappingConditionField(".consumes")
.description("Details of the consumes condition"),
requestMappingConditionField(".consumes.[].mediaType")
.description("Consumed media type."),
requestMappingConditionField(".consumes.[].negated")
.description("Whether the media type is negated."),
requestMappingConditionField(".headers")
.description("Details of the headers condition."),
requestMappingConditionField(".headers.[].name")
.description("Name of the header."),
requestMappingConditionField(".headers.[].value")
.description("Required value of the header, if any."),
requestMappingConditionField(".headers.[].negated")
.description("Whether the value is negated."),
requestMappingConditionField(".methods")
.description("HTTP methods that are handled."),
requestMappingConditionField(".params")
.description("Details of the params condition."),
requestMappingConditionField(".params.[].name")
.description("Name of the parameter."),
requestMappingConditionField("").description("Details of the request mapping conditions.").optional(),
requestMappingConditionField(".consumes").description("Details of the consumes condition"),
requestMappingConditionField(".consumes.[].mediaType").description("Consumed media type."),
requestMappingConditionField(".consumes.[].negated").description("Whether the media type is negated."),
requestMappingConditionField(".headers").description("Details of the headers condition."),
requestMappingConditionField(".headers.[].name").description("Name of the header."),
requestMappingConditionField(".headers.[].value").description("Required value of the header, if any."),
requestMappingConditionField(".headers.[].negated").description("Whether the value is negated."),
requestMappingConditionField(".methods").description("HTTP methods that are handled."),
requestMappingConditionField(".params").description("Details of the params condition."),
requestMappingConditionField(".params.[].name").description("Name of the parameter."),
requestMappingConditionField(".params.[].value")
.description("Required value of the parameter, if any."),
requestMappingConditionField(".params.[].negated")
.description("Whether the value is negated."),
requestMappingConditionField(".patterns").description(
"Patterns identifying the paths handled by the mapping."),
requestMappingConditionField(".produces")
.description("Details of the produces condition."),
requestMappingConditionField(".produces.[].mediaType")
.description("Produced media type."),
requestMappingConditionField(".produces.[].negated")
.description("Whether the media type is negated."));
requestMappingConditionField(".params.[].negated").description("Whether the value is negated."),
requestMappingConditionField(".patterns")
.description("Patterns identifying the paths handled by the mapping."),
requestMappingConditionField(".produces").description("Details of the produces condition."),
requestMappingConditionField(".produces.[].mediaType").description("Produced media type."),
requestMappingConditionField(".produces.[].negated").description("Whether the media type is negated."));
List<FieldDescriptor> handlerMethod = Arrays.asList(
fieldWithPath("*.[].details.handlerMethod").optional()
.type(JsonFieldType.OBJECT)
.description("Details of the method, if any, "
+ "that will handle requests to this mapping."),
fieldWithPath("*.[].details.handlerMethod").optional().type(JsonFieldType.OBJECT)
.description("Details of the method, if any, " + "that will handle requests to this mapping."),
fieldWithPath("*.[].details.handlerMethod.className")
.description("Fully qualified name of the class of the method."),
fieldWithPath("*.[].details.handlerMethod.name")
.description("Name of the method."),
fieldWithPath("*.[].details.handlerMethod.name").description("Name of the method."),
fieldWithPath("*.[].details.handlerMethod.descriptor")
.description("Descriptor of the method as specified in the Java "
+ "Language Specification."));
.description("Descriptor of the method as specified in the Java " + "Language Specification."));
dispatcherServletFields.addAll(handlerMethod);
dispatcherServletFields.addAll(requestMappingConditions);
this.client.get().uri("/actuator/mappings").exchange().expectBody()
.consumeWith(document(
"mappings", commonResponseFields,
responseFields(beneathPath(
"contexts.*.mappings.dispatcherServlets")
.withSubsectionId("dispatcher-servlets"),
dispatcherServletFields),
.consumeWith(document("mappings", commonResponseFields,
responseFields(beneathPath("contexts.*.mappings.dispatcherServlets")
.withSubsectionId("dispatcher-servlets"), dispatcherServletFields),
responseFields(
beneathPath("contexts.*.mappings.servletFilters")
.withSubsectionId("servlet-filters"),
fieldWithPath("[].servletNameMappings").description(
"Names of the servlets to which the filter is mapped."),
fieldWithPath("[].urlPatternMappings").description(
"URL pattern to which the filter is mapped."),
fieldWithPath("[].name")
.description("Name of the filter."),
fieldWithPath("[].className")
.description("Class name of the filter")),
responseFields(
beneathPath("contexts.*.mappings.servlets")
.withSubsectionId("servlets"),
fieldWithPath("[].mappings")
.description("Mappings of the servlet."),
fieldWithPath("[].name")
.description("Name of the servlet."),
fieldWithPath("[].className")
.description("Class name of the servlet"))));
beneathPath("contexts.*.mappings.servletFilters").withSubsectionId("servlet-filters"),
fieldWithPath("[].servletNameMappings")
.description("Names of the servlets to which the filter is mapped."),
fieldWithPath("[].urlPatternMappings")
.description("URL pattern to which the filter is mapped."),
fieldWithPath("[].name").description("Name of the filter."),
fieldWithPath("[].className").description("Class name of the filter")),
responseFields(beneathPath("contexts.*.mappings.servlets").withSubsectionId("servlets"),
fieldWithPath("[].mappings").description("Mappings of the servlet."),
fieldWithPath("[].name").description("Name of the servlet."),
fieldWithPath("[].className").description("Class name of the servlet"))));
}
private FieldDescriptor requestMappingConditionField(String path) {
@@ -216,8 +176,7 @@ public class MappingsEndpointServletDocumentationTests
}
@Bean
public MappingsEndpoint mappingsEndpoint(
Collection<MappingDescriptionProvider> descriptionProviders,
public MappingsEndpoint mappingsEndpoint(Collection<MappingDescriptionProvider> descriptionProviders,
ConfigurableApplicationContext context) {
return new MappingsEndpoint(descriptionProviders, context);
}
@@ -232,10 +191,8 @@ public class MappingsEndpointServletDocumentationTests
@RestController
private static class ExampleController {
@PostMapping(path = "/",
consumes = { MediaType.APPLICATION_JSON_VALUE, "!application/xml" },
produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo",
params = "a!=alpha")
@PostMapping(path = "/", consumes = { MediaType.APPLICATION_JSON_VALUE, "!application/xml" },
produces = MediaType.TEXT_PLAIN_VALUE, headers = "X-Custom=Foo", params = "a!=alpha")
public String example() {
return "Hello World";
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,43 +43,34 @@ public class MetricsEndpointDocumentationTests extends MockMvcEndpointDocumentat
@Test
public void metricNames() throws Exception {
this.mockMvc.perform(get("/actuator/metrics")).andExpect(status().isOk())
.andDo(document("metrics/names", responseFields(fieldWithPath("names")
.description("Names of the known metrics."))));
this.mockMvc.perform(get("/actuator/metrics")).andExpect(status().isOk()).andDo(document("metrics/names",
responseFields(fieldWithPath("names").description("Names of the known metrics."))));
}
@Test
public void metric() throws Exception {
this.mockMvc.perform(get("/actuator/metrics/jvm.memory.max"))
.andExpect(status().isOk())
.andDo(document("metrics/metric", responseFields(
fieldWithPath("name").description("Name of the metric"),
fieldWithPath("description")
.description("Description of the metric"),
fieldWithPath("baseUnit").description("Base unit of the metric"),
fieldWithPath("measurements")
.description("Measurements of the metric"),
fieldWithPath("measurements[].statistic")
.description("Statistic of the measurement. ("
+ describeEnumValues(Statistic.class) + ")."),
fieldWithPath("measurements[].value")
.description("Value of the measurement."),
fieldWithPath("availableTags")
.description("Tags that are available for drill-down."),
fieldWithPath("availableTags[].tag")
.description("Name of the tag."),
fieldWithPath("availableTags[].values")
.description("Possible values of the tag."))));
this.mockMvc.perform(get("/actuator/metrics/jvm.memory.max")).andExpect(status().isOk())
.andDo(document("metrics/metric",
responseFields(fieldWithPath("name").description("Name of the metric"),
fieldWithPath("description").description("Description of the metric"),
fieldWithPath("baseUnit").description("Base unit of the metric"),
fieldWithPath("measurements").description("Measurements of the metric"),
fieldWithPath("measurements[].statistic").description(
"Statistic of the measurement. (" + describeEnumValues(Statistic.class) + ")."),
fieldWithPath("measurements[].value").description("Value of the measurement."),
fieldWithPath("availableTags").description("Tags that are available for drill-down."),
fieldWithPath("availableTags[].tag").description("Name of the tag."),
fieldWithPath("availableTags[].values").description("Possible values of the tag."))));
}
@Test
public void metricWithTags() throws Exception {
this.mockMvc.perform(get("/actuator/metrics/jvm.memory.max")
.param("tag", "area:nonheap").param("tag", "id:Compressed Class Space"))
this.mockMvc
.perform(get("/actuator/metrics/jvm.memory.max").param("tag", "area:nonheap").param("tag",
"id:Compressed Class Space"))
.andExpect(status().isOk())
.andDo(document("metrics/metric-with-tags",
requestParameters(parameterWithName("tag").description(
"A tag to use for drill-down in the form `name:value`."))));
.andDo(document("metrics/metric-with-tags", requestParameters(parameterWithName("tag")
.description("A tag to use for drill-down in the form `name:value`."))));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,8 +37,7 @@ import org.springframework.web.context.WebApplicationContext;
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public abstract class MockMvcEndpointDocumentationTests
extends AbstractEndpointDocumentationTests {
public abstract class MockMvcEndpointDocumentationTests extends AbstractEndpointDocumentationTests {
@Rule
public final JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
@@ -51,9 +50,7 @@ public abstract class MockMvcEndpointDocumentationTests
@Before
public void before() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.applicationContext)
.apply(MockMvcRestDocumentation
.documentationConfiguration(this.restDocumentation).uris())
.build();
.apply(MockMvcRestDocumentation.documentationConfiguration(this.restDocumentation).uris()).build();
}
protected WebApplicationContext getApplicationContext() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,13 +36,11 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class PrometheusScrapeEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class PrometheusScrapeEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void prometheus() throws Exception {
this.mockMvc.perform(get("/actuator/prometheus")).andExpect(status().isOk())
.andDo(document("prometheus"));
this.mockMvc.perform(get("/actuator/prometheus")).andExpect(status().isOk()).andDo(document("prometheus"));
}
@Configuration
@@ -52,8 +50,8 @@ public class PrometheusScrapeEndpointDocumentationTests
@Bean
public PrometheusScrapeEndpoint endpoint() {
CollectorRegistry collectorRegistry = new CollectorRegistry(true);
PrometheusMeterRegistry meterRegistry = new PrometheusMeterRegistry(
(key) -> null, collectorRegistry, Clock.SYSTEM);
PrometheusMeterRegistry meterRegistry = new PrometheusMeterRegistry((key) -> null, collectorRegistry,
Clock.SYSTEM);
new JvmMemoryMetrics().bindTo(meterRegistry);
return new PrometheusScrapeEndpoint(collectorRegistry);
}

View File

@@ -48,51 +48,40 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class ScheduledTasksEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class ScheduledTasksEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void scheduledTasks() throws Exception {
this.mockMvc.perform(get("/actuator/scheduledtasks")).andExpect(status().isOk())
.andDo(document("scheduled-tasks",
preprocessResponse(replacePattern(Pattern.compile(
"org.*\\.ScheduledTasksEndpointDocumentationTests\\$"
+ "TestConfiguration"),
"com.example.Processor")),
responseFields(
fieldWithPath("cron").description("Cron tasks, if any."),
targetFieldWithPrefix("cron.[]."),
fieldWithPath("cron.[].expression")
.description("Cron expression."),
fieldWithPath("fixedDelay")
.description("Fixed delay tasks, if any."),
targetFieldWithPrefix("fixedDelay.[]."),
initialDelayWithPrefix("fixedDelay.[]."),
fieldWithPath("fixedDelay.[].interval").description(
"Interval, in milliseconds, between the end of the last"
+ " execution and the start of the next."),
fieldWithPath("fixedRate")
.description("Fixed rate tasks, if any."),
targetFieldWithPrefix("fixedRate.[]."),
fieldWithPath("fixedRate.[].interval").description(
"Interval, in milliseconds, between the start of each execution."),
initialDelayWithPrefix("fixedRate.[]."),
fieldWithPath("custom").description(
"Tasks with custom triggers, if any."),
targetFieldWithPrefix("custom.[]."),
fieldWithPath("custom.[].trigger")
.description("Trigger for the task."))))
this.mockMvc.perform(get("/actuator/scheduledtasks")).andExpect(status().isOk()).andDo(document(
"scheduled-tasks",
preprocessResponse(replacePattern(
Pattern.compile("org.*\\.ScheduledTasksEndpointDocumentationTests\\$" + "TestConfiguration"),
"com.example.Processor")),
responseFields(fieldWithPath("cron").description("Cron tasks, if any."),
targetFieldWithPrefix("cron.[]."),
fieldWithPath("cron.[].expression").description("Cron expression."),
fieldWithPath("fixedDelay").description("Fixed delay tasks, if any."),
targetFieldWithPrefix("fixedDelay.[]."), initialDelayWithPrefix("fixedDelay.[]."),
fieldWithPath("fixedDelay.[].interval")
.description("Interval, in milliseconds, between the end of the last"
+ " execution and the start of the next."),
fieldWithPath("fixedRate").description("Fixed rate tasks, if any."),
targetFieldWithPrefix("fixedRate.[]."),
fieldWithPath("fixedRate.[].interval")
.description("Interval, in milliseconds, between the start of each execution."),
initialDelayWithPrefix("fixedRate.[]."),
fieldWithPath("custom").description("Tasks with custom triggers, if any."),
targetFieldWithPrefix("custom.[]."),
fieldWithPath("custom.[].trigger").description("Trigger for the task."))))
.andDo(MockMvcResultHandlers.print());
}
private FieldDescriptor targetFieldWithPrefix(String prefix) {
return fieldWithPath(prefix + "runnable.target")
.description("Target that will be executed.");
return fieldWithPath(prefix + "runnable.target").description("Target that will be executed.");
}
private FieldDescriptor initialDelayWithPrefix(String prefix) {
return fieldWithPath(prefix + "initialDelay")
.description("Delay, in milliseconds, before first execution.");
return fieldWithPath(prefix + "initialDelay").description("Delay, in milliseconds, before first execution.");
}
@Configuration
@@ -122,8 +111,7 @@ public class ScheduledTasksEndpointDocumentationTests
@Bean
public SchedulingConfigurer schedulingConfigurer() {
return (registrar) -> registrar.addTriggerTask(new CustomTriggeredRunnable(),
new CustomTrigger());
return (registrar) -> registrar.addTriggerTask(new CustomTriggeredRunnable(), new CustomTrigger());
}
static class CustomTrigger implements Trigger {

View File

@@ -53,32 +53,25 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
@TestPropertySource(
properties = "spring.jackson.serialization.write-dates-as-timestamps=false")
public class SessionsEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
@TestPropertySource(properties = "spring.jackson.serialization.write-dates-as-timestamps=false")
public class SessionsEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
private static final Session sessionOne = createSession(
Instant.now().minusSeconds(60 * 60 * 12), Instant.now().minusSeconds(45));
private static final Session sessionOne = createSession(Instant.now().minusSeconds(60 * 60 * 12),
Instant.now().minusSeconds(45));
private static final Session sessionTwo = createSession(
"4db5efcc-99cb-4d05-a52c-b49acfbb7ea9",
private static final Session sessionTwo = createSession("4db5efcc-99cb-4d05-a52c-b49acfbb7ea9",
Instant.now().minusSeconds(60 * 60 * 5), Instant.now().minusSeconds(37));
private static final Session sessionThree = createSession(
Instant.now().minusSeconds(60 * 60 * 2), Instant.now().minusSeconds(12));
private static final Session sessionThree = createSession(Instant.now().minusSeconds(60 * 60 * 2),
Instant.now().minusSeconds(12));
private static final List<FieldDescriptor> sessionFields = Arrays.asList(
fieldWithPath("id").description("ID of the session."),
fieldWithPath("attributeNames")
.description("Names of the attributes stored in the session."),
fieldWithPath("creationTime")
.description("Timestamp of when the session was created."),
fieldWithPath("lastAccessedTime")
.description("Timestamp of when the session was last accessed."),
fieldWithPath("maxInactiveInterval")
.description("Maximum permitted period of inactivity, in seconds, "
+ "before the session will expire."),
fieldWithPath("attributeNames").description("Names of the attributes stored in the session."),
fieldWithPath("creationTime").description("Timestamp of when the session was created."),
fieldWithPath("lastAccessedTime").description("Timestamp of when the session was last accessed."),
fieldWithPath("maxInactiveInterval").description(
"Maximum permitted period of inactivity, in seconds, " + "before the session will expire."),
fieldWithPath("expired").description("Whether the session has expired."));
@MockBean
@@ -91,14 +84,11 @@ public class SessionsEndpointDocumentationTests
sessions.put(sessionTwo.getId(), sessionTwo);
sessions.put(sessionThree.getId(), sessionThree);
given(this.sessionRepository.findByPrincipalName("alice")).willReturn(sessions);
this.mockMvc.perform(get("/actuator/sessions").param("username", "alice"))
.andExpect(status().isOk())
this.mockMvc.perform(get("/actuator/sessions").param("username", "alice")).andExpect(status().isOk())
.andDo(document("sessions/username",
responseFields(fieldWithPath("sessions")
.description("Sessions for the given username."))
.andWithPrefix("sessions.[].", sessionFields),
requestParameters(parameterWithName("username")
.description("Name of the user."))));
responseFields(fieldWithPath("sessions").description("Sessions for the given username."))
.andWithPrefix("sessions.[].", sessionFields),
requestParameters(parameterWithName("username").description("Name of the user."))));
}
@Test
@@ -108,26 +98,22 @@ public class SessionsEndpointDocumentationTests
sessions.put(sessionTwo.getId(), sessionTwo);
sessions.put(sessionThree.getId(), sessionThree);
given(this.sessionRepository.findById(sessionTwo.getId())).willReturn(sessionTwo);
this.mockMvc.perform(get("/actuator/sessions/{id}", sessionTwo.getId()))
.andExpect(status().isOk())
this.mockMvc.perform(get("/actuator/sessions/{id}", sessionTwo.getId())).andExpect(status().isOk())
.andDo(document("sessions/id", responseFields(sessionFields)));
}
@Test
public void deleteASession() throws Exception {
this.mockMvc.perform(delete("/actuator/sessions/{id}", sessionTwo.getId()))
.andExpect(status().isNoContent()).andDo(document("sessions/delete"));
this.mockMvc.perform(delete("/actuator/sessions/{id}", sessionTwo.getId())).andExpect(status().isNoContent())
.andDo(document("sessions/delete"));
verify(this.sessionRepository).deleteById(sessionTwo.getId());
}
private static MapSession createSession(Instant creationTime,
Instant lastAccessedTime) {
return createSession(UUID.randomUUID().toString(), creationTime,
lastAccessedTime);
private static MapSession createSession(Instant creationTime, Instant lastAccessedTime) {
return createSession(UUID.randomUUID().toString(), creationTime, lastAccessedTime);
}
private static MapSession createSession(String id, Instant creationTime,
Instant lastAccessedTime) {
private static MapSession createSession(String id, Instant creationTime, Instant lastAccessedTime) {
MapSession session = new MapSession(id);
session.setCreationTime(creationTime);
session.setLastAccessedTime(lastAccessedTime);
@@ -139,8 +125,7 @@ public class SessionsEndpointDocumentationTests
static class TestConfiguration {
@Bean
public SessionsEndpoint endpoint(
FindByIndexNameSessionRepository<?> sessionRepository) {
public SessionsEndpoint endpoint(FindByIndexNameSessionRepository<?> sessionRepository) {
return new SessionsEndpoint(sessionRepository);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,15 +36,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class ShutdownEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class ShutdownEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void shutdown() throws Exception {
this.mockMvc.perform(post("/actuator/shutdown")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("shutdown",
responseFields(fieldWithPath("message").description(
"Message describing the result of the request."))));
.andDo(MockMvcRestDocumentation.document("shutdown", responseFields(
fieldWithPath("message").description("Message describing the result of the request."))));
}
@Configuration

View File

@@ -40,8 +40,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
*
* @author Andy Wilkinson
*/
public class ThreadDumpEndpointDocumentationTests
extends MockMvcEndpointDocumentationTests {
public class ThreadDumpEndpointDocumentationTests extends MockMvcEndpointDocumentationTests {
@Test
public void threadDump() throws Exception {
@@ -62,151 +61,102 @@ public class ThreadDumpEndpointDocumentationTests
}
}).start();
this.mockMvc.perform(get("/actuator/threaddump")).andExpect(status().isOk())
.andDo(MockMvcRestDocumentation.document("threaddump",
preprocessResponse(limit("threads")),
responseFields(
fieldWithPath("threads").description("JVM's threads."),
fieldWithPath("threads.[].blockedCount").description(
"Total number of times that the thread has been "
+ "blocked."),
fieldWithPath("threads.[].blockedTime").description(
"Time in milliseconds that the thread has spent "
+ "blocked. -1 if thread contention "
+ "monitoring is disabled."),
.andDo(MockMvcRestDocumentation.document("threaddump", preprocessResponse(limit("threads")),
responseFields(fieldWithPath("threads").description("JVM's threads."),
fieldWithPath("threads.[].blockedCount")
.description("Total number of times that the thread has been " + "blocked."),
fieldWithPath("threads.[].blockedTime")
.description("Time in milliseconds that the thread has spent "
+ "blocked. -1 if thread contention " + "monitoring is disabled."),
fieldWithPath("threads.[].daemon")
.description("Whether the thread is a daemon "
+ "thread. Only available on Java 9 or "
+ "later.")
+ "thread. Only available on Java 9 or " + "later.")
.optional().type(JsonFieldType.BOOLEAN),
fieldWithPath("threads.[].inNative").description(
"Whether the thread is executing native code."),
fieldWithPath("threads.[].lockName")
.description(
"Description of the object on which the "
+ "thread is blocked, if any.")
fieldWithPath("threads.[].inNative")
.description("Whether the thread is executing native code."),
fieldWithPath("threads.[].lockName").description(
"Description of the object on which the " + "thread is blocked, if any.")
.optional().type(JsonFieldType.STRING),
fieldWithPath("threads.[].lockInfo")
.description(
"Object for which the thread is blocked "
+ "waiting.")
.optional().type(JsonFieldType.OBJECT),
.description("Object for which the thread is blocked " + "waiting.").optional()
.type(JsonFieldType.OBJECT),
fieldWithPath("threads.[].lockInfo.className")
.description(
"Fully qualified class name of the lock"
+ " object.")
.optional().type(JsonFieldType.STRING),
.description("Fully qualified class name of the lock" + " object.").optional()
.type(JsonFieldType.STRING),
fieldWithPath("threads.[].lockInfo.identityHashCode")
.description(
"Identity hash code of the lock object.")
.optional().type(JsonFieldType.NUMBER),
fieldWithPath("threads.[].lockedMonitors").description(
"Monitors locked by this thread, if any"),
.description("Identity hash code of the lock object.").optional()
.type(JsonFieldType.NUMBER),
fieldWithPath("threads.[].lockedMonitors")
.description("Monitors locked by this thread, if any"),
fieldWithPath("threads.[].lockedMonitors.[].className")
.description("Class name of the lock object.")
.optional().type(JsonFieldType.STRING),
fieldWithPath(
"threads.[].lockedMonitors.[].identityHashCode")
.description(
"Identity hash code of the lock "
+ "object.")
.optional().type(JsonFieldType.NUMBER),
fieldWithPath(
"threads.[].lockedMonitors.[].lockedStackDepth")
.description(
"Stack depth where the monitor "
+ "was locked.")
.optional().type(JsonFieldType.NUMBER),
subsectionWithPath(
"threads.[].lockedMonitors.[].lockedStackFrame")
.description(
"Stack frame that locked the "
+ "monitor.")
.optional().type(JsonFieldType.OBJECT),
.description("Class name of the lock object.").optional()
.type(JsonFieldType.STRING),
fieldWithPath("threads.[].lockedMonitors.[].identityHashCode")
.description("Identity hash code of the lock " + "object.").optional()
.type(JsonFieldType.NUMBER),
fieldWithPath("threads.[].lockedMonitors.[].lockedStackDepth")
.description("Stack depth where the monitor " + "was locked.").optional()
.type(JsonFieldType.NUMBER),
subsectionWithPath("threads.[].lockedMonitors.[].lockedStackFrame")
.description("Stack frame that locked the " + "monitor.").optional()
.type(JsonFieldType.OBJECT),
fieldWithPath("threads.[].lockedSynchronizers")
.description(
"Synchronizers locked by this thread."),
fieldWithPath(
"threads.[].lockedSynchronizers.[].className")
.description("Class name of the locked "
+ "synchronizer.")
.optional().type(JsonFieldType.STRING),
fieldWithPath(
"threads.[].lockedSynchronizers.[].identityHashCode")
.description(
"Identity hash code of the locked "
+ "synchronizer.")
.optional().type(JsonFieldType.NUMBER),
.description("Synchronizers locked by this thread."),
fieldWithPath("threads.[].lockedSynchronizers.[].className").description(
"Class name of the locked " + "synchronizer.").optional()
.type(JsonFieldType.STRING),
fieldWithPath("threads.[].lockedSynchronizers.[].identityHashCode").description(
"Identity hash code of the locked " + "synchronizer.").optional()
.type(JsonFieldType.NUMBER),
fieldWithPath("threads.[].lockOwnerId").description(
"ID of the thread that owns the object on which "
+ "the thread is blocked. `-1` if the "
+ "thread is not blocked."),
+ "the thread is blocked. `-1` if the " + "thread is not blocked."),
fieldWithPath("threads.[].lockOwnerName")
.description("Name of the thread that owns the "
+ "object on which the thread is "
+ "blocked, if any.")
+ "object on which the thread is " + "blocked, if any.")
.optional().type(JsonFieldType.STRING),
fieldWithPath("threads.[].priority")
.description("Priority of the thread. Only "
+ "available on Java 9 or later.")
.description("Priority of the thread. Only " + "available on Java 9 or later.")
.optional().type(JsonFieldType.NUMBER),
fieldWithPath("threads.[].stackTrace")
.description("Stack trace of the thread."),
fieldWithPath("threads.[].stackTrace.[].classLoaderName")
.description("Name of the class loader of the "
+ "class that contains the execution "
fieldWithPath("threads.[].stackTrace").description("Stack trace of the thread."),
fieldWithPath("threads.[].stackTrace.[].classLoaderName").description(
"Name of the class loader of the " + "class that contains the execution "
+ "point identified by this entry, if "
+ "any. Only available on Java 9 or "
+ "later.")
+ "any. Only available on Java 9 or " + "later.")
.optional().type(JsonFieldType.STRING),
fieldWithPath("threads.[].stackTrace.[].className")
.description(
"Name of the class that contains the "
+ "execution point identified "
+ "by this entry."),
fieldWithPath("threads.[].stackTrace.[].className").description(
"Name of the class that contains the " + "execution point identified "
+ "by this entry."),
fieldWithPath("threads.[].stackTrace.[].fileName")
.description("Name of the source file that "
+ "contains the execution point "
.description("Name of the source file that " + "contains the execution point "
+ "identified by this entry, if any.")
.optional().type(JsonFieldType.STRING),
fieldWithPath("threads.[].stackTrace.[].lineNumber")
.description("Line number of the execution "
+ "point identified by this entry. "
+ "Negative if unknown."),
fieldWithPath("threads.[].stackTrace.[].methodName")
.description("Name of the method."),
+ "point identified by this entry. " + "Negative if unknown."),
fieldWithPath("threads.[].stackTrace.[].methodName").description("Name of the method."),
fieldWithPath("threads.[].stackTrace.[].moduleName")
.description("Name of the module that contains "
+ "the execution point identified by "
+ "this entry, if any. Only available "
+ "on Java 9 or later.")
+ "this entry, if any. Only available " + "on Java 9 or later.")
.optional().type(JsonFieldType.STRING),
fieldWithPath("threads.[].stackTrace.[].moduleVersion")
.description("Version of the module that "
+ "contains the execution point "
.description("Version of the module that " + "contains the execution point "
+ "identified by this entry, if any. "
+ "Only available on Java 9 or later.")
.optional().type(JsonFieldType.STRING),
fieldWithPath("threads.[].stackTrace.[].nativeMethod")
.description(
"Whether the execution point is a native "
+ "method."),
fieldWithPath("threads.[].suspended")
.description("Whether the thread is suspended."),
fieldWithPath("threads.[].threadId")
.description("ID of the thread."),
fieldWithPath("threads.[].threadName")
.description("Name of the thread."),
fieldWithPath("threads.[].threadState")
.description("State of the thread ("
+ describeEnumValues(Thread.State.class)
+ ")."),
.description("Whether the execution point is a native " + "method."),
fieldWithPath("threads.[].suspended").description("Whether the thread is suspended."),
fieldWithPath("threads.[].threadId").description("ID of the thread."),
fieldWithPath("threads.[].threadName").description("Name of the thread."),
fieldWithPath("threads.[].threadState").description(
"State of the thread (" + describeEnumValues(Thread.State.class) + ")."),
fieldWithPath("threads.[].waitedCount").description(
"Total number of times that the thread has waited"
+ " for notification."),
fieldWithPath("threads.[].waitedTime").description(
"Time in milliseconds that the thread has spent "
+ "waiting. -1 if thread contention "
+ "monitoring is disabled"))));
"Total number of times that the thread has waited" + " for notification."),
fieldWithPath("threads.[].waitedTime")
.description("Time in milliseconds that the thread has spent "
+ "waiting. -1 if thread contention " + "monitoring is disabled"))));
latch.countDown();
}

View File

@@ -49,24 +49,21 @@ public class JerseyWebEndpointManagementContextConfigurationTests {
@Test
public void resourceConfigCustomizerForEndpointsIsAutoConfigured() {
this.runner.run((context) -> assertThat(context)
.hasSingleBean(ResourceConfigCustomizer.class));
this.runner.run((context) -> assertThat(context).hasSingleBean(ResourceConfigCustomizer.class));
}
@Test
public void autoConfigurationIsConditionalOnServletWebApplication() {
ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations
.of(JerseySameManagementContextConfiguration.class));
contextRunner.run((context) -> assertThat(context)
.doesNotHaveBean(JerseySameManagementContextConfiguration.class));
.withConfiguration(AutoConfigurations.of(JerseySameManagementContextConfiguration.class));
contextRunner
.run((context) -> assertThat(context).doesNotHaveBean(JerseySameManagementContextConfiguration.class));
}
@Test
public void autoConfigurationIsConditionalOnClassResourceConfig() {
this.runner.withClassLoader(new FilteredClassLoader(ResourceConfig.class))
.run((context) -> assertThat(context)
.doesNotHaveBean(JerseySameManagementContextConfiguration.class));
.run((context) -> assertThat(context).doesNotHaveBean(JerseySameManagementContextConfiguration.class));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -39,8 +39,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class EnvironmentEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(EnvironmentEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(EnvironmentEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
@@ -51,8 +50,7 @@ public class EnvironmentEndpointAutoConfigurationTests {
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner.withPropertyValues("management.endpoint.env.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(EnvironmentEndpoint.class));
.run((context) -> assertThat(context).doesNotHaveBean(EnvironmentEndpoint.class));
}
@Test
@@ -62,24 +60,20 @@ public class EnvironmentEndpointAutoConfigurationTests {
.run(validateSystemProperties("******", "123456"));
}
private ContextConsumer<AssertableApplicationContext> validateSystemProperties(
String dbPassword, String apiKey) {
private ContextConsumer<AssertableApplicationContext> validateSystemProperties(String dbPassword, String apiKey) {
return (context) -> {
assertThat(context).hasSingleBean(EnvironmentEndpoint.class);
EnvironmentEndpoint endpoint = context.getBean(EnvironmentEndpoint.class);
EnvironmentDescriptor env = endpoint.environment(null);
Map<String, PropertyValueDescriptor> systemProperties = getSource(
"systemProperties", env).getProperties();
assertThat(systemProperties.get("dbPassword").getValue())
.isEqualTo(dbPassword);
Map<String, PropertyValueDescriptor> systemProperties = getSource("systemProperties", env).getProperties();
assertThat(systemProperties.get("dbPassword").getValue()).isEqualTo(dbPassword);
assertThat(systemProperties.get("apiKey").getValue()).isEqualTo(apiKey);
};
}
private PropertySourceDescriptor getSource(String name,
EnvironmentDescriptor descriptor) {
return descriptor.getPropertySources().stream()
.filter((source) -> name.equals(source.getName())).findFirst().get();
private PropertySourceDescriptor getSource(String name, EnvironmentDescriptor descriptor) {
return descriptor.getPropertySources().stream().filter((source) -> name.equals(source.getName())).findFirst()
.get();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,21 +36,18 @@ import static org.mockito.Mockito.mock;
public class FlywayEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(FlywayEndpointAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(FlywayEndpointAutoConfiguration.class))
.withUserConfiguration(FlywayConfiguration.class);
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(FlywayEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(FlywayEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner.withPropertyValues("management.endpoint.flyway.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(FlywayEndpoint.class));
.run((context) -> assertThat(context).doesNotHaveBean(FlywayEndpoint.class));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -44,34 +44,28 @@ import static org.mockito.Mockito.verify;
*/
public class HealthEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class));
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration(
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class));
@Test
public void healthEndpointShowDetailsDefault() {
this.contextRunner
.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class)
.run((context) -> {
ReactiveHealthIndicator indicator = context.getBean(
"reactiveHealthIndicator", ReactiveHealthIndicator.class);
verify(indicator, never()).health();
Health health = context.getBean(HealthEndpoint.class).health();
assertThat(health.getStatus()).isEqualTo(Status.UP);
assertThat(health.getDetails()).isNotEmpty();
verify(indicator, times(1)).health();
});
this.contextRunner.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class).run((context) -> {
ReactiveHealthIndicator indicator = context.getBean("reactiveHealthIndicator",
ReactiveHealthIndicator.class);
verify(indicator, never()).health();
Health health = context.getBean(HealthEndpoint.class).health();
assertThat(health.getStatus()).isEqualTo(Status.UP);
assertThat(health.getDetails()).isNotEmpty();
verify(indicator, times(1)).health();
});
}
@Test
public void healthEndpointAdaptReactiveHealthIndicator() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class)
.run((context) -> {
ReactiveHealthIndicator indicator = context.getBean(
"reactiveHealthIndicator", ReactiveHealthIndicator.class);
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always")
.withUserConfiguration(ReactiveHealthIndicatorConfiguration.class).run((context) -> {
ReactiveHealthIndicator indicator = context.getBean("reactiveHealthIndicator",
ReactiveHealthIndicator.class);
verify(indicator, never()).health();
Health health = context.getBean(HealthEndpoint.class).health();
assertThat(health.getStatus()).isEqualTo(Status.UP);
@@ -82,21 +76,17 @@ public class HealthEndpointAutoConfigurationTests {
@Test
public void healthEndpointMergeRegularAndReactive() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.withUserConfiguration(HealthIndicatorConfiguration.class,
ReactiveHealthIndicatorConfiguration.class)
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always")
.withUserConfiguration(HealthIndicatorConfiguration.class, ReactiveHealthIndicatorConfiguration.class)
.run((context) -> {
HealthIndicator indicator = context.getBean("simpleHealthIndicator",
HealthIndicator.class);
ReactiveHealthIndicator reactiveHealthIndicator = context.getBean(
"reactiveHealthIndicator", ReactiveHealthIndicator.class);
HealthIndicator indicator = context.getBean("simpleHealthIndicator", HealthIndicator.class);
ReactiveHealthIndicator reactiveHealthIndicator = context.getBean("reactiveHealthIndicator",
ReactiveHealthIndicator.class);
verify(indicator, never()).health();
verify(reactiveHealthIndicator, never()).health();
Health health = context.getBean(HealthEndpoint.class).health();
assertThat(health.getStatus()).isEqualTo(Status.UP);
assertThat(health.getDetails()).containsOnlyKeys("simple",
"reactive");
assertThat(health.getDetails()).containsOnlyKeys("simple", "reactive");
verify(indicator, times(1)).health();
verify(reactiveHealthIndicator, times(1)).health();
});

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -52,347 +52,258 @@ import static org.mockito.Mockito.mock;
public class HealthEndpointWebExtensionTests {
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withUserConfiguration(HealthIndicatorsConfiguration.class).withConfiguration(
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class));
.withUserConfiguration(HealthIndicatorsConfiguration.class).withConfiguration(AutoConfigurations
.of(HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class));
@Test
public void runShouldCreateExtensionBeans() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(HealthEndpointWebExtension.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(HealthEndpointWebExtension.class));
}
@Test
public void runWhenHealthEndpointIsDisabledShouldNotCreateExtensionBeans() {
this.contextRunner.withPropertyValues("management.endpoint.health.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(HealthEndpointWebExtension.class));
.run((context) -> assertThat(context).doesNotHaveBean(HealthEndpointWebExtension.class));
}
@Test
public void runWithCustomHealthMappingShouldMapStatusCode() {
this.contextRunner
.withPropertyValues("management.health.status.http-mapping.CUSTOM=500")
.run((context) -> {
Object extension = context.getBean(HealthEndpointWebExtension.class);
HealthWebEndpointResponseMapper responseMapper = (HealthWebEndpointResponseMapper) ReflectionTestUtils
.getField(extension, "responseMapper");
Class<SecurityContext> securityContext = SecurityContext.class;
assertThat(responseMapper
.map(Health.down().build(), mock(securityContext))
.getStatus()).isEqualTo(503);
assertThat(responseMapper.map(Health.status("OUT_OF_SERVICE").build(),
mock(securityContext)).getStatus()).isEqualTo(503);
assertThat(responseMapper
.map(Health.status("CUSTOM").build(), mock(securityContext))
.getStatus()).isEqualTo(500);
});
this.contextRunner.withPropertyValues("management.health.status.http-mapping.CUSTOM=500").run((context) -> {
Object extension = context.getBean(HealthEndpointWebExtension.class);
HealthWebEndpointResponseMapper responseMapper = (HealthWebEndpointResponseMapper) ReflectionTestUtils
.getField(extension, "responseMapper");
Class<SecurityContext> securityContext = SecurityContext.class;
assertThat(responseMapper.map(Health.down().build(), mock(securityContext)).getStatus()).isEqualTo(503);
assertThat(responseMapper.map(Health.status("OUT_OF_SERVICE").build(), mock(securityContext)).getStatus())
.isEqualTo(503);
assertThat(responseMapper.map(Health.status("CUSTOM").build(), mock(securityContext)).getStatus())
.isEqualTo(500);
});
}
@Test
public void unauthenticatedUsersAreNotShownDetailsByDefault() {
this.contextRunner.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertThat(
extension.health(mock(SecurityContext.class)).getBody().getDetails())
.isEmpty();
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertThat(extension.health(mock(SecurityContext.class)).getBody().getDetails()).isEmpty();
});
}
@Test
public void authenticatedUsersAreNotShownDetailsByDefault() {
this.contextRunner.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
assertThat(extension.health(securityContext).getBody().getDetails())
.isEmpty();
assertThat(extension.health(securityContext).getBody().getDetails()).isEmpty();
});
}
@Test
public void authenticatedUsersWhenAuthorizedCanBeShownDetails() {
this.contextRunner
.withPropertyValues(
"management.endpoint.health.show-details=when-authorized")
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
assertThat(extension.health(securityContext).getBody().getDetails())
.isNotEmpty();
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
assertThat(extension.health(securityContext).getBody().getDetails()).isNotEmpty();
});
}
@Test
public void unauthenticatedUsersCanBeShownDetails() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertThat(extension.health(null).getBody().getDetails())
.isNotEmpty();
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertThat(extension.health(null).getBody().getDetails()).isNotEmpty();
});
}
@Test
public void detailsCanBeHiddenFromAuthenticatedUsers() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=never")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertThat(extension.health(mock(SecurityContext.class)).getBody()
.getDetails()).isEmpty();
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=never").run((context) -> {
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertThat(extension.health(mock(SecurityContext.class)).getBody().getDetails()).isEmpty();
});
}
@Test
public void detailsCanBeHiddenFromUnauthorizedUsers() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ACTUATOR")).willReturn(false);
assertThat(extension.health(securityContext).getBody().getDetails())
.isEmpty();
assertThat(extension.health(securityContext).getBody().getDetails()).isEmpty();
});
}
@Test
public void detailsCanBeShownToAuthorizedUsers() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ACTUATOR")).willReturn(true);
assertThat(extension.health(securityContext).getBody().getDetails())
.isNotEmpty();
assertThat(extension.health(securityContext).getBody().getDetails()).isNotEmpty();
});
}
@Test
public void unauthenticatedUsersAreNotShownComponentByDefault() {
this.contextRunner.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(
extension.healthForComponent(mock(SecurityContext.class), "simple"));
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(extension.healthForComponent(mock(SecurityContext.class), "simple"));
});
}
@Test
public void authenticatedUsersAreNotShownComponentByDefault() {
this.contextRunner.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
assertDetailsNotFound(
extension.healthForComponent(securityContext, "simple"));
assertDetailsNotFound(extension.healthForComponent(securityContext, "simple"));
});
}
@Test
public void authenticatedUsersWhenAuthorizedCanBeShownComponent() {
this.contextRunner
.withPropertyValues(
"management.endpoint.health.show-details=when-authorized")
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
assertSimpleComponent(
extension.healthForComponent(securityContext, "simple"));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
assertSimpleComponent(extension.healthForComponent(securityContext, "simple"));
});
}
@Test
public void unauthenticatedUsersCanBeShownComponent() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertSimpleComponent(extension.healthForComponent(null, "simple"));
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertSimpleComponent(extension.healthForComponent(null, "simple"));
});
}
@Test
public void componentCanBeHiddenFromAuthenticatedUsers() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=never")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(extension
.healthForComponent(mock(SecurityContext.class), "simple"));
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=never").run((context) -> {
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(extension.healthForComponent(mock(SecurityContext.class), "simple"));
});
}
@Test
public void componentCanBeHiddenFromUnauthorizedUsers() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ACTUATOR")).willReturn(false);
assertDetailsNotFound(
extension.healthForComponent(securityContext, "simple"));
assertDetailsNotFound(extension.healthForComponent(securityContext, "simple"));
});
}
@Test
public void componentCanBeShownToAuthorizedUsers() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ACTUATOR")).willReturn(true);
assertSimpleComponent(
extension.healthForComponent(securityContext, "simple"));
assertSimpleComponent(extension.healthForComponent(securityContext, "simple"));
});
}
@Test
public void componentThatDoesNotExistMapTo404() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(
extension.healthForComponent(null, "does-not-exist"));
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(extension.healthForComponent(null, "does-not-exist"));
});
}
@Test
public void unauthenticatedUsersAreNotShownComponentInstanceByDefault() {
this.contextRunner.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(extension.healthForComponentInstance(
mock(SecurityContext.class), "composite", "one"));
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(
extension.healthForComponentInstance(mock(SecurityContext.class), "composite", "one"));
});
}
@Test
public void authenticatedUsersAreNotShownComponentInstanceByDefault() {
this.contextRunner.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
assertDetailsNotFound(extension.healthForComponentInstance(securityContext,
"composite", "one"));
assertDetailsNotFound(extension.healthForComponentInstance(securityContext, "composite", "one"));
});
}
@Test
public void authenticatedUsersWhenAuthorizedCanBeShownComponentInstance() {
this.contextRunner
.withPropertyValues(
"management.endpoint.health.show-details=when-authorized")
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
assertSimpleComponent(extension.healthForComponentInstance(
securityContext, "composite", "one"));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
assertSimpleComponent(extension.healthForComponentInstance(securityContext, "composite", "one"));
});
}
@Test
public void unauthenticatedUsersCanBeShownComponentInstance() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertSimpleComponent(extension.healthForComponentInstance(null,
"composite", "one"));
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertSimpleComponent(extension.healthForComponentInstance(null, "composite", "one"));
});
}
@Test
public void componentInstanceCanBeHiddenFromAuthenticatedUsers() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=never")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(extension.healthForComponentInstance(
mock(SecurityContext.class), "composite", "one"));
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=never").run((context) -> {
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(
extension.healthForComponentInstance(mock(SecurityContext.class), "composite", "one"));
});
}
@Test
public void componentInstanceCanBeHiddenFromUnauthorizedUsers() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ACTUATOR")).willReturn(false);
assertDetailsNotFound(extension.healthForComponentInstance(
securityContext, "composite", "one"));
assertDetailsNotFound(extension.healthForComponentInstance(securityContext, "composite", "one"));
});
}
@Test
public void componentInstanceCanBeShownToAuthorizedUsers() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ACTUATOR")).willReturn(true);
assertSimpleComponent(extension.healthForComponentInstance(
securityContext, "composite", "one"));
assertSimpleComponent(extension.healthForComponentInstance(securityContext, "composite", "one"));
});
}
@Test
public void componentInstanceThatDoesNotExistMapTo404() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(extension.healthForComponentInstance(null,
"composite", "does-not-exist"));
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
assertDetailsNotFound(extension.healthForComponentInstance(null, "composite", "does-not-exist"));
});
}
private void assertDetailsNotFound(WebEndpointResponse<?> response) {
@@ -407,17 +318,13 @@ public class HealthEndpointWebExtensionTests {
@Test
public void roleCanBeCustomized() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ADMIN").run((context) -> {
HealthEndpointWebExtension extension = context
.getBean(HealthEndpointWebExtension.class);
HealthEndpointWebExtension extension = context.getBean(HealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ADMIN")).willReturn(true);
assertThat(extension.health(securityContext).getBody().getDetails())
.isNotEmpty();
assertThat(extension.health(securityContext).getBody().getDetails()).isNotEmpty();
});
}
@@ -434,8 +341,7 @@ public class HealthEndpointWebExtensionTests {
Map<String, HealthIndicator> nestedIndicators = new HashMap<>();
nestedIndicators.put("one", simpleHealthIndicator());
nestedIndicators.put("two", () -> Health.up().build());
return new CompositeHealthIndicator(new OrderedHealthAggregator(),
nestedIndicators);
return new CompositeHealthIndicator(new OrderedHealthAggregator(), nestedIndicators);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -43,14 +43,12 @@ import static org.assertj.core.api.Assertions.assertThat;
public class HealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(HealthIndicatorAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(HealthIndicatorAutoConfiguration.class));
@Test
public void runWhenNoOtherIndicatorsShouldCreateDefaultApplicationHealthIndicator() {
this.contextRunner
.run((context) -> assertThat(context).getBean(HealthIndicator.class)
.isInstanceOf(ApplicationHealthIndicator.class));
this.contextRunner.run((context) -> assertThat(context).getBean(HealthIndicator.class)
.isInstanceOf(ApplicationHealthIndicator.class));
}
@Test
@@ -63,17 +61,15 @@ public class HealthIndicatorAutoConfigurationTests {
@Test
public void runWhenHasDefaultsDisabledAndNoSingleIndicatorEnabledShouldCreateDefaultApplicationHealthIndicator() {
this.contextRunner.withUserConfiguration(CustomHealthIndicatorConfiguration.class)
.withPropertyValues("management.health.defaults.enabled:false")
.run((context) -> assertThat(context).getBean(HealthIndicator.class)
.isInstanceOf(ApplicationHealthIndicator.class));
.withPropertyValues("management.health.defaults.enabled:false").run((context) -> assertThat(context)
.getBean(HealthIndicator.class).isInstanceOf(ApplicationHealthIndicator.class));
}
@Test
public void runWhenHasDefaultsDisabledAndSingleIndicatorEnabledShouldCreateEnabledIndicator() {
this.contextRunner.withUserConfiguration(CustomHealthIndicatorConfiguration.class)
.withPropertyValues("management.health.defaults.enabled:false",
"management.health.custom.enabled:true")
.withPropertyValues("management.health.defaults.enabled:false", "management.health.custom.enabled:true")
.run((context) -> assertThat(context).getBean(HealthIndicator.class)
.isInstanceOf(CustomHealthIndicator.class));
@@ -81,29 +77,25 @@ public class HealthIndicatorAutoConfigurationTests {
@Test
public void runShouldCreateOrderedHealthAggregator() {
this.contextRunner
.run((context) -> assertThat(context).getBean(HealthAggregator.class)
.isInstanceOf(OrderedHealthAggregator.class));
this.contextRunner.run((context) -> assertThat(context).getBean(HealthAggregator.class)
.isInstanceOf(OrderedHealthAggregator.class));
}
@Test
public void runWhenHasCustomOrderPropertyShouldCreateOrderedHealthAggregator() {
this.contextRunner.withPropertyValues("management.health.status.order:UP,DOWN")
.run((context) -> {
OrderedHealthAggregator aggregator = context
.getBean(OrderedHealthAggregator.class);
Map<String, Health> healths = new LinkedHashMap<>();
healths.put("foo", Health.up().build());
healths.put("bar", Health.down().build());
Health aggregate = aggregator.aggregate(healths);
assertThat(aggregate.getStatus()).isEqualTo(Status.UP);
});
this.contextRunner.withPropertyValues("management.health.status.order:UP,DOWN").run((context) -> {
OrderedHealthAggregator aggregator = context.getBean(OrderedHealthAggregator.class);
Map<String, Health> healths = new LinkedHashMap<>();
healths.put("foo", Health.up().build());
healths.put("bar", Health.down().build());
Health aggregate = aggregator.aggregate(healths);
assertThat(aggregate.getStatus()).isEqualTo(Status.UP);
});
}
@Test
public void runWhenHasCustomHealthAggregatorShouldNotCreateOrderedHealthAggregator() {
this.contextRunner
.withUserConfiguration(CustomHealthAggregatorConfiguration.class)
this.contextRunner.withUserConfiguration(CustomHealthAggregatorConfiguration.class)
.run((context) -> assertThat(context).getBean(HealthAggregator.class)
.isNotInstanceOf(OrderedHealthAggregator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,196 +49,157 @@ import static org.mockito.Mockito.mock;
public class ReactiveHealthEndpointWebExtensionTests {
private ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
.withUserConfiguration(HealthIndicatorAutoConfiguration.class,
HealthEndpointAutoConfiguration.class);
.withUserConfiguration(HealthIndicatorAutoConfiguration.class, HealthEndpointAutoConfiguration.class);
@Test
public void runShouldCreateExtensionBeans() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(ReactiveHealthEndpointWebExtension.class));
this.contextRunner
.run((context) -> assertThat(context).hasSingleBean(ReactiveHealthEndpointWebExtension.class));
}
@Test
public void runWhenHealthEndpointIsDisabledShouldNotCreateExtensionBeans() {
this.contextRunner.withPropertyValues("management.endpoint.health.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(ReactiveHealthEndpointWebExtension.class));
.run((context) -> assertThat(context).doesNotHaveBean(ReactiveHealthEndpointWebExtension.class));
}
@Test
public void runWithCustomHealthMappingShouldMapStatusCode() {
this.contextRunner
.withPropertyValues("management.health.status.http-mapping.CUSTOM=500")
.run((context) -> {
Object extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
HealthWebEndpointResponseMapper responseMapper = (HealthWebEndpointResponseMapper) ReflectionTestUtils
.getField(extension, "responseMapper");
Class<SecurityContext> securityContext = SecurityContext.class;
assertThat(responseMapper
.map(Health.down().build(), mock(securityContext))
.getStatus()).isEqualTo(503);
assertThat(responseMapper.map(Health.status("OUT_OF_SERVICE").build(),
mock(securityContext)).getStatus()).isEqualTo(503);
assertThat(responseMapper
.map(Health.status("CUSTOM").build(), mock(securityContext))
.getStatus()).isEqualTo(500);
});
this.contextRunner.withPropertyValues("management.health.status.http-mapping.CUSTOM=500").run((context) -> {
Object extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
HealthWebEndpointResponseMapper responseMapper = (HealthWebEndpointResponseMapper) ReflectionTestUtils
.getField(extension, "responseMapper");
Class<SecurityContext> securityContext = SecurityContext.class;
assertThat(responseMapper.map(Health.down().build(), mock(securityContext)).getStatus()).isEqualTo(503);
assertThat(responseMapper.map(Health.status("OUT_OF_SERVICE").build(), mock(securityContext)).getStatus())
.isEqualTo(503);
assertThat(responseMapper.map(Health.status("CUSTOM").build(), mock(securityContext)).getStatus())
.isEqualTo(500);
});
}
@Test
public void regularAndReactiveHealthIndicatorsMatch() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.withUserConfiguration(HealthIndicatorsConfiguration.class)
.run((context) -> {
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always")
.withUserConfiguration(HealthIndicatorsConfiguration.class).run((context) -> {
HealthEndpoint endpoint = context.getBean(HealthEndpoint.class);
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
Health endpointHealth = endpoint.health();
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
Health extensionHealth = extension.health(securityContext)
.block(Duration.ofSeconds(30)).getBody();
assertThat(endpointHealth.getDetails())
.containsOnlyKeys("application", "first", "second");
assertThat(extensionHealth.getDetails())
.containsOnlyKeys("application", "first", "second");
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
Health extensionHealth = extension.health(securityContext).block(Duration.ofSeconds(30)).getBody();
assertThat(endpointHealth.getDetails()).containsOnlyKeys("application", "first", "second");
assertThat(extensionHealth.getDetails()).containsOnlyKeys("application", "first", "second");
});
}
@Test
public void unauthenticatedUsersAreNotShownDetailsByDefault() {
this.contextRunner.run((context) -> {
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
assertThat(extension.health(mock(SecurityContext.class))
.block(Duration.ofSeconds(30)).getBody().getDetails()).isEmpty();
ReactiveHealthEndpointWebExtension extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
assertThat(
extension.health(mock(SecurityContext.class)).block(Duration.ofSeconds(30)).getBody().getDetails())
.isEmpty();
});
}
@Test
public void authenticatedUsersAreNotShownDetailsByDefault() {
this.contextRunner.run((context) -> {
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
ReactiveHealthEndpointWebExtension extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30))
.getBody().getDetails()).isEmpty();
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
.isEmpty();
});
}
@Test
public void authenticatedUsersWhenAuthorizedCanBeShownDetails() {
this.contextRunner
.withPropertyValues(
"management.endpoint.health.show-details=when-authorized")
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized")
.run((context) -> {
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
assertThat(extension.health(securityContext)
.block(Duration.ofSeconds(30)).getBody().getDetails())
.isNotEmpty();
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
.isNotEmpty();
});
}
@Test
public void unauthenticatedUsersCanBeShownDetails() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=always")
.run((context) -> {
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
assertThat(extension.health(null).block(Duration.ofSeconds(30))
.getBody().getDetails()).isNotEmpty();
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
ReactiveHealthEndpointWebExtension extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
assertThat(extension.health(null).block(Duration.ofSeconds(30)).getBody().getDetails()).isNotEmpty();
});
}
@Test
public void detailsCanBeHiddenFromAuthenticatedUsers() {
this.contextRunner
.withPropertyValues("management.endpoint.health.show-details=never")
.run((context) -> {
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
assertThat(extension.health(securityContext)
.block(Duration.ofSeconds(30)).getBody().getDetails())
.isEmpty();
});
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=never").run((context) -> {
ReactiveHealthEndpointWebExtension extension = context.getBean(ReactiveHealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
.isEmpty();
});
}
@Test
public void detailsCanBeHiddenFromUnauthorizedUsers() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ACTUATOR")).willReturn(false);
assertThat(extension.health(securityContext)
.block(Duration.ofSeconds(30)).getBody().getDetails())
.isEmpty();
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
.isEmpty();
});
}
@Test
public void detailsCanBeShownToAuthorizedUsers() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ACTUATOR").run((context) -> {
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ACTUATOR")).willReturn(true);
assertThat(extension.health(securityContext)
.block(Duration.ofSeconds(30)).getBody().getDetails())
.isNotEmpty();
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
.isNotEmpty();
});
}
@Test
public void roleCanBeCustomized() {
this.contextRunner.withPropertyValues(
"management.endpoint.health.show-details=when-authorized",
this.contextRunner.withPropertyValues("management.endpoint.health.show-details=when-authorized",
"management.endpoint.health.roles=ADMIN").run((context) -> {
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
SecurityContext securityContext = mock(SecurityContext.class);
given(securityContext.getPrincipal())
.willReturn(mock(Principal.class));
given(securityContext.getPrincipal()).willReturn(mock(Principal.class));
given(securityContext.isUserInRole("ADMIN")).willReturn(true);
assertThat(extension.health(securityContext)
.block(Duration.ofSeconds(30)).getBody().getDetails())
.isNotEmpty();
assertThat(extension.health(securityContext).block(Duration.ofSeconds(30)).getBody().getDetails())
.isNotEmpty();
});
}
@Test
public void registryCanBeAltered() {
this.contextRunner.withUserConfiguration(HealthIndicatorsConfiguration.class)
.withPropertyValues("management.endpoint.health.show-details=always")
.run((context) -> {
ReactiveHealthIndicatorRegistry registry = context
.getBean(ReactiveHealthIndicatorRegistry.class);
.withPropertyValues("management.endpoint.health.show-details=always").run((context) -> {
ReactiveHealthIndicatorRegistry registry = context.getBean(ReactiveHealthIndicatorRegistry.class);
ReactiveHealthEndpointWebExtension extension = context
.getBean(ReactiveHealthEndpointWebExtension.class);
assertThat(extension.health(null).block(Duration.ofSeconds(30))
.getBody().getDetails()).containsOnlyKeys("application",
"first", "second");
assertThat(extension.health(null).block(Duration.ofSeconds(30)).getBody().getDetails())
.containsOnlyKeys("application", "first", "second");
assertThat(registry.unregister("second")).isNotNull();
assertThat(extension.health(null).block(Duration.ofSeconds(30))
.getBody().getDetails()).containsKeys("application", "first");
assertThat(extension.health(null).block(Duration.ofSeconds(30)).getBody().getDetails())
.containsKeys("application", "first");
});
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,22 +38,19 @@ import static org.mockito.Mockito.mock;
public class InfluxDbHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(InfluxDbConfiguration.class).withConfiguration(
AutoConfigurations.of(InfluxDbHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
.withUserConfiguration(InfluxDbConfiguration.class).withConfiguration(AutoConfigurations
.of(InfluxDbHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(InfluxDbHealthIndicator.class)
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(InfluxDbHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.influxdb.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(InfluxDbHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(InfluxDbHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -54,36 +54,30 @@ public class InfoContributorAutoConfigurationTests {
@Test
public void disableEnvContributor() {
load("management.info.env.enabled:false");
Map<String, InfoContributor> beans = this.context
.getBeansOfType(InfoContributor.class);
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).hasSize(0);
}
@Test
public void defaultInfoContributorsDisabled() {
load("management.info.defaults.enabled:false");
Map<String, InfoContributor> beans = this.context
.getBeansOfType(InfoContributor.class);
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).hasSize(0);
}
@Test
public void defaultInfoContributorsDisabledWithCustomOne() {
load(CustomInfoContributorConfiguration.class,
"management.info.defaults.enabled:false");
Map<String, InfoContributor> beans = this.context
.getBeansOfType(InfoContributor.class);
load(CustomInfoContributorConfiguration.class, "management.info.defaults.enabled:false");
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).hasSize(1);
assertThat(this.context.getBean("customInfoContributor"))
.isSameAs(beans.values().iterator().next());
assertThat(this.context.getBean("customInfoContributor")).isSameAs(beans.values().iterator().next());
}
@SuppressWarnings("unchecked")
@Test
public void gitPropertiesDefaultMode() {
load(GitPropertiesConfiguration.class);
Map<String, InfoContributor> beans = this.context
.getBeansOfType(InfoContributor.class);
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).containsKeys("gitInfoContributor");
Map<String, Object> content = invokeContributor(
this.context.getBean("gitInfoContributor", InfoContributor.class));
@@ -117,8 +111,7 @@ public class InfoContributorAutoConfigurationTests {
@Test
public void buildProperties() {
load(BuildPropertiesConfiguration.class);
Map<String, InfoContributor> beans = this.context
.getBeansOfType(InfoContributor.class);
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).containsKeys("buildInfoContributor");
Map<String, Object> content = invokeContributor(
this.context.getBean("buildInfoContributor", InfoContributor.class));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,8 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat;
public class InfoEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(InfoEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(InfoEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
@@ -51,8 +50,7 @@ public class InfoEndpointAutoConfigurationTests {
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner.withPropertyValues("management.endpoint.info.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(InfoEndpoint.class));
.run((context) -> assertThat(context).doesNotHaveBean(InfoEndpoint.class));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,31 +36,26 @@ import static org.assertj.core.api.Assertions.assertThat;
public class IntegrationGraphEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class,
IntegrationAutoConfiguration.class,
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class, IntegrationAutoConfiguration.class,
IntegrationGraphEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(IntegrationGraphEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(IntegrationGraphEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner
.withPropertyValues("management.endpoint.integrationgraph.enabled:false")
.run((context) -> {
assertThat(context).doesNotHaveBean(IntegrationGraphEndpoint.class);
assertThat(context).doesNotHaveBean(IntegrationGraphServer.class);
});
this.contextRunner.withPropertyValues("management.endpoint.integrationgraph.enabled:false").run((context) -> {
assertThat(context).doesNotHaveBean(IntegrationGraphEndpoint.class);
assertThat(context).doesNotHaveBean(IntegrationGraphServer.class);
});
}
@Test
public void runWhenSpringIntegrationIsNotEnabledShouldNotHaveEndpointBean() {
ApplicationContextRunner noSpringIntegrationRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations
.of(IntegrationGraphEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(IntegrationGraphEndpointAutoConfiguration.class));
noSpringIntegrationRunner.run((context) -> {
assertThat(context).doesNotHaveBean(IntegrationGraphEndpoint.class);
assertThat(context).doesNotHaveBean(IntegrationGraphServer.class);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -57,25 +57,21 @@ public class ControllerEndpointWebFluxIntegrationTests {
@Test
public void endpointsCanBeAccessed() throws Exception {
TestSecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
TestSecurityContextHolder.getContext()
.setAuthentication(new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
this.context = new AnnotationConfigReactiveWebApplicationContext();
this.context.register(DefaultConfiguration.class, ExampleController.class);
TestPropertyValues.of("management.endpoints.web.exposure.include=*")
.applyTo(this.context);
TestPropertyValues.of("management.endpoints.web.exposure.include=*").applyTo(this.context);
this.context.refresh();
WebTestClient webClient = WebTestClient.bindToApplicationContext(this.context)
.build();
WebTestClient webClient = WebTestClient.bindToApplicationContext(this.context).build();
webClient.get().uri("/actuator/example").exchange().expectStatus().isOk();
}
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
ReactiveManagementContextAutoConfiguration.class,
AuditAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class,
WebFluxAutoConfiguration.class, ManagementContextAutoConfiguration.class,
BeansEndpointAutoConfiguration.class })
@ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
ReactiveManagementContextAutoConfiguration.class, AuditAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, WebFluxAutoConfiguration.class,
ManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class })
static class DefaultConfiguration {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -79,13 +79,12 @@ public class ControllerEndpointWebMvcIntegrationTests {
@Test
public void endpointsCanBeAccessed() throws Exception {
TestSecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
TestSecurityContextHolder.getContext()
.setAuthentication(new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
this.context = new AnnotationConfigWebApplicationContext();
this.context.register(SecureConfiguration.class, ExampleController.class);
TestPropertyValues
.of("management.endpoints.web.base-path:/management",
"management.endpoints.web.exposure.include=*")
.of("management.endpoints.web.base-path:/management", "management.endpoints.web.exposure.include=*")
.applyTo(this.context);
MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/management/example")).andExpect(status().isOk());
@@ -105,13 +104,11 @@ public class ControllerEndpointWebMvcIntegrationTests {
return builder.build();
}
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
@ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class, AuditAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
ManagementContextAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
BeansEndpointAutoConfiguration.class })
static class DefaultConfiguration {

View File

@@ -47,8 +47,7 @@ public class JerseyEndpointIntegrationTests {
@Test
public void linksAreProvidedToAllEndpointTypes() {
testJerseyEndpoints(new Class[] { EndpointsConfiguration.class,
ResourceConfigConfiguration.class });
testJerseyEndpoints(new Class[] { EndpointsConfiguration.class, ResourceConfigConfiguration.class });
}
@Test
@@ -57,33 +56,23 @@ public class JerseyEndpointIntegrationTests {
}
protected void testJerseyEndpoints(Class<?>[] userConfigurations) {
FilteredClassLoader classLoader = new FilteredClassLoader(
DispatcherServlet.class);
new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new)
.withClassLoader(classLoader)
.withConfiguration(
AutoConfigurations.of(JacksonAutoConfiguration.class,
JerseyAutoConfiguration.class,
EndpointAutoConfiguration.class,
ServletWebServerFactoryAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
BeansEndpointAutoConfiguration.class))
.withUserConfiguration(userConfigurations)
.withPropertyValues("management.endpoints.web.exposure.include:*",
"server.port:0")
.run((context) -> {
int port = context.getSourceApplicationContext(
AnnotationConfigServletWebServerApplicationContext.class)
.getWebServer().getPort();
WebTestClient client = WebTestClient.bindToServer()
.baseUrl("http://localhost:" + port).build();
client.get().uri("/actuator").exchange().expectStatus().isOk()
.expectBody().jsonPath("_links.beans").isNotEmpty()
.jsonPath("_links.restcontroller").doesNotExist()
.jsonPath("_links.controller").doesNotExist();
});
FilteredClassLoader classLoader = new FilteredClassLoader(DispatcherServlet.class);
new WebApplicationContextRunner(AnnotationConfigServletWebServerApplicationContext::new)
.withClassLoader(classLoader)
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, JerseyAutoConfiguration.class,
EndpointAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class,
WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
BeansEndpointAutoConfiguration.class))
.withUserConfiguration(userConfigurations)
.withPropertyValues("management.endpoints.web.exposure.include:*", "server.port:0").run((context) -> {
int port = context
.getSourceApplicationContext(AnnotationConfigServletWebServerApplicationContext.class)
.getWebServer().getPort();
WebTestClient client = WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build();
client.get().uri("/actuator").exchange().expectStatus().isOk().expectBody().jsonPath("_links.beans")
.isNotEmpty().jsonPath("_links.restcontroller").doesNotExist().jsonPath("_links.controller")
.doesNotExist();
});
}
@ControllerEndpoint(id = "controller")

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,52 +46,40 @@ import static org.assertj.core.api.Assertions.assertThat;
public class JmxEndpointIntegrationTests {
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class,
EndpointAutoConfiguration.class, JmxEndpointAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class,
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class, EndpointAutoConfiguration.class,
JmxEndpointAutoConfiguration.class, HealthIndicatorAutoConfiguration.class,
HttpTraceAutoConfiguration.class))
.withConfiguration(
AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL));
.withConfiguration(AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL));
@Test
public void jmxEndpointsAreExposed() {
this.contextRunner.run((context) -> {
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
checkEndpointMBeans(mBeanServer,
new String[] { "beans", "conditions", "configprops", "env", "health",
"info", "mappings", "threaddump", "httptrace" },
new String[] { "shutdown" });
checkEndpointMBeans(mBeanServer, new String[] { "beans", "conditions", "configprops", "env", "health",
"info", "mappings", "threaddump", "httptrace" }, new String[] { "shutdown" });
});
}
@Test
public void jmxEndpointsCanBeExcluded() {
this.contextRunner
.withPropertyValues("management.endpoints.jmx.exposure.exclude:*")
.run((context) -> {
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
checkEndpointMBeans(mBeanServer, new String[0],
new String[] { "beans", "conditions", "configprops", "env",
"health", "mappings", "shutdown", "threaddump",
"httptrace" });
this.contextRunner.withPropertyValues("management.endpoints.jmx.exposure.exclude:*").run((context) -> {
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
checkEndpointMBeans(mBeanServer, new String[0], new String[] { "beans", "conditions", "configprops", "env",
"health", "mappings", "shutdown", "threaddump", "httptrace" });
});
});
}
@Test
public void singleJmxEndpointCanBeExposed() {
this.contextRunner
.withPropertyValues("management.endpoints.jmx.exposure.include=beans")
.run((context) -> {
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
checkEndpointMBeans(mBeanServer, new String[] { "beans" },
new String[] { "conditions", "configprops", "env", "health",
"mappings", "shutdown", "threaddump", "httptrace" });
});
this.contextRunner.withPropertyValues("management.endpoints.jmx.exposure.include=beans").run((context) -> {
MBeanServer mBeanServer = context.getBean(MBeanServer.class);
checkEndpointMBeans(mBeanServer, new String[] { "beans" }, new String[] { "conditions", "configprops",
"env", "health", "mappings", "shutdown", "threaddump", "httptrace" });
});
}
private void checkEndpointMBeans(MBeanServer mBeanServer, String[] enabledEndpoints,
String[] disabledEndpoints) {
private void checkEndpointMBeans(MBeanServer mBeanServer, String[] enabledEndpoints, String[] disabledEndpoints) {
for (String enabledEndpoint : enabledEndpoints) {
assertThat(isRegistered(mBeanServer, getDefaultObjectName(enabledEndpoint)))
.as(String.format("Endpoint %s", enabledEndpoint)).isTrue();
@@ -112,14 +100,12 @@ public class JmxEndpointIntegrationTests {
}
}
private MBeanInfo getMBeanInfo(MBeanServer mBeanServer, ObjectName objectName)
throws InstanceNotFoundException {
private MBeanInfo getMBeanInfo(MBeanServer mBeanServer, ObjectName objectName) throws InstanceNotFoundException {
try {
return mBeanServer.getMBeanInfo(objectName);
}
catch (ReflectionException | IntrospectionException ex) {
throw new IllegalStateException(
"Failed to retrieve MBeanInfo for ObjectName " + objectName, ex);
throw new IllegalStateException("Failed to retrieve MBeanInfo for ObjectName " + objectName, ex);
}
}
@@ -129,8 +115,8 @@ public class JmxEndpointIntegrationTests {
private ObjectName getObjectName(String domain, String endpointId) {
try {
return new ObjectName(String.format("%s:type=Endpoint,name=%s", domain,
StringUtils.capitalize(endpointId)));
return new ObjectName(
String.format("%s:type=Endpoint,name=%s", domain, StringUtils.capitalize(endpointId)));
}
catch (MalformedObjectNameException ex) {
throw new IllegalStateException("Invalid object name", ex);

View File

@@ -68,8 +68,7 @@ public class JolokiaEndpointAutoConfigurationIntegrationTests {
@Test
public void jolokiaIsExposed() {
ResponseEntity<String> response = this.restTemplate
.getForEntity("/actuator/jolokia", String.class);
ResponseEntity<String> response = this.restTemplate.getForEntity("/actuator/jolokia", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).contains("\"agent\"");
assertThat(response.getBody()).contains("\"request\":{\"type\"");
@@ -77,36 +76,33 @@ public class JolokiaEndpointAutoConfigurationIntegrationTests {
@Test
public void search() {
ResponseEntity<String> response = this.restTemplate
.getForEntity("/actuator/jolokia/search/java.lang:*", String.class);
ResponseEntity<String> response = this.restTemplate.getForEntity("/actuator/jolokia/search/java.lang:*",
String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).contains("GarbageCollector");
}
@Test
public void read() {
ResponseEntity<String> response = this.restTemplate.getForEntity(
"/actuator/jolokia/read/java.lang:type=Memory", String.class);
ResponseEntity<String> response = this.restTemplate.getForEntity("/actuator/jolokia/read/java.lang:type=Memory",
String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).contains("NonHeapMemoryUsage");
}
@Test
public void list() {
ResponseEntity<String> response = this.restTemplate.getForEntity(
"/actuator/jolokia/list/java.lang/type=Memory/attr", String.class);
ResponseEntity<String> response = this.restTemplate
.getForEntity("/actuator/jolokia/list/java.lang/type=Memory/attr", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(response.getBody()).contains("NonHeapMemoryUsage");
}
@Configuration
@MinimalWebConfiguration
@Import({ JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
JolokiaEndpointAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
@Import({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
JolokiaEndpointAutoConfiguration.class, EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class, ManagementContextAutoConfiguration.class,
ServletEndpointManagementContextConfiguration.class })
protected static class Application {
@@ -115,9 +111,8 @@ public class JolokiaEndpointAutoConfigurationIntegrationTests {
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ ServletWebServerFactoryAutoConfiguration.class,
DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class,
WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
@Import({ ServletWebServerFactoryAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
ValidationAutoConfiguration.class, WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
ErrorMvcAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class })
protected @interface MinimalWebConfiguration {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -57,40 +57,34 @@ public class WebEndpointsAutoConfigurationIntegrationTests {
@Test
public void healthEndpointWebExtensionIsAutoConfigured() {
servletWebRunner()
.run((context) -> context.getBean(WebEndpointTestApplication.class));
servletWebRunner().run((context) -> assertThat(context)
.hasSingleBean(HealthEndpointWebExtension.class));
servletWebRunner().run((context) -> context.getBean(WebEndpointTestApplication.class));
servletWebRunner().run((context) -> assertThat(context).hasSingleBean(HealthEndpointWebExtension.class));
}
@Test
public void healthEndpointReactiveWebExtensionIsAutoConfigured() {
reactiveWebRunner().run((context) -> assertThat(context)
.hasSingleBean(ReactiveHealthEndpointWebExtension.class));
reactiveWebRunner()
.run((context) -> assertThat(context).hasSingleBean(ReactiveHealthEndpointWebExtension.class));
}
private WebApplicationContextRunner servletWebRunner() {
return new WebApplicationContextRunner().withConfiguration(
UserConfigurations.of(WebEndpointTestApplication.class));
return new WebApplicationContextRunner()
.withConfiguration(UserConfigurations.of(WebEndpointTestApplication.class));
}
private ReactiveWebApplicationContextRunner reactiveWebRunner() {
return new ReactiveWebApplicationContextRunner().withConfiguration(
UserConfigurations.of(WebEndpointTestApplication.class));
return new ReactiveWebApplicationContextRunner()
.withConfiguration(UserConfigurations.of(WebEndpointTestApplication.class));
}
@EnableAutoConfiguration(exclude = { FlywayAutoConfiguration.class,
LiquibaseAutoConfiguration.class, CassandraAutoConfiguration.class,
CassandraDataAutoConfiguration.class, Neo4jDataAutoConfiguration.class,
Neo4jRepositoriesAutoConfiguration.class, MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class, MongoReactiveAutoConfiguration.class,
MongoReactiveDataAutoConfiguration.class,
@EnableAutoConfiguration(exclude = { FlywayAutoConfiguration.class, LiquibaseAutoConfiguration.class,
CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class, Neo4jDataAutoConfiguration.class,
Neo4jRepositoriesAutoConfiguration.class, MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
MongoReactiveAutoConfiguration.class, MongoReactiveDataAutoConfiguration.class,
RepositoryRestMvcAutoConfiguration.class, HazelcastAutoConfiguration.class,
ElasticsearchAutoConfiguration.class,
ElasticsearchDataAutoConfiguration.class, JestAutoConfiguration.class,
SolrRepositoriesAutoConfiguration.class, SolrAutoConfiguration.class,
RedisAutoConfiguration.class, RedisRepositoriesAutoConfiguration.class,
MetricsAutoConfiguration.class })
ElasticsearchAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class, JestAutoConfiguration.class,
SolrRepositoriesAutoConfiguration.class, SolrAutoConfiguration.class, RedisAutoConfiguration.class,
RedisRepositoriesAutoConfiguration.class, MetricsAutoConfiguration.class })
@SpringBootConfiguration
public static class WebEndpointTestApplication {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -47,123 +47,89 @@ public class WebFluxEndpointCorsIntegrationTests {
@Before
public void createContext() {
this.context = new AnnotationConfigReactiveWebApplicationContext();
this.context.register(JacksonAutoConfiguration.class,
CodecsAutoConfiguration.class, WebFluxAutoConfiguration.class,
HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ReactiveManagementContextAutoConfiguration.class,
BeansEndpointAutoConfiguration.class);
TestPropertyValues.of("management.endpoints.web.exposure.include:*")
.applyTo(this.context);
this.context.register(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class,
WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class, ManagementContextAutoConfiguration.class,
ReactiveManagementContextAutoConfiguration.class, BeansEndpointAutoConfiguration.class);
TestPropertyValues.of("management.endpoints.web.exposure.include:*").applyTo(this.context);
}
@Test
public void corsIsDisabledByDefault() {
createWebTestClient().options().uri("/actuator/beans")
.header("Origin", "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange()
.expectStatus().isForbidden().expectHeader()
.doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN);
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange().expectStatus().isForbidden()
.expectHeader().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN);
}
@Test
public void settingAllowedOriginsEnablesCors() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org")
.applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans")
.header("Origin", "test.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange()
.expectStatus().isForbidden();
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org").applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans").header("Origin", "test.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange().expectStatus().isForbidden();
performAcceptedCorsRequest("/actuator/beans");
}
@Test
public void maxAgeDefaultsTo30Minutes() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org")
.applyTo(this.context);
performAcceptedCorsRequest("/actuator/beans").expectHeader()
.valueEquals(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800");
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org").applyTo(this.context);
performAcceptedCorsRequest("/actuator/beans").expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_MAX_AGE,
"1800");
}
@Test
public void maxAgeCanBeConfigured() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.max-age: 2400")
.applyTo(this.context);
performAcceptedCorsRequest("/actuator/beans").expectHeader()
.valueEquals(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "2400");
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.max-age: 2400").applyTo(this.context);
performAcceptedCorsRequest("/actuator/beans").expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_MAX_AGE,
"2400");
}
@Test
public void requestsWithDisallowedHeadersAreRejected() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org")
.applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans")
.header("Origin", "spring.example.org")
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org").applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha").exchange()
.expectStatus().isForbidden();
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha").exchange().expectStatus().isForbidden();
}
@Test
public void allowedHeadersCanBeConfigured() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.allowed-headers:Alpha,Bravo")
.applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans")
.header("Origin", "spring.example.org")
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.allowed-headers:Alpha,Bravo").applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha").exchange()
.expectStatus().isOk().expectHeader()
.valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha");
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha").exchange().expectStatus().isOk()
.expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha");
}
@Test
public void requestsWithDisallowedMethodsAreRejected() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org")
.applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans")
.header("Origin", "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PATCH").exchange()
.expectStatus().isForbidden();
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org").applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PATCH").exchange().expectStatus().isForbidden();
}
@Test
public void allowedMethodsCanBeConfigured() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.allowed-methods:GET,HEAD")
.applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans")
.header("Origin", "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD").exchange()
.expectStatus().isOk().expectHeader()
.valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,HEAD");
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.allowed-methods:GET,HEAD").applyTo(this.context);
createWebTestClient().options().uri("/actuator/beans").header("Origin", "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD").exchange().expectStatus().isOk()
.expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,HEAD");
}
@Test
public void credentialsCanBeAllowed() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.allow-credentials:true")
.applyTo(this.context);
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.allow-credentials:true").applyTo(this.context);
performAcceptedCorsRequest("/actuator/beans").expectHeader()
.valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
}
@Test
public void credentialsCanBeDisabled() {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.allow-credentials:false")
.applyTo(this.context);
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:spring.example.org",
"management.endpoints.web.cors.allow-credentials:false").applyTo(this.context);
performAcceptedCorsRequest("/actuator/beans").expectHeader()
.doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS);
}
@@ -175,12 +141,9 @@ public class WebFluxEndpointCorsIntegrationTests {
}
private WebTestClient.ResponseSpec performAcceptedCorsRequest(String url) {
return createWebTestClient().options().uri(url)
.header(HttpHeaders.ORIGIN, "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange()
.expectHeader().valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,
"spring.example.org")
.expectStatus().isOk();
return createWebTestClient().options().uri(url).header(HttpHeaders.ORIGIN, "spring.example.org")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").exchange().expectHeader()
.valueEquals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "spring.example.org").expectStatus().isOk();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -46,28 +46,23 @@ public class WebFluxEndpointIntegrationTests {
@Test
public void linksAreProvidedToAllEndpointTypes() throws Exception {
new ReactiveWebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class,
CodecsAutoConfiguration.class, WebFluxAutoConfiguration.class,
HttpHandlerAutoConfiguration.class,
EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ReactiveManagementContextAutoConfiguration.class,
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class, CodecsAutoConfiguration.class,
WebFluxAutoConfiguration.class, HttpHandlerAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
ManagementContextAutoConfiguration.class, ReactiveManagementContextAutoConfiguration.class,
BeansEndpointAutoConfiguration.class))
.withUserConfiguration(EndpointsConfiguration.class)
.withPropertyValues("management.endpoints.web.exposure.include:*")
.run((context) -> {
.withPropertyValues("management.endpoints.web.exposure.include:*").run((context) -> {
WebTestClient client = createWebTestClient(context);
client.get().uri("/actuator").exchange().expectStatus().isOk()
.expectBody().jsonPath("_links.beans").isNotEmpty()
.jsonPath("_links.restcontroller").isNotEmpty()
.jsonPath("_links.controller").isNotEmpty();
client.get().uri("/actuator").exchange().expectStatus().isOk().expectBody().jsonPath("_links.beans")
.isNotEmpty().jsonPath("_links.restcontroller").isNotEmpty().jsonPath("_links.controller")
.isNotEmpty();
});
}
private WebTestClient createWebTestClient(ApplicationContext context) {
return WebTestClient.bindToApplicationContext(context).configureClient()
.baseUrl("https://spring.example.org").build();
return WebTestClient.bindToApplicationContext(context).configureClient().baseUrl("https://spring.example.org")
.build();
}
@ControllerEndpoint(id = "controller")

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -55,15 +55,12 @@ public class WebMvcEndpointCorsIntegrationTests {
public void createContext() {
this.context = new AnnotationConfigWebApplicationContext();
this.context.setServletContext(new MockServletContext());
this.context.register(JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
this.context.register(JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
WebMvcAutoConfiguration.class, DispatcherServletAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
BeansEndpointAutoConfiguration.class);
TestPropertyValues.of("management.endpoints.web.exposure.include:*")
.applyTo(this.context);
TestPropertyValues.of("management.endpoints.web.exposure.include:*").applyTo(this.context);
}
@Test
@@ -71,111 +68,80 @@ public class WebMvcEndpointCorsIntegrationTests {
createMockMvc()
.perform(options("/actuator/beans").header("Origin", "foo.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"))
.andExpect(
header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
.andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
}
@Test
public void settingAllowedOriginsEnablesCors() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com")
.applyTo(this.context);
createMockMvc()
.perform(options("/actuator/beans").header("Origin", "bar.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"))
.andExpect(status().isForbidden());
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com").applyTo(this.context);
createMockMvc().perform(options("/actuator/beans").header("Origin", "bar.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")).andExpect(status().isForbidden());
performAcceptedCorsRequest();
}
@Test
public void maxAgeDefaultsTo30Minutes() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com")
.applyTo(this.context);
performAcceptedCorsRequest()
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800"));
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com").applyTo(this.context);
performAcceptedCorsRequest().andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800"));
}
@Test
public void maxAgeCanBeConfigured() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.max-age: 2400")
.applyTo(this.context);
performAcceptedCorsRequest()
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "2400"));
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.max-age: 2400").applyTo(this.context);
performAcceptedCorsRequest().andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "2400"));
}
@Test
public void requestsWithDisallowedHeadersAreRejected() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com")
.applyTo(this.context);
createMockMvc()
.perform(options("/actuator/beans").header("Origin", "foo.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha"))
.andExpect(status().isForbidden());
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com").applyTo(this.context);
createMockMvc().perform(options("/actuator/beans").header("Origin", "foo.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha")).andExpect(status().isForbidden());
}
@Test
public void allowedHeadersCanBeConfigured() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.allowed-headers:Alpha,Bravo")
.applyTo(this.context);
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.allowed-headers:Alpha,Bravo").applyTo(this.context);
createMockMvc()
.perform(options("/actuator/beans").header("Origin", "foo.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Alpha"))
.andExpect(status().isOk()).andExpect(header()
.string(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha"));
.andExpect(status().isOk())
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "Alpha"));
}
@Test
public void requestsWithDisallowedMethodsAreRejected() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com")
.applyTo(this.context);
createMockMvc()
.perform(options("/actuator/health")
.header(HttpHeaders.ORIGIN, "foo.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PATCH"))
.andExpect(status().isForbidden());
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com").applyTo(this.context);
createMockMvc().perform(options("/actuator/health").header(HttpHeaders.ORIGIN, "foo.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "PATCH")).andExpect(status().isForbidden());
}
@Test
public void allowedMethodsCanBeConfigured() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.allowed-methods:GET,HEAD")
.applyTo(this.context);
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.allowed-methods:GET,HEAD").applyTo(this.context);
createMockMvc()
.perform(options("/actuator/beans")
.header(HttpHeaders.ORIGIN, "foo.example.com")
.perform(options("/actuator/beans").header(HttpHeaders.ORIGIN, "foo.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "HEAD"))
.andExpect(status().isOk()).andExpect(header()
.string(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,HEAD"));
.andExpect(status().isOk())
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,HEAD"));
}
@Test
public void credentialsCanBeAllowed() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.allow-credentials:true")
.applyTo(this.context);
performAcceptedCorsRequest().andExpect(
header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"));
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.allow-credentials:true").applyTo(this.context);
performAcceptedCorsRequest().andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"));
}
@Test
public void credentialsCanBeDisabled() throws Exception {
TestPropertyValues
.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.allow-credentials:false")
.applyTo(this.context);
performAcceptedCorsRequest().andExpect(
header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
TestPropertyValues.of("management.endpoints.web.cors.allowed-origins:foo.example.com",
"management.endpoints.web.cors.allow-credentials:false").applyTo(this.context);
performAcceptedCorsRequest().andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
}
private MockMvc createMockMvc() {
@@ -191,8 +157,7 @@ public class WebMvcEndpointCorsIntegrationTests {
return createMockMvc()
.perform(options(url).header(HttpHeaders.ORIGIN, "foo.example.com")
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET"))
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,
"foo.example.com"))
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "foo.example.com"))
.andExpect(status().isOk());
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -62,24 +62,16 @@ import static org.assertj.core.api.Assertions.assertThat;
public class WebMvcEndpointExposureIntegrationTests {
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner(
AnnotationConfigServletWebServerApplicationContext::new).withConfiguration(
AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class,
WebMvcAutoConfiguration.class,
EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
HttpTraceAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class))
.withConfiguration(
AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL))
.withUserConfiguration(CustomMvcEndpoint.class,
CustomServletEndpoint.class)
AnnotationConfigServletWebServerApplicationContext::new)
.withConfiguration(AutoConfigurations.of(ServletWebServerFactoryAutoConfiguration.class,
DispatcherServletAutoConfiguration.class, JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, WebMvcAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
HttpTraceAutoConfiguration.class, HealthIndicatorAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(EndpointAutoConfigurationClasses.ALL))
.withUserConfiguration(CustomMvcEndpoint.class, CustomServletEndpoint.class)
.withPropertyValues("server.port:0");
@Test
@@ -146,8 +138,7 @@ public class WebMvcEndpointExposureIntegrationTests {
@Test
public void singleWebEndpointCanBeExcluded() {
WebApplicationContextRunner contextRunner = this.contextRunner.withPropertyValues(
"management.endpoints.web.exposure.include=*",
"management.endpoints.web.exposure.exclude=shutdown");
"management.endpoints.web.exposure.include=*", "management.endpoints.web.exposure.exclude=shutdown");
contextRunner.run((context) -> {
WebTestClient client = createClient(context);
assertThat(isExposed(client, HttpMethod.GET, "beans")).isTrue();
@@ -166,17 +157,14 @@ public class WebMvcEndpointExposureIntegrationTests {
}
private WebTestClient createClient(AssertableWebApplicationContext context) {
int port = context
.getSourceApplicationContext(ServletWebServerApplicationContext.class)
.getWebServer().getPort();
int port = context.getSourceApplicationContext(ServletWebServerApplicationContext.class).getWebServer()
.getPort();
return WebTestClient.bindToServer().baseUrl("http://localhost:" + port).build();
}
private boolean isExposed(WebTestClient client, HttpMethod method, String path)
throws Exception {
private boolean isExposed(WebTestClient client, HttpMethod method, String path) throws Exception {
path = "/actuator/" + path;
EntityExchangeResult<byte[]> result = client.method(method).uri(path).exchange()
.expectBody().returnResult();
EntityExchangeResult<byte[]> result = client.method(method).uri(path).exchange().expectBody().returnResult();
if (result.getStatus() == HttpStatus.OK) {
return true;
}
@@ -184,8 +172,7 @@ public class WebMvcEndpointExposureIntegrationTests {
return false;
}
throw new IllegalStateException(
String.format("Unexpected %s HTTP status for " + "endpoint %s",
result.getStatus(), path));
String.format("Unexpected %s HTTP status for " + "endpoint %s", result.getStatus(), path));
}
@RestControllerEndpoint(id = "custommvc")

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -83,16 +83,14 @@ public class WebMvcEndpointIntegrationTests {
this.context = new AnnotationConfigWebApplicationContext();
this.context.register(SecureConfiguration.class);
MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/actuator/beans").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
mockMvc.perform(get("/actuator/beans").accept(MediaType.APPLICATION_JSON)).andExpect(status().isUnauthorized());
}
@Test
public void endpointsAreSecureByDefaultWithCustomBasePath() throws Exception {
this.context = new AnnotationConfigWebApplicationContext();
this.context.register(SecureConfiguration.class);
TestPropertyValues.of("management.endpoints.web.base-path:/management")
.applyTo(this.context);
TestPropertyValues.of("management.endpoints.web.base-path:/management").applyTo(this.context);
MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/management/beans").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isUnauthorized());
@@ -100,13 +98,12 @@ public class WebMvcEndpointIntegrationTests {
@Test
public void endpointsAreSecureWithActuatorRoleWithCustomBasePath() throws Exception {
TestSecurityContextHolder.getContext().setAuthentication(
new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
TestSecurityContextHolder.getContext()
.setAuthentication(new TestingAuthenticationToken("user", "N/A", "ROLE_ACTUATOR"));
this.context = new AnnotationConfigWebApplicationContext();
this.context.register(SecureConfiguration.class);
TestPropertyValues
.of("management.endpoints.web.base-path:/management",
"management.endpoints.web.exposure.include=*")
.of("management.endpoints.web.base-path:/management", "management.endpoints.web.exposure.include=*")
.applyTo(this.context);
MockMvc mockMvc = createSecureMockMvc();
mockMvc.perform(get("/management/beans")).andExpect(status().isOk());
@@ -116,12 +113,10 @@ public class WebMvcEndpointIntegrationTests {
public void linksAreProvidedToAllEndpointTypes() throws Exception {
this.context = new AnnotationConfigWebApplicationContext();
this.context.register(DefaultConfiguration.class, EndpointsConfiguration.class);
TestPropertyValues.of("management.endpoints.web.exposure.include=*")
.applyTo(this.context);
TestPropertyValues.of("management.endpoints.web.exposure.include=*").applyTo(this.context);
MockMvc mockMvc = doCreateMockMvc();
mockMvc.perform(get("/actuator").accept("*/*")).andExpect(status().isOk())
.andExpect(jsonPath("_links", both(hasKey("beans")).and(hasKey("servlet"))
.and(hasKey("restcontroller")).and(hasKey("controller"))));
mockMvc.perform(get("/actuator").accept("*/*")).andExpect(status().isOk()).andExpect(jsonPath("_links",
both(hasKey("beans")).and(hasKey("servlet")).and(hasKey("restcontroller")).and(hasKey("controller"))));
}
private MockMvc createSecureMockMvc() {
@@ -138,14 +133,12 @@ public class WebMvcEndpointIntegrationTests {
return builder.build();
}
@ImportAutoConfiguration({ JacksonAutoConfiguration.class,
HttpMessageConvertersAutoConfiguration.class, EndpointAutoConfiguration.class,
WebEndpointAutoConfiguration.class,
@ImportAutoConfiguration({ JacksonAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class,
EndpointAutoConfiguration.class, WebEndpointAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class, AuditAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class, WebMvcAutoConfiguration.class,
ManagementContextAutoConfiguration.class, AuditAutoConfiguration.class,
DispatcherServletAutoConfiguration.class,
BeansEndpointAutoConfiguration.class })
DispatcherServletAutoConfiguration.class, BeansEndpointAutoConfiguration.class })
static class DefaultConfiguration {
}
@@ -157,8 +150,7 @@ public class WebMvcEndpointIntegrationTests {
}
@Import(SecureConfiguration.class)
@ImportAutoConfiguration({ HypermediaAutoConfiguration.class,
RepositoryRestMvcAutoConfiguration.class })
@ImportAutoConfiguration({ HypermediaAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class })
static class SpringDataRestConfiguration {
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,8 +49,7 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class,
DataSourceHealthIndicatorAutoConfiguration.class))
HealthIndicatorAutoConfiguration.class, DataSourceHealthIndicatorAutoConfiguration.class))
.withPropertyValues("spring.datasource.initialization-mode=never");
@Test
@@ -64,37 +63,28 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
@Test
public void runWhenMultipleDataSourceBeansShouldCreateCompositeIndicator() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
DataSourceConfig.class).run((context) -> {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, DataSourceConfig.class)
.run((context) -> {
assertThat(context).hasSingleBean(HealthIndicator.class);
HealthIndicator indicator = context
.getBean(CompositeHealthIndicator.class);
assertThat(indicator.health().getDetails())
.containsOnlyKeys("dataSource", "testDataSource");
HealthIndicator indicator = context.getBean(CompositeHealthIndicator.class);
assertThat(indicator.health().getDetails()).containsOnlyKeys("dataSource", "testDataSource");
});
}
@Test
public void runShouldFilterRoutingDataSource() {
this.contextRunner
.withUserConfiguration(EmbeddedDataSourceConfiguration.class,
RoutingDatasourceConfig.class)
.run((context) -> assertThat(context)
.hasSingleBean(DataSourceHealthIndicator.class)
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class, RoutingDatasourceConfig.class)
.run((context) -> assertThat(context).hasSingleBean(DataSourceHealthIndicator.class)
.doesNotHaveBean(CompositeHealthIndicator.class));
}
@Test
public void runWithValidationQueryPropertyShouldUseCustomQuery() {
this.contextRunner
.withUserConfiguration(DataSourceConfig.class,
DataSourcePoolMetadataProvidersConfiguration.class)
.withPropertyValues(
"spring.datasource.test.validation-query:SELECT from FOOBAR")
.run((context) -> {
.withUserConfiguration(DataSourceConfig.class, DataSourcePoolMetadataProvidersConfiguration.class)
.withPropertyValues("spring.datasource.test.validation-query:SELECT from FOOBAR").run((context) -> {
assertThat(context).hasSingleBean(HealthIndicator.class);
DataSourceHealthIndicator indicator = context
.getBean(DataSourceHealthIndicator.class);
DataSourceHealthIndicator indicator = context.getBean(DataSourceHealthIndicator.class);
assertThat(indicator.getQuery()).isEqualTo("SELECT from FOOBAR");
});
}
@@ -103,8 +93,7 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class)
.withPropertyValues("management.health.db.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(DataSourceHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(DataSourceHealthIndicator.class)
.doesNotHaveBean(CompositeHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}
@@ -116,10 +105,8 @@ public class DataSourceHealthIndicatorAutoConfigurationTests {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.test")
public DataSource testDataSource() {
return DataSourceBuilder.create()
.type(org.apache.tomcat.jdbc.pool.DataSource.class)
.driverClassName("org.hsqldb.jdbc.JDBCDriver")
.url("jdbc:hsqldb:mem:test").username("sa").build();
return DataSourceBuilder.create().type(org.apache.tomcat.jdbc.pool.DataSource.class)
.driverClassName("org.hsqldb.jdbc.JDBCDriver").url("jdbc:hsqldb:mem:test").username("sa").build();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -37,21 +37,18 @@ public class JmsHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(ActiveMQAutoConfiguration.class,
JmsHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
JmsHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(JmsHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(JmsHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.jms.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(LdapHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(LdapHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -49,49 +49,41 @@ import static org.assertj.core.api.Assertions.assertThat;
public class JolokiaEndpointAutoConfigurationTests {
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
DispatcherServletAutoConfiguration.class,
ManagementContextAutoConfiguration.class,
ServletManagementContextAutoConfiguration.class,
ServletEndpointManagementContextConfiguration.class,
JolokiaEndpointAutoConfiguration.class, TestConfiguration.class));
.withConfiguration(AutoConfigurations.of(DispatcherServletAutoConfiguration.class,
ManagementContextAutoConfiguration.class, ServletManagementContextAutoConfiguration.class,
ServletEndpointManagementContextConfiguration.class, JolokiaEndpointAutoConfiguration.class,
TestConfiguration.class));
@Test
public void jolokiaServletShouldBeEnabledByDefault() {
this.contextRunner.run((context) -> {
ExposableServletEndpoint endpoint = getEndpoint(context);
assertThat(endpoint.getRootPath()).isEqualTo("jolokia");
Object servlet = ReflectionTestUtils.getField(endpoint.getEndpointServlet(),
"servlet");
Object servlet = ReflectionTestUtils.getField(endpoint.getEndpointServlet(), "servlet");
assertThat(servlet).isInstanceOf(AgentServlet.class);
});
}
@Test
public void jolokiaServletWhenDisabledShouldNotBeDiscovered() {
this.contextRunner.withPropertyValues("management.endpoint.jolokia.enabled=false")
.run((context) -> {
Collection<ExposableServletEndpoint> endpoints = context
.getBean(ServletEndpointsSupplier.class).getEndpoints();
assertThat(endpoints).isEmpty();
});
this.contextRunner.withPropertyValues("management.endpoint.jolokia.enabled=false").run((context) -> {
Collection<ExposableServletEndpoint> endpoints = context.getBean(ServletEndpointsSupplier.class)
.getEndpoints();
assertThat(endpoints).isEmpty();
});
}
@Test
public void jolokiaServletWhenHasCustomConfigShouldApplyInitParams() {
this.contextRunner
.withPropertyValues("management.endpoint.jolokia.config.debug=true")
.run((context) -> {
ExposableServletEndpoint endpoint = getEndpoint(context);
assertThat(endpoint.getEndpointServlet()).extracting("initParameters")
.containsOnly(Collections.singletonMap("debug", "true"));
});
this.contextRunner.withPropertyValues("management.endpoint.jolokia.config.debug=true").run((context) -> {
ExposableServletEndpoint endpoint = getEndpoint(context);
assertThat(endpoint.getEndpointServlet()).extracting("initParameters")
.containsOnly(Collections.singletonMap("debug", "true"));
});
}
private ExposableServletEndpoint getEndpoint(
AssertableWebApplicationContext context) {
Collection<ExposableServletEndpoint> endpoints = context
.getBean(ServletEndpointsSupplier.class).getEndpoints();
private ExposableServletEndpoint getEndpoint(AssertableWebApplicationContext context) {
Collection<ExposableServletEndpoint> endpoints = context.getBean(ServletEndpointsSupplier.class).getEndpoints();
return endpoints.iterator().next();
}
@@ -99,10 +91,8 @@ public class JolokiaEndpointAutoConfigurationTests {
static class TestConfiguration {
@Bean
public ServletEndpointDiscoverer servletEndpointDiscoverer(
ApplicationContext applicationContext) {
return new ServletEndpointDiscoverer(applicationContext, null,
Collections.emptyList());
public ServletEndpointDiscoverer servletEndpointDiscoverer(ApplicationContext applicationContext) {
return new ServletEndpointDiscoverer(applicationContext, null, Collections.emptyList());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -40,22 +40,19 @@ import static org.mockito.Mockito.mock;
public class LdapHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(LdapConfiguration.class).withConfiguration(
AutoConfigurations.of(LdapHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class));
.withUserConfiguration(LdapConfiguration.class).withConfiguration(AutoConfigurations
.of(LdapHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class));
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(LdapHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(LdapHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.ldap.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(LdapHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(LdapHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,46 +38,37 @@ import static org.mockito.Mockito.mock;
public class LiquibaseEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(LiquibaseEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(LiquibaseEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.withUserConfiguration(LiquibaseConfiguration.class).run(
(context) -> assertThat(context).hasSingleBean(LiquibaseEndpoint.class));
this.contextRunner.withUserConfiguration(LiquibaseConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(LiquibaseEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner.withUserConfiguration(LiquibaseConfiguration.class)
.withPropertyValues("management.endpoint.liquibase.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(LiquibaseEndpoint.class));
.run((context) -> assertThat(context).doesNotHaveBean(LiquibaseEndpoint.class));
}
@Test
public void disablesCloseOfDataSourceWhenEndpointIsEnabled() {
this.contextRunner
.withUserConfiguration(DataSourceClosingLiquibaseConfiguration.class)
.run((context) -> {
assertThat(context).hasSingleBean(LiquibaseEndpoint.class);
assertThat(context.getBean(DataSourceClosingSpringLiquibase.class))
.hasFieldOrPropertyWithValue("closeDataSourceOnceMigrated",
false);
});
this.contextRunner.withUserConfiguration(DataSourceClosingLiquibaseConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(LiquibaseEndpoint.class);
assertThat(context.getBean(DataSourceClosingSpringLiquibase.class))
.hasFieldOrPropertyWithValue("closeDataSourceOnceMigrated", false);
});
}
@Test
public void doesNotDisableCloseOfDataSourceWhenEndpointIsDisabled() {
this.contextRunner
.withUserConfiguration(DataSourceClosingLiquibaseConfiguration.class)
.withPropertyValues("management.endpoint.liquibase.enabled:false")
.run((context) -> {
this.contextRunner.withUserConfiguration(DataSourceClosingLiquibaseConfiguration.class)
.withPropertyValues("management.endpoint.liquibase.enabled:false").run((context) -> {
assertThat(context).doesNotHaveBean(LiquibaseEndpoint.class);
DataSourceClosingSpringLiquibase bean = context
.getBean(DataSourceClosingSpringLiquibase.class);
assertThat(bean).hasFieldOrPropertyWithValue(
"closeDataSourceOnceMigrated", true);
DataSourceClosingSpringLiquibase bean = context.getBean(DataSourceClosingSpringLiquibase.class);
assertThat(bean).hasFieldOrPropertyWithValue("closeDataSourceOnceMigrated", true);
});
}
@@ -101,11 +92,10 @@ public class LiquibaseEndpointAutoConfigurationTests {
private boolean propertiesSet = false;
@Override
public void setCloseDataSourceOnceMigrated(
boolean closeDataSourceOnceMigrated) {
public void setCloseDataSourceOnceMigrated(boolean closeDataSourceOnceMigrated) {
if (this.propertiesSet) {
throw new IllegalStateException("setCloseDataSourceOnceMigrated "
+ "invoked after afterPropertiesSet");
throw new IllegalStateException(
"setCloseDataSourceOnceMigrated " + "invoked after afterPropertiesSet");
}
super.setCloseDataSourceOnceMigrated(closeDataSourceOnceMigrated);
}

View File

@@ -49,48 +49,40 @@ public class LogFileWebEndpointAutoConfigurationTests {
@Test
public void logFileWebEndpointIsAutoConfiguredWhenLoggingFileIsSet() {
this.contextRunner.withPropertyValues("logging.file:test.log").run(
(context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
this.contextRunner.withPropertyValues("logging.file:test.log")
.run((context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
}
@Test
public void logFileWebEndpointIsAutoConfiguredWhenLoggingPathIsSet() {
this.contextRunner.withPropertyValues("logging.path:test/logs").run(
(context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
this.contextRunner.withPropertyValues("logging.path:test/logs")
.run((context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
}
@Test
public void logFileWebEndpointIsAutoConfiguredWhenExternalFileIsSet() {
this.contextRunner
.withPropertyValues(
"management.endpoint.logfile.external-file:external.log")
.run((context) -> assertThat(context)
.hasSingleBean(LogFileWebEndpoint.class));
this.contextRunner.withPropertyValues("management.endpoint.logfile.external-file:external.log")
.run((context) -> assertThat(context).hasSingleBean(LogFileWebEndpoint.class));
}
@Test
public void logFileWebEndpointCanBeDisabled() {
this.contextRunner
.withPropertyValues("logging.file:test.log",
"management.endpoint.logfile.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(LogFileWebEndpoint.class));
this.contextRunner.withPropertyValues("logging.file:test.log", "management.endpoint.logfile.enabled:false")
.run((context) -> assertThat(context).doesNotHaveBean(LogFileWebEndpoint.class));
}
@Test
public void logFileWebEndpointUsesConfiguredExternalFile() throws IOException {
File file = this.temp.newFile("logfile");
FileCopyUtils.copy("--TEST--".getBytes(), file);
this.contextRunner.withPropertyValues(
"management.endpoint.logfile.external-file:" + file.getAbsolutePath())
this.contextRunner.withPropertyValues("management.endpoint.logfile.external-file:" + file.getAbsolutePath())
.run((context) -> {
assertThat(context).hasSingleBean(LogFileWebEndpoint.class);
LogFileWebEndpoint endpoint = context
.getBean(LogFileWebEndpoint.class);
LogFileWebEndpoint endpoint = context.getBean(LogFileWebEndpoint.class);
Resource resource = endpoint.logFile();
assertThat(resource).isNotNull();
assertThat(StreamUtils.copyToString(resource.getInputStream(),
StandardCharsets.UTF_8)).isEqualTo("--TEST--");
assertThat(StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8))
.isEqualTo("--TEST--");
});
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,30 +36,24 @@ import static org.mockito.Mockito.mock;
public class LoggersEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(LoggersEndpointAutoConfiguration.class))
.withConfiguration(AutoConfigurations.of(LoggersEndpointAutoConfiguration.class))
.withUserConfiguration(LoggingConfiguration.class);
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(LoggersEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(LoggersEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner.withPropertyValues("management.endpoint.loggers.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(LoggersEndpoint.class));
.run((context) -> assertThat(context).doesNotHaveBean(LoggersEndpoint.class));
}
@Test
public void runWithNoneLoggingSystemShouldNotHaveEndpointBean() {
this.contextRunner
.withSystemProperties(
"org.springframework.boot.logging.LoggingSystem=none")
.run((context) -> assertThat(context)
.doesNotHaveBean(LoggersEndpoint.class));
this.contextRunner.withSystemProperties("org.springframework.boot.logging.LoggingSystem=none")
.run((context) -> assertThat(context).doesNotHaveBean(LoggersEndpoint.class));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,22 +36,19 @@ public class MailHealthIndicatorAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MailSenderAutoConfiguration.class,
MailHealthIndicatorAutoConfiguration.class,
HealthIndicatorAutoConfiguration.class))
MailHealthIndicatorAutoConfiguration.class, HealthIndicatorAutoConfiguration.class))
.withPropertyValues("spring.mail.host:smtp.example.com");
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(MailHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(MailHealthIndicator.class)
.doesNotHaveBean(ApplicationHealthIndicator.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner.withPropertyValues("management.health.mail.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(MailHealthIndicator.class)
.run((context) -> assertThat(context).doesNotHaveBean(MailHealthIndicator.class)
.hasSingleBean(ApplicationHealthIndicator.class));
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -36,16 +36,13 @@ public class HeapDumpWebEndpointAutoConfigurationTests {
@Test
public void runShouldCreateIndicator() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(HeapDumpWebEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(HeapDumpWebEndpoint.class));
}
@Test
public void runWhenDisabledShouldNotCreateIndicator() {
this.contextRunner
.withPropertyValues("management.endpoint.heapdump.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(HeapDumpWebEndpoint.class));
this.contextRunner.withPropertyValues("management.endpoint.heapdump.enabled:false")
.run((context) -> assertThat(context).doesNotHaveBean(HeapDumpWebEndpoint.class));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2017 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -32,21 +32,17 @@ import static org.assertj.core.api.Assertions.assertThat;
public class ThreadDumpEndpointAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(
AutoConfigurations.of(ThreadDumpEndpointAutoConfiguration.class));
.withConfiguration(AutoConfigurations.of(ThreadDumpEndpointAutoConfiguration.class));
@Test
public void runShouldHaveEndpointBean() {
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(ThreadDumpEndpoint.class));
this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ThreadDumpEndpoint.class));
}
@Test
public void runWhenEnabledPropertyIsFalseShouldNotHaveEndpointBean() {
this.contextRunner
.withPropertyValues("management.endpoint.threaddump.enabled:false")
.run((context) -> assertThat(context)
.doesNotHaveBean(ThreadDumpEndpoint.class));
this.contextRunner.withPropertyValues("management.endpoint.threaddump.enabled:false")
.run((context) -> assertThat(context).doesNotHaveBean(ThreadDumpEndpoint.class));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -42,55 +42,47 @@ public class CompositeMeterRegistryAutoConfigurationTests {
private static final String COMPOSITE_NAME = "compositeMeterRegistry";
private ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withUserConfiguration(BaseConfig.class).withConfiguration(
AutoConfigurations.of(CompositeMeterRegistryAutoConfiguration.class));
.withUserConfiguration(BaseConfig.class)
.withConfiguration(AutoConfigurations.of(CompositeMeterRegistryAutoConfiguration.class));
@Test
public void registerWhenHasNoMeterRegistryShouldRegisterEmptyNoOpComposite() {
this.contextRunner.withUserConfiguration(NoMeterRegistryConfig.class)
.run((context) -> {
assertThat(context).hasSingleBean(MeterRegistry.class);
CompositeMeterRegistry registry = context.getBean("noOpMeterRegistry",
CompositeMeterRegistry.class);
assertThat(registry.getRegistries()).isEmpty();
});
this.contextRunner.withUserConfiguration(NoMeterRegistryConfig.class).run((context) -> {
assertThat(context).hasSingleBean(MeterRegistry.class);
CompositeMeterRegistry registry = context.getBean("noOpMeterRegistry", CompositeMeterRegistry.class);
assertThat(registry.getRegistries()).isEmpty();
});
}
@Test
public void registerWhenHasSingleMeterRegistryShouldDoNothing() {
this.contextRunner.withUserConfiguration(SingleMeterRegistryConfig.class)
.run((context) -> {
assertThat(context).hasSingleBean(MeterRegistry.class);
MeterRegistry registry = context.getBean(MeterRegistry.class);
assertThat(registry).isInstanceOf(TestMeterRegistry.class);
});
this.contextRunner.withUserConfiguration(SingleMeterRegistryConfig.class).run((context) -> {
assertThat(context).hasSingleBean(MeterRegistry.class);
MeterRegistry registry = context.getBean(MeterRegistry.class);
assertThat(registry).isInstanceOf(TestMeterRegistry.class);
});
}
@Test
public void registerWhenHasMultipleMeterRegistriesShouldAddPrimaryComposite() {
this.contextRunner.withUserConfiguration(MultipleMeterRegistriesConfig.class)
.run((context) -> {
assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(3)
.containsKeys("meterRegistryOne", "meterRegistryTwo",
COMPOSITE_NAME);
MeterRegistry primary = context.getBean(MeterRegistry.class);
assertThat(primary).isInstanceOf(CompositeMeterRegistry.class);
assertThat(((CompositeMeterRegistry) primary).getRegistries())
.hasSize(2);
assertThat(primary.config().clock()).isNotNull();
});
this.contextRunner.withUserConfiguration(MultipleMeterRegistriesConfig.class).run((context) -> {
assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(3).containsKeys("meterRegistryOne",
"meterRegistryTwo", COMPOSITE_NAME);
MeterRegistry primary = context.getBean(MeterRegistry.class);
assertThat(primary).isInstanceOf(CompositeMeterRegistry.class);
assertThat(((CompositeMeterRegistry) primary).getRegistries()).hasSize(2);
assertThat(primary.config().clock()).isNotNull();
});
}
@Test
public void registerWhenHasMultipleRegistriesAndOneIsPrimaryShouldDoNothing() {
this.contextRunner
.withUserConfiguration(MultipleMeterRegistriesWithOnePrimaryConfig.class)
.run((context) -> {
assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(2)
.containsKeys("meterRegistryOne", "meterRegistryTwo");
MeterRegistry primary = context.getBean(MeterRegistry.class);
assertThat(primary).isInstanceOf(TestMeterRegistry.class);
});
this.contextRunner.withUserConfiguration(MultipleMeterRegistriesWithOnePrimaryConfig.class).run((context) -> {
assertThat(context.getBeansOfType(MeterRegistry.class)).hasSize(2).containsKeys("meterRegistryOne",
"meterRegistryTwo");
MeterRegistry primary = context.getBean(MeterRegistry.class);
assertThat(primary).isInstanceOf(TestMeterRegistry.class);
});
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -38,70 +38,55 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class JvmMetricsAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.with(MetricsRun.simple())
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple())
.withConfiguration(AutoConfigurations.of(JvmMetricsAutoConfiguration.class));
@Test
public void autoConfiguresJvmMetrics() {
this.contextRunner.run((context) -> assertThat(context)
.hasSingleBean(JvmGcMetrics.class).hasSingleBean(JvmMemoryMetrics.class)
.hasSingleBean(JvmThreadMetrics.class)
.hasSingleBean(ClassLoaderMetrics.class));
this.contextRunner.run(
(context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class).hasSingleBean(JvmMemoryMetrics.class)
.hasSingleBean(JvmThreadMetrics.class).hasSingleBean(ClassLoaderMetrics.class));
}
@Test
@Deprecated
public void allowsJvmMetricsToBeDisabled() {
this.contextRunner
.withPropertyValues("management.metrics.binders.jvm.enabled=false")
this.contextRunner.withPropertyValues("management.metrics.binders.jvm.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean(JvmGcMetrics.class)
.doesNotHaveBean(JvmMemoryMetrics.class)
.doesNotHaveBean(JvmThreadMetrics.class)
.doesNotHaveBean(JvmMemoryMetrics.class).doesNotHaveBean(JvmThreadMetrics.class)
.doesNotHaveBean(ClassLoaderMetrics.class));
}
@Test
public void allowsCustomJvmGcMetricsToBeUsed() {
this.contextRunner.withUserConfiguration(CustomJvmGcMetricsConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class)
.hasBean("customJvmGcMetrics")
.hasSingleBean(JvmMemoryMetrics.class)
.hasSingleBean(JvmThreadMetrics.class)
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class).hasBean("customJvmGcMetrics")
.hasSingleBean(JvmMemoryMetrics.class).hasSingleBean(JvmThreadMetrics.class)
.hasSingleBean(ClassLoaderMetrics.class));
}
@Test
public void allowsCustomJvmMemoryMetricsToBeUsed() {
this.contextRunner
.withUserConfiguration(CustomJvmMemoryMetricsConfiguration.class)
this.contextRunner.withUserConfiguration(CustomJvmMemoryMetricsConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class)
.hasSingleBean(JvmMemoryMetrics.class)
.hasBean("customJvmMemoryMetrics")
.hasSingleBean(JvmThreadMetrics.class)
.hasSingleBean(ClassLoaderMetrics.class));
.hasSingleBean(JvmMemoryMetrics.class).hasBean("customJvmMemoryMetrics")
.hasSingleBean(JvmThreadMetrics.class).hasSingleBean(ClassLoaderMetrics.class));
}
@Test
public void allowsCustomJvmThreadMetricsToBeUsed() {
this.contextRunner
.withUserConfiguration(CustomJvmThreadMetricsConfiguration.class)
this.contextRunner.withUserConfiguration(CustomJvmThreadMetricsConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class)
.hasSingleBean(JvmMemoryMetrics.class)
.hasSingleBean(JvmThreadMetrics.class)
.hasSingleBean(ClassLoaderMetrics.class)
.hasBean("customJvmThreadMetrics"));
.hasSingleBean(JvmMemoryMetrics.class).hasSingleBean(JvmThreadMetrics.class)
.hasSingleBean(ClassLoaderMetrics.class).hasBean("customJvmThreadMetrics"));
}
@Test
public void allowsCustomClassLoaderMetricsToBeUsed() {
this.contextRunner
.withUserConfiguration(CustomClassLoaderMetricsConfiguration.class)
this.contextRunner.withUserConfiguration(CustomClassLoaderMetricsConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(JvmGcMetrics.class)
.hasSingleBean(JvmMemoryMetrics.class)
.hasSingleBean(JvmThreadMetrics.class)
.hasSingleBean(ClassLoaderMetrics.class)
.hasBean("customClassLoaderMetrics"));
.hasSingleBean(JvmMemoryMetrics.class).hasSingleBean(JvmThreadMetrics.class)
.hasSingleBean(ClassLoaderMetrics.class).hasBean("customClassLoaderMetrics"));
}
@Configuration

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* Copyright 2012-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,31 +35,25 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class KafkaMetricsAutoConfigurationTests {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.with(MetricsRun.simple()).withConfiguration(
AutoConfigurations.of(KafkaMetricsAutoConfiguration.class));
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner().with(MetricsRun.simple())
.withConfiguration(AutoConfigurations.of(KafkaMetricsAutoConfiguration.class));
@Test
public void whenThereIsNoMBeanServerAutoConfigurationBacksOff() {
this.contextRunner.run((context) -> assertThat(context)
.doesNotHaveBean(KafkaConsumerMetrics.class));
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(KafkaConsumerMetrics.class));
}
@Test
public void whenThereIsAnMBeanServerKafkaConsumerMetricsIsConfigured() {
this.contextRunner
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class))
.run((context) -> assertThat(context)
.hasSingleBean(KafkaConsumerMetrics.class));
this.contextRunner.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class))
.run((context) -> assertThat(context).hasSingleBean(KafkaConsumerMetrics.class));
}
@Test
public void allowsCustomKafkaConsumerMetricsToBeUsed() {
this.contextRunner
.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class))
this.contextRunner.withConfiguration(AutoConfigurations.of(JmxAutoConfiguration.class))
.withUserConfiguration(CustomKafkaConsumerMetricsConfiguration.class)
.run((context) -> assertThat(context)
.hasSingleBean(KafkaConsumerMetrics.class)
.run((context) -> assertThat(context).hasSingleBean(KafkaConsumerMetrics.class)
.hasBean("customKafkaConsumerMetrics"));
}

Some files were not shown because too many files have changed in this diff Show More