package org.zalando.riptide;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.restdriver.clientdriver.ClientDriverRule;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NON_PRIVATE;
import static com.github.restdriver.clientdriver.RestClientDriver.giveEmptyResponse;
import static com.github.restdriver.clientdriver.RestClientDriver.giveResponseAsBytes;
import static com.github.restdriver.clientdriver.RestClientDriver.onRequestTo;
import static com.google.common.io.Resources.getResource;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static java.util.stream.Collectors.toList;
import static org.hamcrest.Matchers.hasItems;
import static org.junit.Assert.assertThat;
import static org.springframework.http.HttpStatus.Series.SUCCESSFUL;
import static org.zalando.riptide.Bindings.on;
import static org.zalando.riptide.Navigators.series;
import static org.zalando.riptide.RestBuilder.simpleRequestFactory;
import static org.zalando.riptide.Route.listOf;
import static org.zalando.riptide.Route.pass;
public final class IOTest {
@Rule
public final ClientDriverRule driver = new ClientDriverRule();
@JsonAutoDetect(fieldVisibility = NON_PRIVATE)
static class User {
String login;
public String getLogin() {
return login;
}
}
private final ExecutorService executor = newSingleThreadExecutor();
private final Rest rest = Rest.builder()
.baseUrl(driver.getBaseUrl())
.configure(simpleRequestFactory(executor))
.converter(createJsonConverter())
.build();
private MappingJackson2HttpMessageConverter createJsonConverter() {
final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(new ObjectMapper().findAndRegisterModules()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
return converter;
}
@After
public void tearDown() {
executor.shutdown();
}
@Test
public void shouldReadContributors() throws IOException {
driver.addExpectation(onRequestTo("/repos/zalando/riptide/contributors"),
giveResponseAsBytes(getResource("contributors.json").openStream(), "application/json"));
final AtomicReference<List<User>> reference = new AtomicReference<>();
rest.get("/repos/{org}/{repo}/contributors", "zalando", "riptide")
.dispatch(series(),
on(SUCCESSFUL).call(listOf(User.class), reference::set)).join();
final List<String> users = reference.get().stream()
.map(User::getLogin)
.collect(toList());
assertThat(users, hasItems("jhorstmann", "lukasniemeier-zalando", "whiskeysierra"));
}
@Test
public void shouldCancelRequest() throws ExecutionException, InterruptedException {
driver.addExpectation(onRequestTo("/repos/zalando/riptide/contributors"),
giveEmptyResponse().after(1, TimeUnit.SECONDS));
final CompletableFuture<Void> future = rest.get("/repos/{org}/{repo}/contributors", "zalando", "riptide")
.dispatch(series(),
on(SUCCESSFUL).call(pass()));
future.cancel(true);
try {
future.join();
} catch (final CancellationException e) {
// expected
}
// we don't care whether the request was actually made or not, but by default the driver will verify
// all expectations after every tests
driver.reset();
}
}