Skip to content

Commit 56eda74

Browse files
committed
Building response with log normal delays
1 parent 2f16dbf commit 56eda74

File tree

6 files changed

+184
-56
lines changed

6 files changed

+184
-56
lines changed

docs/pages/corefunctionality/dsl.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,22 @@ Per-request delay can be set as follows:
5252

5353
.. code-block:: java
5454
55+
// Fixed delay
5556
SimulationSource.dsl(
5657
service("www.not-so-slow-service.com")
5758
.get("/api/bookings")
5859
.willReturn(success().withFixedDelay(1, TimeUnit.SECONDS))
5960
)
6061
)
6162
63+
// Log Normal random delay
64+
SimulationSource.dsl(
65+
service("www.not-so-slow-service.com")
66+
.get("/api/bookings")
67+
.willReturn(success().withLogNormalDelay(2, 1, TimeUnit.SECONDS))
68+
)
69+
)
70+
6271
6372
Request/response body conversion
6473
--------------------------------
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package io.specto.hoverfly.junit.core.model;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
7+
@JsonIgnoreProperties(ignoreUnknown = true)
8+
public class LogNormalDelay {
9+
10+
private final int min;
11+
private final int max;
12+
private final int mean;
13+
private final int median;
14+
15+
@JsonCreator
16+
public LogNormalDelay(
17+
@JsonProperty("min") int min,
18+
@JsonProperty("max") int max,
19+
@JsonProperty("mean") int mean,
20+
@JsonProperty("median") int median) {
21+
this.min = min;
22+
this.max = max;
23+
this.mean = mean;
24+
this.median = median;
25+
}
26+
27+
public int getMin() {
28+
return min;
29+
}
30+
31+
public int getMax() {
32+
return max;
33+
}
34+
35+
public int getMean() {
36+
return mean;
37+
}
38+
39+
public int getMedian() {
40+
return median;
41+
}
42+
}

src/main/java/io/specto/hoverfly/junit/core/model/Response.java

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.apache.commons.lang3.builder.EqualsBuilder;
2020
import org.apache.commons.lang3.builder.HashCodeBuilder;
2121
import org.apache.commons.lang3.builder.ToStringBuilder;
22+
import sun.rmi.runtime.Log;
2223

2324
import java.util.List;
2425
import java.util.Map;
@@ -34,18 +35,19 @@ public class Response {
3435
private final Map<String, String> transitionsState;
3536
private final List<String> removesState;
3637
private final Integer fixedDelay;
37-
38+
private final LogNormalDelay logNormalDelay;
3839

3940
@JsonCreator
4041
public Response(
41-
@JsonProperty("status") Integer status,
42-
@JsonProperty("body") String body,
43-
@JsonProperty("encodedBody") boolean encodedBody,
44-
@JsonProperty("templated") boolean templated,
45-
@JsonProperty("headers") Map<String, List<String>> headers,
46-
@JsonProperty("transitionsState") Map<String, String> transitionsState,
47-
@JsonProperty("removesState") List<String> removesState,
48-
@JsonProperty("fixedDelay") Integer fixedDelay) {
42+
@JsonProperty("status") Integer status,
43+
@JsonProperty("body") String body,
44+
@JsonProperty("encodedBody") boolean encodedBody,
45+
@JsonProperty("templated") boolean templated,
46+
@JsonProperty("headers") Map<String, List<String>> headers,
47+
@JsonProperty("transitionsState") Map<String, String> transitionsState,
48+
@JsonProperty("removesState") List<String> removesState,
49+
@JsonProperty("fixedDelay") Integer fixedDelay,
50+
@JsonProperty("logNormalDelay") LogNormalDelay logNormalDelay) {
4951
this.status = status;
5052
this.body = body;
5153
this.encodedBody = encodedBody;
@@ -54,6 +56,7 @@ public Response(
5456
this.transitionsState = transitionsState;
5557
this.removesState = removesState;
5658
this.fixedDelay = fixedDelay;
59+
this.logNormalDelay = logNormalDelay;
5760
}
5861

5962
public Integer getStatus() {
@@ -89,6 +92,10 @@ public Integer getFixedDelay() {
8992
return fixedDelay;
9093
}
9194

95+
public LogNormalDelay getLogNormalDelay() {
96+
return logNormalDelay;
97+
}
98+
9299
static class Builder {
93100
private Integer status;
94101
private String body;
@@ -98,6 +105,7 @@ static class Builder {
98105
private Map<String, String> transitionsState;
99106
private List<String> removesState;
100107
private Integer fixedDelay;
108+
private LogNormalDelay logNormalDelay;
101109

102110
Builder status(int status) {
103111
this.status = status;
@@ -139,8 +147,13 @@ Builder fixedDelay(int fixedDelay) {
139147
return this;
140148
}
141149

150+
Builder logNormalDelay(int min, int max, int mean, int median) {
151+
this.logNormalDelay = new LogNormalDelay(min, max, mean, median);
152+
return this;
153+
}
154+
142155
Response build() {
143-
return new Response(status, body, encodedBody, templated, headers, transitionsState, removesState, fixedDelay);
156+
return new Response(status, body, encodedBody, templated, headers, transitionsState, removesState, fixedDelay, logNormalDelay);
144157
}
145158
}
146159

src/main/java/io/specto/hoverfly/junit/dsl/ResponseBuilder.java

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313
package io.specto.hoverfly.junit.dsl;
1414

15+
import io.specto.hoverfly.junit.core.model.LogNormalDelay;
1516
import io.specto.hoverfly.junit.core.model.Response;
1617

1718
import java.util.ArrayList;
@@ -37,7 +38,7 @@ public class ResponseBuilder {
3738
private final List<String> removesState = new ArrayList<>();
3839

3940
private int fixedDelay;
40-
private TimeUnit fixedDelayTimeUnit;
41+
private LogNormalDelay logNormalDelay;
4142

4243
// Deprecated: For global delay settings
4344
private int delay;
@@ -112,8 +113,7 @@ public ResponseBuilder andRemoveState(final String stateToRemove) {
112113
* @return the response
113114
*/
114115
Response build() {
115-
int fixedDelayInMillis = fixedDelayTimeUnit == null ? 0 : (int) fixedDelayTimeUnit.toMillis(fixedDelay);
116-
return new Response(status, body, false, templated, headers, transitionsState, removesState, fixedDelayInMillis);
116+
return new Response(status, body, false, templated, headers, transitionsState, removesState, fixedDelay, logNormalDelay);
117117
}
118118

119119
public ResponseBuilder body(final HttpBodyConverter httpBodyConverter) {
@@ -128,9 +128,53 @@ public ResponseBuilder disableTemplating() {
128128
return this;
129129
}
130130

131+
132+
/**
133+
* Set fixed delay for the request-response pair
134+
* @param delay amount of delay
135+
* @param delayTimeUnit time unit of delay (e.g. SECONDS)
136+
* @return the {@link ResponseBuilder for further customizations}
137+
*/
131138
public ResponseBuilder withFixedDelay(int delay, TimeUnit delayTimeUnit) {
132-
fixedDelay = delay;
133-
fixedDelayTimeUnit = delayTimeUnit;
139+
fixedDelay = (int) delayTimeUnit.toMillis(delay);
140+
return this;
141+
}
142+
143+
/**
144+
* Set Log Normal delay for the request-response pair. The delay value will be generated randomly based on the distribution
145+
* which is defined by 2 parameters μ and σ. We will compute these parameters from the mean and median of a server response time.
146+
* You can typically find these values in your monitoring of the production server.
147+
* @param mean mean value of the delays to simulate
148+
* @param median median value of the delays to simulate
149+
* @param delayTimeUnit time unit of delay (e.g. SECONDS)
150+
* @return the {@link ResponseBuilder for further customizations}
151+
*/
152+
public ResponseBuilder withLogNormalDelay(int mean, int median, TimeUnit delayTimeUnit) {
153+
logNormalDelay = new LogNormalDelay(
154+
0,
155+
0,
156+
(int) delayTimeUnit.toMillis(mean),
157+
(int) delayTimeUnit.toMillis(median));
158+
return this;
159+
}
160+
161+
/**
162+
* Set Log Normal delay for the request-response pair. The delay value will be generated randomly based on the distribution
163+
* which is defined by 2 parameters μ and σ. We will compute these parameters from the mean and median of a server response time.
164+
* You can typically find these values in your monitoring of the production server.
165+
* @param mean mean value of the delays to simulate
166+
* @param median median value of the delays to simulate
167+
* @param min lower bound of the delays
168+
* @param max upper bound of the delays
169+
* @param delayTimeUnit time unit of delay (e.g. SECONDS)
170+
* @return the {@link ResponseBuilder for further customizations}
171+
*/
172+
public ResponseBuilder withLogNormalDelay(int mean, int median, int min, int max, TimeUnit delayTimeUnit) {
173+
logNormalDelay = new LogNormalDelay(
174+
(int) delayTimeUnit.toMillis(min),
175+
(int) delayTimeUnit.toMillis(max),
176+
(int) delayTimeUnit.toMillis(mean),
177+
(int) delayTimeUnit.toMillis(median));
134178
return this;
135179
}
136180

src/test/java/io/specto/hoverfly/junit/dsl/StubServiceBuilderTest.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
import com.fasterxml.jackson.core.JsonProcessingException;
44
import com.fasterxml.jackson.databind.ObjectMapper;
55
import com.google.common.collect.Iterables;
6-
import io.specto.hoverfly.junit.core.model.Request;
7-
import io.specto.hoverfly.junit.core.model.RequestFieldMatcher;
8-
import io.specto.hoverfly.junit.core.model.RequestResponsePair;
9-
import io.specto.hoverfly.junit.core.model.Response;
6+
import io.specto.hoverfly.junit.core.model.*;
7+
108
import java.util.concurrent.TimeUnit;
119
import org.apache.commons.lang3.builder.EqualsBuilder;
1210
import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -554,6 +552,32 @@ public void shouldBeAbleToSetFixedDelay() {
554552
assertThat(pair.getResponse().getFixedDelay()).isEqualTo(10000);
555553
}
556554

555+
@Test
556+
public void shouldBeAbleToSetLogNormalRandomDelay() {
557+
558+
final RequestResponsePair pair = service("https://www.my-test.com")
559+
.get("/")
560+
.willReturn(response().withLogNormalDelay(3, 4, TimeUnit.SECONDS))
561+
.getRequestResponsePairs()
562+
.iterator().next();
563+
564+
assertThat(pair.getResponse().getLogNormalDelay())
565+
.isEqualToComparingFieldByField(new LogNormalDelay(0, 0, 3000, 4000));
566+
}
567+
568+
@Test
569+
public void shouldBeAbleToSetLogNormalRandomDelayWithMinAndMax() {
570+
571+
final RequestResponsePair pair = service("https://www.my-test.com")
572+
.get("/")
573+
.willReturn(response().withLogNormalDelay(3, 4, 1, 5, TimeUnit.SECONDS))
574+
.getRequestResponsePairs()
575+
.iterator().next();
576+
577+
assertThat(pair.getResponse().getLogNormalDelay())
578+
.isEqualToComparingFieldByField(new LogNormalDelay(1000, 5000, 3000, 4000));
579+
}
580+
557581
@Test
558582
public void shouldSetDefaultValuesForResponse() {
559583

@@ -564,14 +588,15 @@ public void shouldSetDefaultValuesForResponse() {
564588
.iterator().next()
565589
.getResponse();
566590

567-
assertThat(response.getFixedDelay()).isEqualTo(0);
568591
assertThat(response.getStatus()).isEqualTo(200);
569592
assertThat(response.getBody()).isEmpty();
570593
assertThat(response.getHeaders()).isEmpty();
571594
assertThat(response.getTransitionsState()).isEmpty();
572595
assertThat(response.getRemovesState()).isEmpty();
573596
assertThat(response.isEncodedBody()).isFalse();
574597
assertThat(response.isTemplated()).isTrue();
598+
assertThat(response.getFixedDelay()).isEqualTo(0);
599+
assertThat(response.getLogNormalDelay()).isNull();
575600
}
576601

577602
private void assertExactMatcherForMethod(RequestMatcherBuilder builder, String method) {

0 commit comments

Comments
 (0)