fi.hsl.parkandride.itest.RequestLogITest.java Source code

Java tutorial

Introduction

Here is the source code for fi.hsl.parkandride.itest.RequestLogITest.java

Source

// Copyright  2015 HSL <https://www.hsl.fi>
// This program is dual-licensed under the EUPL v1.2 and AGPLv3 licenses.

package fi.hsl.parkandride.itest;

import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.response.Response;
import fi.hsl.parkandride.back.RequestLogDao;
import fi.hsl.parkandride.core.domain.RequestLogEntry;
import fi.hsl.parkandride.core.service.BatchingRequestLogService;
import fi.hsl.parkandride.core.service.reporting.ReportParameters;
import fi.hsl.parkandride.core.service.reporting.RequestLogInterval;
import fi.hsl.parkandride.front.UrlSchema;
import junit.framework.AssertionFailedError;
import org.apache.poi.ss.usermodel.Sheet;
import org.joda.time.DateTime;
import org.junit.Before;
import org.junit.Test;
import org.springframework.http.HttpStatus;

import javax.inject.Inject;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;

import static com.jayway.restassured.RestAssured.given;
import static com.jayway.restassured.RestAssured.when;
import static fi.hsl.parkandride.front.ReportController.MEDIA_TYPE_EXCEL;
import static fi.hsl.parkandride.front.RequestLoggingInterceptor.SOURCE_HEADER;
import static fi.hsl.parkandride.front.UrlSchema.FACILITY;
import static fi.hsl.parkandride.front.UrlSchema.HUB;
import static fi.hsl.parkandride.test.DateTimeTestUtils.withDate;
import static java.util.Arrays.asList;
import static java.util.stream.IntStream.range;
import static org.assertj.core.api.Assertions.assertThat;

public class RequestLogITest extends AbstractReportingITest {

    private static final String WEB_UI_SOURCE = "liipi-ui";
    private static final String REQUEST_LOG = "RequestLog";

    @Inject
    BatchingRequestLogService batchingRequestLogService;
    @Inject
    RequestLogDao requestLogDao;
    private String unknownSource;

    @Before
    public void init() {
        unknownSource = messageSource.getMessage("reports.requestlog.unknownSource", null, new Locale("fi"));
    }

    // ---------------------
    // REQUEST LOG REPORT
    // ---------------------
    @Test
    public void report_RequestLog_emptyReport() {
        generateDummyRequestLog();

        // Defaults to DAY interval, the month is empty so report should be empty
        final ReportParameters params = baseParams(BASE_DATE_TIME.minusMonths(2).toLocalDate());
        final Response whenPostingToReportUrl = postToReportUrl(params, REQUEST_LOG, adminUser);
        // If this succeeds, the response was a valid excel file
        withWorkbook(whenPostingToReportUrl, workbook -> {
            assertThat(workbook.getSheetName(0)).isEqualTo("Rajapintakutsut");
            assertThat(workbook.getSheetName(1)).isEqualTo("Selite");

            final Sheet sheet = workbook.getSheetAt(0);
            assertThat(getDataFromRow(sheet, 0)).containsExactly("Pivmr", "Lhde", "Polku",
                    "Kutsujen mr");
            assertThat(sheet.getPhysicalNumberOfRows()).isEqualTo(1);
        });
    }

    @Test
    public void report_RequestLog_byHour() {
        generateDummyRequestLog();

        final ReportParameters params = baseParams(BASE_DATE_TIME.toLocalDate());
        params.requestLogInterval = RequestLogInterval.HOUR;

        final Response whenPostingToReportUrl = postToReportUrl(params, REQUEST_LOG, adminUser);
        checkSheetContents(whenPostingToReportUrl, 0, headerWithTime("Aika"),
                asList(ROUNDED_BASE_DATETIME.toString(DATETIME_FORMAT), unknownSource, FACILITY, "12"),
                asList(ROUNDED_BASE_DATETIME.toString(DATETIME_FORMAT), unknownSource, HUB, "8"),
                asList(ROUNDED_BASE_DATETIME.toString(DATETIME_FORMAT), WEB_UI_SOURCE, FACILITY, "12"),
                asList(ROUNDED_BASE_DATETIME.toString(DATETIME_FORMAT), WEB_UI_SOURCE, HUB, "8"),
                asList(ROUNDED_BASE_DATETIME.plusHours(1).toString(DATETIME_FORMAT), WEB_UI_SOURCE, FACILITY, "12"),
                asList(ROUNDED_BASE_DATETIME.plusDays(1).toString(DATETIME_FORMAT), WEB_UI_SOURCE, FACILITY, "12"));
    }

    @Test
    public void report_RequestLog_byDay() {
        generateDummyRequestLog();

        final ReportParameters params = baseParams(BASE_DATE_TIME.toLocalDate());
        params.requestLogInterval = RequestLogInterval.DAY;

        final Response whenPostingToReportUrl = postToReportUrl(params, REQUEST_LOG, adminUser);
        checkSheetContents(whenPostingToReportUrl, 0, headerWithTime("Pivmr"),
                asList(ROUNDED_BASE_DATETIME.toString(DATE_FORMAT), unknownSource, FACILITY, "12"),
                asList(ROUNDED_BASE_DATETIME.toString(DATE_FORMAT), unknownSource, HUB, "8"),
                asList(ROUNDED_BASE_DATETIME.toString(DATE_FORMAT), WEB_UI_SOURCE, FACILITY, "24"),
                asList(ROUNDED_BASE_DATETIME.toString(DATE_FORMAT), WEB_UI_SOURCE, HUB, "8"),
                asList(ROUNDED_BASE_DATETIME.plusDays(1).toString(DATE_FORMAT), WEB_UI_SOURCE, FACILITY, "12"));
    }

    @Test
    public void report_RequestLog_byMonth() {
        generateDummyRequestLog();

        final ReportParameters params = baseParams(BASE_DATE_TIME.toLocalDate());
        params.requestLogInterval = RequestLogInterval.MONTH;
        params.startDate = BASE_DATE_TIME.minusMonths(1).withDayOfMonth(1).toLocalDate();

        final Response whenPostingToReportUrl = postToReportUrl(params, REQUEST_LOG, adminUser);
        checkSheetContents(whenPostingToReportUrl, 0, headerWithTime("Kuukausi"),
                asList(ROUNDED_BASE_DATETIME.minusMonths(1).toString(MONTH_FORMAT), WEB_UI_SOURCE, FACILITY, "12"),
                asList(ROUNDED_BASE_DATETIME.toString(MONTH_FORMAT), unknownSource, FACILITY, "12"),
                asList(ROUNDED_BASE_DATETIME.toString(MONTH_FORMAT), unknownSource, HUB, "8"),
                asList(ROUNDED_BASE_DATETIME.toString(MONTH_FORMAT), WEB_UI_SOURCE, FACILITY, "36"),
                asList(ROUNDED_BASE_DATETIME.toString(MONTH_FORMAT), WEB_UI_SOURCE, HUB, "8"));
    }

    @Test
    public void report_RequestLog_emptyParams() {
        final Response requestLog = whenPostingToReportUrl(new ReportParameters(), REQUEST_LOG, adminUser);
        requestLog.then().assertThat().statusCode(HttpStatus.BAD_REQUEST.value());
    }

    @Test
    public void report_RequestLog_nonExistentUrl_andUrlOutsideApi() {
        withDate(BASE_DATE_TIME, () -> {
            when().get(UrlSchema.API + "/foobarbazqux");
            when().get(UrlSchema.DOCS);
        });
        batchingRequestLogService.updateRequestLogs();

        // Defaults to DAY interval, the month is empty so report should be empty
        final ReportParameters params = baseParams(BASE_DATE_TIME.toLocalDate());
        final Response whenPostingToReportUrl = postToReportUrl(params, REQUEST_LOG, adminUser);
        // If this succeeds, the response was a valid excel file
        withWorkbook(whenPostingToReportUrl, workbook -> {
            // No requests logged
            final Sheet sheet = workbook.getSheetAt(0);
            assertThat(sheet.getPhysicalNumberOfRows()).isEqualTo(1);
        });
    }

    @Test
    public void report_RequestLog_unauthorized() {
        given().contentType(ContentType.JSON).accept(MEDIA_TYPE_EXCEL)
                .header(authorization(devHelper.login(apiUser.username).token)).body(new ReportParameters()).when()
                .post(UrlSchema.REPORT, REQUEST_LOG).then().assertThat().statusCode(HttpStatus.FORBIDDEN.value());
    }

    @Test
    public void illegalApplicationId_resultsInBadRequest() {
        given().header(SOURCE_HEADER, "mmm").when().get(UrlSchema.FACILITY, 1).then().assertThat()
                .statusCode(HttpStatus.BAD_REQUEST.value());
    }

    @Test
    public void generateConcurrent() {
        concurrentlyGenerateLogs(1000, 10);
        batchingRequestLogService.updateRequestLogs();
        final List<RequestLogEntry> logEntriesBetween = requestLogDao.getLogEntriesBetween(
                DateTime.now().millisOfDay().withMinimumValue(), DateTime.now().millisOfDay().withMaximumValue());
        assertThat(logEntriesBetween).hasSize(1).containsExactly(new RequestLogEntry(UrlSchema.CAPACITY_TYPES,
                WEB_UI_SOURCE, DateTime.now().withTime(12, 0, 0, 0), 1000l));
    }

    private void generateDummyRequestLog() {
        // Today
        withDate(BASE_DATE_TIME, () -> {
            range(0, 12).forEach(
                    i -> given().header(SOURCE_HEADER, WEB_UI_SOURCE).when().get(UrlSchema.FACILITY, facility1.id));
            range(0, 8)
                    .forEach(i -> given().header(SOURCE_HEADER, WEB_UI_SOURCE).when().get(UrlSchema.HUB, hub.id));

            // Without Source header
            range(0, 12).forEach(i -> when().get(UrlSchema.FACILITY, facility1.id));
            range(0, 8).forEach(i -> when().get(UrlSchema.HUB, hub.id));
        });

        // An hour after now
        withDate(BASE_DATE_TIME.plusHours(1), () -> {
            range(0, 12).forEach(
                    i -> given().header(SOURCE_HEADER, WEB_UI_SOURCE).when().get(UrlSchema.FACILITY, facility1.id));
        });

        // A day after now
        withDate(BASE_DATE_TIME.plusDays(1), () -> {
            range(0, 12).forEach(
                    i -> given().header(SOURCE_HEADER, WEB_UI_SOURCE).when().get(UrlSchema.FACILITY, facility1.id));
        });

        // A month before now
        withDate(BASE_DATE_TIME.minusMonths(1), () -> {
            range(0, 12).forEach(
                    i -> given().header(SOURCE_HEADER, WEB_UI_SOURCE).when().get(UrlSchema.FACILITY, facility1.id));
        });

        // Store the batch to database
        batchingRequestLogService.updateRequestLogs();
    }

    private void concurrentlyGenerateLogs(int numberOfRequests, int numberOfUpdates) {
        withDate(DateTime.now().withTime(12, 2, 0, 0), () -> {
            final Stream<CompletableFuture<Integer>> statusCodes = range(0, numberOfRequests).parallel()
                    .mapToObj(i -> {
                        final Response response = given().header(SOURCE_HEADER, WEB_UI_SOURCE).when()
                                .get(UrlSchema.CAPACITY_TYPES).thenReturn();
                        return CompletableFuture.completedFuture(response.statusCode());
                    });

            final Stream<CompletableFuture<Integer>> updates = range(0, numberOfUpdates).parallel().mapToObj(i -> {
                batchingRequestLogService.updateRequestLogs();
                return CompletableFuture.completedFuture(0);
            });

            try {
                CompletableFuture.allOf(Stream.concat(statusCodes, updates).toArray(i -> new CompletableFuture[i]))
                        .get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
                throw new AssertionFailedError(e.getMessage());
            }
        });
    }

    private List<String> headerWithTime(String timeColumnHeader) {
        return asList(timeColumnHeader, "Lhde", "Polku", "Kutsujen mr");
    }

}