uk.co.sdev.async.http.AbstractParallel2SequentialCompletableFutureTest.java Source code

Java tutorial

Introduction

Here is the source code for uk.co.sdev.async.http.AbstractParallel2SequentialCompletableFutureTest.java

Source

/**
 * Copyright 2014 Andy Godwin
 *
 * 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 uk.co.sdev.async.http;

import com.github.tomakehurst.wiremock.verification.LoggedRequest;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.junit.Test;
import uk.co.sdev.async.HandOff;
import uk.co.sdev.async.Tuple2;
import uk.co.sdev.async.http.model.Denominator;
import uk.co.sdev.async.http.model.Numerator;
import uk.co.sdev.async.http.model.Quotient;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

import static com.github.tomakehurst.wiremock.client.WireMock.findAll;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static uk.co.sdev.async.Futures.none;
import static uk.co.sdev.async.Futures.parallel;
import static uk.co.sdev.async.Futures.sequential;

public abstract class AbstractParallel2SequentialCompletableFutureTest extends CompletableFutureClientTestSupport {

    protected abstract CompletableFuture<Optional<Numerator>> getNumerator() throws IOException;

    protected abstract CompletableFuture<Optional<Denominator>> getDenominator() throws IOException;

    protected abstract CompletableFuture<Optional<Quotient>> divide(Numerator numerator, Denominator denominator)
            throws IOException;

    private Function<Tuple2<Optional<Numerator>, Optional<Denominator>>, CompletableFuture<Optional<Quotient>>> divideFunc = tuple -> {
        if (tuple.a().isPresent() && tuple.b().isPresent()) {
            try {
                return divide(tuple.a().get(), tuple.b().get());
            } catch (IOException ioe) {
                return none();
            }
        } else {
            return none();
        }
    };

    @Test
    public void shouldDivide() throws Exception {
        stubGet("/numerator", new Numerator(new BigDecimal("12.4")));
        stubGet("/denominator", new Denominator(new BigDecimal("3.2")));
        stubGet("/divide/12.4/3.2", new Quotient(new BigDecimal("3.875")));

        HandOff<Optional<Quotient>> handOff = new HandOff<>();

        sequential(parallel(getNumerator(), getDenominator()), divideFunc)
                .whenComplete((quotient, throwable) -> handOff.put(quotient));

        Optional<Quotient> quotient = handOff.get(3);
        assertThat(quotient.isPresent(), is(true));
        assertThat(quotient.get().getValue(), is(new BigDecimal("3.875")));

        List<LoggedRequest> gets = findAll(getRequestedFor(urlMatching(".*")));
        for (LoggedRequest get : gets) {
            System.out.println(ReflectionToStringBuilder.toString(get));
        }
        assertThat(gets.size(), is(3));
    }

    @Test
    public void shouldReturnNoneIfNumeratorNotFound() throws Exception {
        stubGet("/numerator", 404);
        stubGet("/denominator", new Denominator(new BigDecimal("5.5")));

        HandOff<Optional<Quotient>> handOff = new HandOff<>();

        sequential(parallel(getNumerator(), getDenominator()), divideFunc)
                .whenComplete((quotient, throwable) -> handOff.put(quotient));

        Optional<Quotient> quotient = handOff.get(3);
        assertThat(quotient.isPresent(), is(false));

        List<LoggedRequest> gets = findAll(getRequestedFor(urlMatching(".*")));
        for (LoggedRequest get : gets) {
            System.out.println(ReflectionToStringBuilder.toString(get));
        }
        assertThat(gets.size(), is(2));
    }

    @Test
    public void shouldReturnNoneIfGetDenominatorReturnsInternalServerError() throws Exception {
        stubGet("/numerator", new Numerator(new BigDecimal("6.2")));
        stubGet("/denominator", 500);

        HandOff<Optional<Quotient>> handOff = new HandOff<>();

        sequential(parallel(getNumerator(), getDenominator()), divideFunc)
                .whenComplete((quotient, throwable) -> handOff.put(quotient));

        Optional<Quotient> quotient = handOff.get(3);
        assertThat(quotient.isPresent(), is(false));

        List<LoggedRequest> gets = findAll(getRequestedFor(urlMatching(".*")));
        for (LoggedRequest get : gets) {
            System.out.println(ReflectionToStringBuilder.toString(get));
        }
        assertThat(gets.size(), is(2));
    }

    @Test
    public void shouldReturnNoneIfDivideReturnsServiceUnavailable() throws Exception {
        stubGet("/numerator", new Numerator(new BigDecimal("7.2")));
        stubGet("/denominator", new Denominator(new BigDecimal("2.5")));
        stubGet("/divide/7.2/2.5", 503);

        HandOff<Optional<Quotient>> handOff = new HandOff<>();

        sequential(parallel(getNumerator(), getDenominator()), divideFunc)
                .whenComplete((quotient, throwable) -> handOff.put(quotient));

        Optional<Quotient> quotient = handOff.get(3);
        assertThat(quotient.isPresent(), is(false));

        List<LoggedRequest> gets = findAll(getRequestedFor(urlMatching(".*")));
        for (LoggedRequest get : gets) {
            System.out.println(ReflectionToStringBuilder.toString(get));
        }
        assertThat(gets.size(), is(3));
    }
}