/*
* Copyright (C) 2013 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package retrofit2.mock;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.Callable;
import okhttp3.ResponseBody;
import org.junit.Test;
import retrofit2.Response;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public final class NetworkBehaviorTest {
private final NetworkBehavior behavior = NetworkBehavior.create(new Random(2847));
@Test public void defaultThrowable() {
Throwable t = behavior.failureException();
assertThat(t).isInstanceOf(IOException.class)
.isExactlyInstanceOf(MockRetrofitIOException.class);
assertThat(t.getStackTrace()).isEmpty();
}
@Test public void delayMustBePositive() {
try {
behavior.setDelay(-1, SECONDS);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Amount must be positive value.");
}
}
@Test public void varianceRestrictsRange() {
try {
behavior.setVariancePercent(-13);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Variance percentage must be between 0 and 100.");
}
try {
behavior.setVariancePercent(174);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Variance percentage must be between 0 and 100.");
}
}
@Test public void failureRestrictsRange() {
try {
behavior.setFailurePercent(-13);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Failure percentage must be between 0 and 100.");
}
try {
behavior.setFailurePercent(174);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Failure percentage must be between 0 and 100.");
}
}
@Test public void failureExceptionIsNotNull() {
try {
behavior.setFailureException(null);
fail();
} catch (NullPointerException e) {
assertThat(e).hasMessage("exception == null");
}
}
@Test public void errorRestrictsRange() {
try {
behavior.setErrorPercent(-13);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Error percentage must be between 0 and 100.");
}
try {
behavior.setErrorPercent(174);
fail();
} catch (IllegalArgumentException e) {
assertThat(e).hasMessage("Error percentage must be between 0 and 100.");
}
}
@Test public void errorFactoryIsNotNull() {
try {
behavior.setErrorFactory(null);
fail();
} catch (NullPointerException e) {
assertThat(e).hasMessage("errorFactory == null");
}
}
@Test public void errorFactoryCannotReturnNull() {
behavior.setErrorFactory(new Callable<Response<?>>() {
@Override public Response<?> call() throws Exception {
return null;
}
});
try {
behavior.createErrorResponse();
fail();
} catch (IllegalStateException e) {
assertThat(e).hasMessage("Error factory returned null.");
}
}
@Test public void errorFactoryCannotThrow() {
final RuntimeException broken = new RuntimeException("Broken");
behavior.setErrorFactory(new Callable<Response<?>>() {
@Override public Response<?> call() throws Exception {
throw broken;
}
});
try {
behavior.createErrorResponse();
fail();
} catch (IllegalStateException e) {
assertThat(e).hasMessage("Error factory threw an exception.");
assertThat(e.getCause()).isSameAs(broken);
}
}
@Test public void errorFactoryCannotReturnSuccess() {
behavior.setErrorFactory(new Callable<Response<?>>() {
@Override public Response<?> call() throws Exception {
return Response.success("Taco");
}
});
try {
behavior.createErrorResponse();
fail();
} catch (IllegalStateException e) {
assertThat(e).hasMessage("Error factory returned successful response.");
}
}
@Test public void errorFactoryCalledEachTime() {
behavior.setErrorFactory(new Callable<Response<?>>() {
private int code = 500;
@Override public Response<?> call() throws Exception {
return Response.error(code++, ResponseBody.create(null, new byte[0]));
}
});
assertEquals(500, behavior.createErrorResponse().code());
assertEquals(501, behavior.createErrorResponse().code());
assertEquals(502, behavior.createErrorResponse().code());
}
@Test public void failurePercentageIsAccurate() {
behavior.setFailurePercent(0);
for (int i = 0; i < 10000; i++) {
assertThat(behavior.calculateIsFailure()).isFalse();
}
behavior.setFailurePercent(3);
int failures = 0;
for (int i = 0; i < 100000; i++) {
if (behavior.calculateIsFailure()) {
failures += 1;
}
}
assertThat(failures).isEqualTo(2964); // ~3% of 100k
}
@Test public void errorPercentageIsAccurate() {
behavior.setErrorPercent(0);
for (int i = 0; i < 10000; i++) {
assertThat(behavior.calculateIsError()).isFalse();
}
behavior.setErrorPercent(3);
int errors = 0;
for (int i = 0; i < 100000; i++) {
if (behavior.calculateIsError()) {
errors += 1;
}
}
assertThat(errors).isEqualTo(2964); // ~3% of 100k
}
@Test public void delayVarianceIsAccurate() {
behavior.setDelay(2, SECONDS);
behavior.setVariancePercent(0);
for (int i = 0; i < 100000; i++) {
assertThat(behavior.calculateDelay(MILLISECONDS)).isEqualTo(2000);
}
behavior.setVariancePercent(40);
long lowerBound = Integer.MAX_VALUE;
long upperBound = Integer.MIN_VALUE;
for (int i = 0; i < 100000; i++) {
long delay = behavior.calculateDelay(MILLISECONDS);
if (delay > upperBound) {
upperBound = delay;
}
if (delay < lowerBound) {
lowerBound = delay;
}
}
assertThat(upperBound).isEqualTo(2799); // ~40% above 2000
assertThat(lowerBound).isEqualTo(1200); // ~40% below 2000
}
}