Browse Source

Fix hystrix command keys in tests to be unique

pull/6/head
Dave Syer 7 years ago
parent
commit
7672ee3666
  1. 8
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/AdhocTestSuite.java
  2. 466
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/RibbonCommandCauseFallbackPropagationTest.java
  3. 67
      spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/RibbonCommandHystrixThreadPoolKeyTests.java

8
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/AdhocTestSuite.java

@ -21,8 +21,8 @@ import org.junit.runner.RunWith; @@ -21,8 +21,8 @@ import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import org.springframework.cloud.netflix.zuul.FormZuulServletProxyApplicationTests;
import org.springframework.cloud.netflix.zuul.filters.route.LazyLoadOfZuulConfigurationTests;
import org.springframework.cloud.netflix.zuul.filters.route.support.RibbonCommandCauseFallbackPropagationTest;
import org.springframework.cloud.netflix.zuul.filters.route.support.RibbonCommandHystrixThreadPoolKeyTests;
/**
* A test suite for probing weird ordering problems in the tests.
@ -30,8 +30,8 @@ import org.springframework.cloud.netflix.zuul.filters.route.LazyLoadOfZuulConfig @@ -30,8 +30,8 @@ import org.springframework.cloud.netflix.zuul.filters.route.LazyLoadOfZuulConfig
* @author Dave Syer
*/
@RunWith(Suite.class)
@SuiteClasses({ FormZuulServletProxyApplicationTests.class,
LazyLoadOfZuulConfigurationTests.class })
@SuiteClasses({ RibbonCommandHystrixThreadPoolKeyTests.class,
RibbonCommandCauseFallbackPropagationTest.class })
@Ignore
public class AdhocTestSuite {

466
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/RibbonCommandCauseFallbackPropagationTest.java

@ -17,6 +17,11 @@ @@ -17,6 +17,11 @@
package org.springframework.cloud.netflix.zuul.filters.route.support;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import com.netflix.client.AbstractLoadBalancerAwareClient;
import com.netflix.client.ClientException;
import com.netflix.client.ClientRequest;
@ -26,18 +31,16 @@ import com.netflix.client.config.IClientConfig; @@ -26,18 +31,16 @@ import com.netflix.client.config.IClientConfig;
import com.netflix.client.http.HttpResponse;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.exception.HystrixTimeoutException;
import org.junit.Test;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.cloud.netflix.zuul.filters.route.ZuulFallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.assertj.core.api.Assertions.assertThat;
/**
@ -45,220 +48,241 @@ import static org.assertj.core.api.Assertions.assertThat; @@ -45,220 +48,241 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class RibbonCommandCauseFallbackPropagationTest {
@Test
public void providerIsCalledInCaseOfException() throws Exception {
TestZuulFallbackProviderWithoutCause provider = new TestZuulFallbackProviderWithoutCause(HttpStatus.INTERNAL_SERVER_ERROR);
RuntimeException exception = new RuntimeException("Failed!");
TestRibbonCommand testCommand = new TestRibbonCommand(new TestClient(exception), provider);
ClientHttpResponse response = testCommand.execute();
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
}
@Test
public void causeIsProvidedForNewInterface() throws Exception {
TestFallbackProvider provider = TestFallbackProvider.withResponse(HttpStatus.NOT_FOUND);
RuntimeException exception = new RuntimeException("Failed!");
TestRibbonCommand testCommand = new TestRibbonCommand(new TestClient(exception), provider);
ClientHttpResponse response = testCommand.execute();
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
Throwable cause = provider.getCause();
assertThat(cause.getClass()).isEqualTo(exception.getClass());
assertThat(cause.getMessage()).isEqualTo(exception.getMessage());
}
@Test
public void executionExceptionIsUsedInsteadWhenFailedExceptionIsNull() throws Exception {
TestFallbackProvider provider = TestFallbackProvider.withResponse(HttpStatus.BAD_GATEWAY);
final RuntimeException exception = new RuntimeException("Failed!");
TestRibbonCommand testCommand = new TestRibbonCommand(new TestClient(exception), provider) {
@Override
public Throwable getFailedExecutionException() {
return null;
}
@Override
public Throwable getExecutionException() {
return exception;
}
};
ClientHttpResponse response = testCommand.execute();
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_GATEWAY);
}
@Test
public void timeoutExceptionIsPropagated() throws Exception {
TestFallbackProvider provider = TestFallbackProvider.withResponse(HttpStatus.CONFLICT);
RuntimeException exception = new RuntimeException("Failed!");
TestRibbonCommand testCommand = new TestRibbonCommand(new TestClient(exception), provider, 1) {
@Override
protected ClientRequest createRequest() throws Exception {
Thread.sleep(5);
return super.createRequest();
}
};
ClientHttpResponse response = testCommand.execute();
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CONFLICT);
assertThat(provider.getCause()).isNotNull();
assertThat(provider.getCause().getClass()).isEqualTo(HystrixTimeoutException.class);
}
public static class TestRibbonCommand
extends AbstractRibbonCommand<AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse>, ClientRequest, HttpResponse> {
public TestRibbonCommand(AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse> client, ZuulFallbackProvider fallbackProvider) {
this(client, new ZuulProperties(), fallbackProvider);
}
public TestRibbonCommand(AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse> client,
ZuulProperties zuulProperties,
ZuulFallbackProvider fallbackProvider) {
super("testCommand", client, null, zuulProperties, fallbackProvider);
}
public TestRibbonCommand(AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse> client,
ZuulFallbackProvider fallbackProvider,
int timeout) {
// different name is used because of properties caching
super(getSetter("testCommand2", new ZuulProperties()).andCommandPropertiesDefaults(defauts(timeout)),
client, null, fallbackProvider, null);
}
private static HystrixCommandProperties.Setter defauts(final int timeout) {
return HystrixCommandProperties.Setter().withExecutionTimeoutEnabled(true)
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
.withExecutionTimeoutInMilliseconds(timeout);
}
@Override
protected ClientRequest createRequest() throws Exception {
return null;
}
}
public static class TestClient extends AbstractLoadBalancerAwareClient {
private final RuntimeException exception;
public TestClient(RuntimeException exception) {
super(null);
this.exception = exception;
}
@Override
public IResponse executeWithLoadBalancer(final ClientRequest request, final IClientConfig requestConfig) throws ClientException {
throw exception;
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(final ClientRequest clientRequest, final IClientConfig iClientConfig) {
return null;
}
@Override
public IResponse execute(final ClientRequest clientRequest, final IClientConfig iClientConfig) throws Exception {
return null;
}
}
public static class TestFallbackProvider implements FallbackProvider {
private final ClientHttpResponse response;
private Throwable cause;
public TestFallbackProvider(final ClientHttpResponse response) {
this.response = response;
}
@Override
public ClientHttpResponse fallbackResponse(final Throwable cause) {
this.cause = cause;
return response;
}
@Override
public String getRoute() {
return "test-route";
}
@Override
public ClientHttpResponse fallbackResponse() {
throw new UnsupportedOperationException("fallback without cause is not supported");
}
public Throwable getCause() {
return cause;
}
public static TestFallbackProvider withResponse(final HttpStatus status) {
return new TestFallbackProvider(getClientHttpResponse(status));
}
}
public static class TestZuulFallbackProviderWithoutCause implements ZuulFallbackProvider {
private final ClientHttpResponse response;
public TestZuulFallbackProviderWithoutCause(final ClientHttpResponse response) {
this.response = response;
}
public TestZuulFallbackProviderWithoutCause(final HttpStatus status) {
this(getClientHttpResponse(status));
}
@Override
public String getRoute() {
return "test-route";
}
@Override
public ClientHttpResponse fallbackResponse() {
return response;
}
}
private static ClientHttpResponse getClientHttpResponse(final HttpStatus status) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return status;
}
@Override
public int getRawStatusCode() throws IOException {
return getStatusCode().value();
}
@Override
public String getStatusText() throws IOException {
return getStatusCode().getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("test".getBytes());
}
@Override
public HttpHeaders getHeaders() {
return new HttpHeaders();
}
};
}
@Test
public void providerIsCalledInCaseOfException() throws Exception {
TestZuulFallbackProviderWithoutCause provider = new TestZuulFallbackProviderWithoutCause(
HttpStatus.INTERNAL_SERVER_ERROR);
RuntimeException exception = new RuntimeException("Failed!");
TestRibbonCommand testCommand = new TestRibbonCommand(new TestClient(exception),
provider);
ClientHttpResponse response = testCommand.execute();
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
}
@Test
public void causeIsProvidedForNewInterface() throws Exception {
TestFallbackProvider provider = TestFallbackProvider
.withResponse(HttpStatus.NOT_FOUND);
RuntimeException exception = new RuntimeException("Failed!");
TestRibbonCommand testCommand = new TestRibbonCommand(new TestClient(exception),
provider);
ClientHttpResponse response = testCommand.execute();
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
Throwable cause = provider.getCause();
assertThat(cause.getClass()).isEqualTo(exception.getClass());
assertThat(cause.getMessage()).isEqualTo(exception.getMessage());
}
@Test
public void executionExceptionIsUsedInsteadWhenFailedExceptionIsNull()
throws Exception {
TestFallbackProvider provider = TestFallbackProvider
.withResponse(HttpStatus.BAD_GATEWAY);
final RuntimeException exception = new RuntimeException("Failed!");
TestRibbonCommand testCommand = new TestRibbonCommand(new TestClient(exception),
provider) {
@Override
public Throwable getFailedExecutionException() {
return null;
}
@Override
public Throwable getExecutionException() {
return exception;
}
};
ClientHttpResponse response = testCommand.execute();
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_GATEWAY);
}
@Test
public void timeoutExceptionIsPropagated() throws Exception {
TestFallbackProvider provider = TestFallbackProvider
.withResponse(HttpStatus.CONFLICT);
RuntimeException exception = new RuntimeException("Failed!");
TestRibbonCommand testCommand = new TestRibbonCommand(new TestClient(exception),
provider, 1) {
@Override
protected ClientRequest createRequest() throws Exception {
Thread.sleep(5);
return super.createRequest();
}
};
ClientHttpResponse response = testCommand.execute();
assertThat(response).isNotNull();
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.CONFLICT);
assertThat(provider.getCause()).isNotNull();
assertThat(provider.getCause().getClass())
.isEqualTo(HystrixTimeoutException.class);
}
public static class TestRibbonCommand extends
AbstractRibbonCommand<AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse>, ClientRequest, HttpResponse> {
public TestRibbonCommand(
AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse> client,
ZuulFallbackProvider fallbackProvider) {
this(client, new ZuulProperties(), fallbackProvider);
}
public TestRibbonCommand(
AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse> client,
ZuulProperties zuulProperties, ZuulFallbackProvider fallbackProvider) {
super("testCommand" + UUID.randomUUID(), client, null, zuulProperties,
fallbackProvider);
}
public TestRibbonCommand(
AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse> client,
ZuulFallbackProvider fallbackProvider, int timeout) {
// different name is used because of properties caching
super(getSetter("testCommand" + UUID.randomUUID(), new ZuulProperties())
.andCommandPropertiesDefaults(defauts(timeout)), client, null,
fallbackProvider, null);
}
private static HystrixCommandProperties.Setter defauts(final int timeout) {
return HystrixCommandProperties.Setter().withExecutionTimeoutEnabled(true)
.withExecutionIsolationStrategy(
HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
.withExecutionTimeoutInMilliseconds(timeout);
}
@Override
protected ClientRequest createRequest() throws Exception {
return null;
}
}
@SuppressWarnings("rawtypes")
public static class TestClient extends AbstractLoadBalancerAwareClient {
private final RuntimeException exception;
public TestClient(RuntimeException exception) {
super(null);
this.exception = exception;
}
@Override
public IResponse executeWithLoadBalancer(final ClientRequest request,
final IClientConfig requestConfig) throws ClientException {
throw exception;
}
@Override
public RequestSpecificRetryHandler getRequestSpecificRetryHandler(
final ClientRequest clientRequest, final IClientConfig iClientConfig) {
return null;
}
@Override
public IResponse execute(final ClientRequest clientRequest,
final IClientConfig iClientConfig) throws Exception {
return null;
}
}
public static class TestFallbackProvider implements FallbackProvider {
private final ClientHttpResponse response;
private Throwable cause;
public TestFallbackProvider(final ClientHttpResponse response) {
this.response = response;
}
@Override
public ClientHttpResponse fallbackResponse(final Throwable cause) {
this.cause = cause;
return response;
}
@Override
public String getRoute() {
return "test-route";
}
@Override
public ClientHttpResponse fallbackResponse() {
throw new UnsupportedOperationException(
"fallback without cause is not supported");
}
public Throwable getCause() {
return cause;
}
public static TestFallbackProvider withResponse(final HttpStatus status) {
return new TestFallbackProvider(getClientHttpResponse(status));
}
}
public static class TestZuulFallbackProviderWithoutCause
implements ZuulFallbackProvider {
private final ClientHttpResponse response;
public TestZuulFallbackProviderWithoutCause(final ClientHttpResponse response) {
this.response = response;
}
public TestZuulFallbackProviderWithoutCause(final HttpStatus status) {
this(getClientHttpResponse(status));
}
@Override
public String getRoute() {
return "test-route";
}
@Override
public ClientHttpResponse fallbackResponse() {
return response;
}
}
private static ClientHttpResponse getClientHttpResponse(final HttpStatus status) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return status;
}
@Override
public int getRawStatusCode() throws IOException {
return getStatusCode().value();
}
@Override
public String getStatusText() throws IOException {
return getStatusCode().getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream("test".getBytes());
}
@Override
public HttpHeaders getHeaders() {
return new HttpHeaders();
}
};
}
}

67
spring-cloud-netflix-core/src/test/java/org/springframework/cloud/netflix/zuul/filters/route/support/RibbonCommandHystrixThreadPoolKeyTests.java

@ -20,8 +20,12 @@ import com.netflix.client.AbstractLoadBalancerAwareClient; @@ -20,8 +20,12 @@ import com.netflix.client.AbstractLoadBalancerAwareClient;
import com.netflix.client.ClientRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import static org.assertj.core.api.Assertions.assertThat;
@ -38,25 +42,38 @@ public class RibbonCommandHystrixThreadPoolKeyTests { @@ -38,25 +42,38 @@ public class RibbonCommandHystrixThreadPoolKeyTests {
zuulProperties = new ZuulProperties();
}
@After
public void tearDown() throws Exception {
HystrixPlugins.reset();
}
@Test
public void testDefaultHystrixThreadPoolKey() throws Exception {
zuulProperties.setRibbonIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
zuulProperties.setRibbonIsolationStrategy(
HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
TestRibbonCommand ribbonCommand1 = new TestRibbonCommand("testCommand1", zuulProperties);
TestRibbonCommand ribbonCommand2 = new TestRibbonCommand("testCommand2", zuulProperties);
TestRibbonCommand ribbonCommand1 = new TestRibbonCommand("testCommand1",
zuulProperties);
TestRibbonCommand ribbonCommand2 = new TestRibbonCommand("testCommand2",
zuulProperties);
// CommandGroupKey should be used as ThreadPoolKey as default.
assertThat(ribbonCommand1.getThreadPoolKey().name()).isEqualTo(ribbonCommand1.getCommandGroup().name());
assertThat(ribbonCommand2.getThreadPoolKey().name()).isEqualTo(ribbonCommand2.getCommandGroup().name());
assertThat(ribbonCommand1.getThreadPoolKey().name())
.isEqualTo(ribbonCommand1.getCommandGroup().name());
assertThat(ribbonCommand2.getThreadPoolKey().name())
.isEqualTo(ribbonCommand2.getCommandGroup().name());
}
@Test
public void testUseSeparateThreadPools() throws Exception {
zuulProperties.setRibbonIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
zuulProperties.setRibbonIsolationStrategy(
HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
zuulProperties.getThreadPool().setUseSeparateThreadPools(true);
TestRibbonCommand ribbonCommand1 = new TestRibbonCommand("testCommand1", zuulProperties);
TestRibbonCommand ribbonCommand2 = new TestRibbonCommand("testCommand2", zuulProperties);
TestRibbonCommand ribbonCommand1 = new TestRibbonCommand("testCommand1",
zuulProperties);
TestRibbonCommand ribbonCommand2 = new TestRibbonCommand("testCommand2",
zuulProperties);
assertThat(ribbonCommand1.getThreadPoolKey().name()).isEqualTo("testCommand1");
assertThat(ribbonCommand2.getThreadPoolKey().name()).isEqualTo("testCommand2");
@ -66,35 +83,45 @@ public class RibbonCommandHystrixThreadPoolKeyTests { @@ -66,35 +83,45 @@ public class RibbonCommandHystrixThreadPoolKeyTests {
public void testThreadPoolKeyPrefix() throws Exception {
final String prefix = "zuulgw-";
zuulProperties.setRibbonIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
zuulProperties.setRibbonIsolationStrategy(
HystrixCommandProperties.ExecutionIsolationStrategy.THREAD);
zuulProperties.getThreadPool().setUseSeparateThreadPools(true);
zuulProperties.getThreadPool().setThreadPoolKeyPrefix(prefix);
TestRibbonCommand ribbonCommand1 = new TestRibbonCommand("testCommand1", zuulProperties);
TestRibbonCommand ribbonCommand2 = new TestRibbonCommand("testCommand2", zuulProperties);
TestRibbonCommand ribbonCommand1 = new TestRibbonCommand("testCommand1",
zuulProperties);
TestRibbonCommand ribbonCommand2 = new TestRibbonCommand("testCommand2",
zuulProperties);
assertThat(ribbonCommand1.getThreadPoolKey().name()).isEqualTo(prefix + "testCommand1");
assertThat(ribbonCommand2.getThreadPoolKey().name()).isEqualTo(prefix + "testCommand2");
assertThat(ribbonCommand1.getThreadPoolKey().name())
.isEqualTo(prefix + "testCommand1");
assertThat(ribbonCommand2.getThreadPoolKey().name())
.isEqualTo(prefix + "testCommand2");
}
@Test
public void testNoSideEffectOnSemaphoreIsolation() throws Exception {
final String prefix = "zuulgw-";
zuulProperties.setRibbonIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE);
zuulProperties.setRibbonIsolationStrategy(
HystrixCommandProperties.ExecutionIsolationStrategy.SEMAPHORE);
zuulProperties.getThreadPool().setUseSeparateThreadPools(true);
zuulProperties.getThreadPool().setThreadPoolKeyPrefix(prefix);
TestRibbonCommand ribbonCommand1 = new TestRibbonCommand("testCommand1", zuulProperties);
TestRibbonCommand ribbonCommand2 = new TestRibbonCommand("testCommand2", zuulProperties);
TestRibbonCommand ribbonCommand1 = new TestRibbonCommand("testCommand1",
zuulProperties);
TestRibbonCommand ribbonCommand2 = new TestRibbonCommand("testCommand2",
zuulProperties);
// There should be no side effect on semaphore isolation
assertThat(ribbonCommand1.getThreadPoolKey().name()).isEqualTo(ribbonCommand1.getCommandGroup().name());
assertThat(ribbonCommand2.getThreadPoolKey().name()).isEqualTo(ribbonCommand2.getCommandGroup().name());
assertThat(ribbonCommand1.getThreadPoolKey().name())
.isEqualTo(ribbonCommand1.getCommandGroup().name());
assertThat(ribbonCommand2.getThreadPoolKey().name())
.isEqualTo(ribbonCommand2.getCommandGroup().name());
}
public static class TestRibbonCommand
extends AbstractRibbonCommand<AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse>, ClientRequest, HttpResponse> {
public static class TestRibbonCommand extends
AbstractRibbonCommand<AbstractLoadBalancerAwareClient<ClientRequest, HttpResponse>, ClientRequest, HttpResponse> {
public TestRibbonCommand(String commandKey, ZuulProperties zuulProperties) {
super(commandKey, null, null, zuulProperties);
}

Loading…
Cancel
Save