Updates WeightCalculatorWebFilter to be more testable.
Since Random can't be mocked in jdk17+, replace the settable Random with Supplier<Double>. Production should still use ThreadLoacalRandom unless the supplier is set.
This commit is contained in:
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -64,7 +65,7 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli
|
||||
|
||||
private final ConfigurationService configurationService;
|
||||
|
||||
private Random random = null;
|
||||
private Supplier<Double> randomSupplier = null;
|
||||
|
||||
private int order = WEIGHT_CALC_FILTER_ORDER;
|
||||
|
||||
@@ -98,8 +99,13 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void setRandom(Random random) {
|
||||
this.random = random;
|
||||
this.randomSupplier = random::nextDouble;
|
||||
}
|
||||
|
||||
public void setRandomSupplier(Supplier<Double> randomSupplier) {
|
||||
this.randomSupplier = randomSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -236,9 +242,13 @@ public class WeightCalculatorWebFilter implements WebFilter, Ordered, SmartAppli
|
||||
* Usually, multiple threads accessing the same random object will have some
|
||||
* performance problems, so we can use ThreadLocalRandom by default
|
||||
*/
|
||||
Random useRandom = this.random;
|
||||
useRandom = useRandom == null ? ThreadLocalRandom.current() : useRandom;
|
||||
double r = useRandom.nextDouble();
|
||||
double r;
|
||||
if (this.randomSupplier != null) {
|
||||
r = randomSupplier.get();
|
||||
}
|
||||
else {
|
||||
r = ThreadLocalRandom.current().nextDouble();
|
||||
}
|
||||
|
||||
List<Double> ranges = config.ranges;
|
||||
|
||||
|
||||
@@ -19,11 +19,9 @@ package org.springframework.cloud.gateway.filter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledForJreRange;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.cloud.gateway.event.PredicateArgsEvent;
|
||||
import org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter.GroupWeightConfig;
|
||||
@@ -95,20 +93,18 @@ public class WeightCalculatorWebFilterTests {
|
||||
return "route" + i;
|
||||
}
|
||||
|
||||
// TODO: modify implementation for testability on JDK17 for Spring 6
|
||||
@Test
|
||||
@DisabledForJreRange(min = JRE.JAVA_17)
|
||||
public void testChooseRouteWithRandom() {
|
||||
WeightCalculatorWebFilter filter = createFilter();
|
||||
filter.addWeightConfig(new WeightConfig("groupa", "route1", 1));
|
||||
filter.addWeightConfig(new WeightConfig("groupa", "route2", 3));
|
||||
filter.addWeightConfig(new WeightConfig("groupa", "route3", 6));
|
||||
|
||||
Random random = mock(Random.class);
|
||||
Supplier<Double> random = mock(Supplier.class);
|
||||
|
||||
when(random.nextDouble()).thenReturn(0.05).thenReturn(0.2).thenReturn(0.6);
|
||||
when(random.get()).thenReturn(0.05).thenReturn(0.2).thenReturn(0.6);
|
||||
|
||||
filter.setRandom(random);
|
||||
filter.setRandomSupplier(random);
|
||||
|
||||
MockServerWebExchange exchange = MockServerWebExchange
|
||||
.from(MockServerHttpRequest.get("http://localhost").build());
|
||||
|
||||
@@ -16,12 +16,10 @@
|
||||
|
||||
package org.springframework.cloud.gateway.handler.predicate;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledForJreRange;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -45,21 +43,20 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
|
||||
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||
@DirtiesContext
|
||||
@DisabledForJreRange(min = JRE.JAVA_17)
|
||||
public class WeightRoutePredicateFactoryIntegrationTests extends BaseWebClientTests {
|
||||
|
||||
@Autowired
|
||||
private WeightCalculatorWebFilter filter;
|
||||
|
||||
private static Random getRandom(double value) {
|
||||
Random random = mock(Random.class);
|
||||
when(random.nextDouble()).thenReturn(value);
|
||||
private static Supplier<Double> getRandom(double value) {
|
||||
Supplier<Double> random = mock(Supplier.class);
|
||||
when(random.get()).thenReturn(value);
|
||||
return random;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void highWeight() {
|
||||
filter.setRandom(getRandom(0.9));
|
||||
filter.setRandomSupplier(getRandom(0.9));
|
||||
|
||||
testClient.get().uri("/get").header(HttpHeaders.HOST, "www.weighthigh.org").exchange().expectStatus().isOk()
|
||||
.expectHeader().valueEquals(ROUTE_ID_HEADER, "weight_high_test");
|
||||
@@ -67,7 +64,7 @@ public class WeightRoutePredicateFactoryIntegrationTests extends BaseWebClientTe
|
||||
|
||||
@Test
|
||||
public void lowWeight() {
|
||||
filter.setRandom(getRandom(0.1));
|
||||
filter.setRandomSupplier(getRandom(0.1));
|
||||
|
||||
testClient.get().uri("/get").header(HttpHeaders.HOST, "www.weightlow.org").exchange().expectStatus().isOk()
|
||||
.expectHeader().valueEquals(ROUTE_ID_HEADER, "weight_low_test");
|
||||
@@ -89,9 +86,9 @@ public class WeightRoutePredicateFactoryIntegrationTests extends BaseWebClientTe
|
||||
private String uri;
|
||||
|
||||
public TestConfig(WeightCalculatorWebFilter filter) {
|
||||
Random random = getRandom(0.4);
|
||||
Supplier<Double> random = getRandom(0.4);
|
||||
|
||||
filter.setRandom(random);
|
||||
filter.setRandomSupplier(random);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -16,11 +16,9 @@
|
||||
|
||||
package org.springframework.cloud.gateway.handler.predicate;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledForJreRange;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootConfiguration;
|
||||
@@ -40,21 +38,20 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
|
||||
@SpringBootTest(webEnvironment = RANDOM_PORT)
|
||||
@ActiveProfiles("weights-404")
|
||||
@DirtiesContext
|
||||
@DisabledForJreRange(min = JRE.JAVA_17)
|
||||
class WeightRoutePredicateFactoryYaml404Tests extends BaseWebClientTests {
|
||||
|
||||
@Autowired
|
||||
private WeightCalculatorWebFilter filter;
|
||||
|
||||
private static Random getRandom(double value) {
|
||||
Random random = mock(Random.class);
|
||||
when(random.nextDouble()).thenReturn(value);
|
||||
private static Supplier<Double> getRandom(double value) {
|
||||
Supplier<Double> random = mock(Supplier.class);
|
||||
when(random.get()).thenReturn(value);
|
||||
return random;
|
||||
}
|
||||
|
||||
@Test
|
||||
void weightsFromYamlNot404() {
|
||||
filter.setRandom(getRandom(0.5));
|
||||
filter.setRandomSupplier(getRandom(0.5));
|
||||
|
||||
testClient.get().uri("/get").header(HttpHeaders.HOST, "www.weight4041.org").exchange().expectStatus().isOk()
|
||||
.expectHeader().valueEquals(ROUTE_ID_HEADER, "weight_first_404_test_1");
|
||||
@@ -66,9 +63,9 @@ class WeightRoutePredicateFactoryYaml404Tests extends BaseWebClientTests {
|
||||
static class TestConfig {
|
||||
|
||||
TestConfig(WeightCalculatorWebFilter filter) {
|
||||
Random random = getRandom(0.4);
|
||||
Supplier<Double> random = getRandom(0.4);
|
||||
|
||||
filter.setRandom(random);
|
||||
filter.setRandomSupplier(random);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user