package uk.ac.ox.zoo.seeg.abraid.mp.common.service.workflow.support.runrequest; import net.lingala.zip4j.exception.ZipException; import org.apache.commons.lang.RandomStringUtils; import org.joda.time.DateTime; import org.joda.time.DateTimeUtils; import org.joda.time.LocalDateTime; import org.junit.Test; import org.mockito.ArgumentCaptor; import uk.ac.ox.zoo.seeg.abraid.mp.common.domain.*; import uk.ac.ox.zoo.seeg.abraid.mp.common.dto.json.JsonModelRunResponse; import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.CovariateService; import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.DiseaseService; import uk.ac.ox.zoo.seeg.abraid.mp.common.service.core.ModelRunService; import java.io.File; import java.io.IOException; import java.net.URI; import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.*; import static uk.ac.ox.zoo.seeg.abraid.mp.testutils.GeneralTestUtils.captorForClass; /** * Tests for ModelRunRequester. * Copyright (c) 2014 University of Oxford */ public class ModelRunRequesterTest { @Test public void requestModelRunUsesLeastBusyModelWrapper() throws Exception { // Arrange CovariateService covariateService = mock(CovariateService.class); DiseaseService diseaseService = mock(DiseaseService.class); ModelRunPackageBuilder modelRunPackageBuilder = mock(ModelRunPackageBuilder.class); when(diseaseService.getDiseaseGroupById(87)).thenReturn(mock(DiseaseGroup.class)); when(diseaseService.getDiseaseGroupById(87).getAbbreviation()).thenReturn("deng"); ModelWrapperWebService webService = mock(ModelWrapperWebService.class); when(webService.startRun(any(URI.class), any(File.class))).thenReturn(mock(JsonModelRunResponse.class)); ModelRunService runService = mock(ModelRunService.class); when(runService.getModelRunRequestServersByUsage()).thenReturn(Arrays.asList("a", "c", "b")); ModelRunRequester target = new ModelRunRequester(webService, modelRunPackageBuilder, covariateService, diseaseService, runService, Arrays.asList("http://api:key@a:1245/path", "http://api:key@b:1245/path", "http://api:key@c:1245/path")); // Act target.requestModelRun(87, Arrays.asList(mock(DiseaseOccurrence.class)), null, null); // Assert verify(webService).startRun(eq(URI.create("http://api:key@a:1245/path")), any(File.class)); } @Test public void requestModelRunUsesFirstNewModelWrapper() throws Exception { // Arrange CovariateService covariateService = mock(CovariateService.class); DiseaseService diseaseService = mock(DiseaseService.class); ModelRunPackageBuilder modelRunPackageBuilder = mock(ModelRunPackageBuilder.class); when(diseaseService.getDiseaseGroupById(87)).thenReturn(mock(DiseaseGroup.class)); when(diseaseService.getDiseaseGroupById(87).getAbbreviation()).thenReturn("deng"); ModelWrapperWebService webService = mock(ModelWrapperWebService.class); when(webService.startRun(any(URI.class), any(File.class))).thenReturn(mock(JsonModelRunResponse.class)); ModelRunService runService = mock(ModelRunService.class); when(runService.getModelRunRequestServersByUsage()).thenReturn(Arrays.asList("c", "b")); ModelRunRequester target = new ModelRunRequester(webService, modelRunPackageBuilder, covariateService, diseaseService, runService, Arrays.asList("http://api:key@a:1245/path", "http://api:key@b:1245/path", "http://api:key@c:1245/path", "http://api:key@d:1245/path")); // Act target.requestModelRun(87, Arrays.asList(mock(DiseaseOccurrence.class)), null, null); // Assert verify(webService).startRun(eq(URI.create("http://api:key@a:1245/path")), any(File.class)); } @Test public void requestModelRunSavesTheInputOccurrencesForAutomaticModelRun() throws Exception { // Arrange ModelRunService runService = mock(ModelRunService.class); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, true, true, null), mock(ModelRunPackageBuilder.class), mock(CovariateService.class), mock(ModelWrapperWebService.class)); // Act target.requestModelRun(87, Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)), null, null); // Assert ArgumentCaptor<ModelRun> modelRunArgumentCaptor = captorForClass(ModelRun.class); verify(runService).saveModelRun(modelRunArgumentCaptor.capture()); ModelRun value = modelRunArgumentCaptor.getValue(); assertThat(value.getInputDiseaseOccurrences()).hasSize(3); } @Test public void requestModelRunDoesNotSaveTheInputOccurrencesForManualModelRun() throws Exception { // Arrange ModelRunService runService = mock(ModelRunService.class); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, false, true, null), mock(ModelRunPackageBuilder.class), mock(CovariateService.class), mock(ModelWrapperWebService.class)); // Act target.requestModelRun(87, Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)), null, null); // Assert ArgumentCaptor<ModelRun> modelRunArgumentCaptor = captorForClass(ModelRun.class); verify(runService).saveModelRun(modelRunArgumentCaptor.capture()); ModelRun value = modelRunArgumentCaptor.getValue(); assertThat(value.getInputDiseaseOccurrences()).isNull(); } @Test public void requestModelRunSavesTheInputExtent() throws Exception { // Arrange ModelRunService runService = mock(ModelRunService.class); DiseaseService diseaseService = mock(DiseaseService.class); List<AdminUnitDiseaseExtentClass> extent = Arrays.asList( createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass() ); when(diseaseService.getDiseaseExtentByDiseaseGroupId(87)).thenReturn(extent); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, true, true, diseaseService), mock(ModelRunPackageBuilder.class), mock(CovariateService.class), mock(ModelWrapperWebService.class)); // Act target.requestModelRun(87, Arrays.asList(mock(DiseaseOccurrence.class)), null, null); // Assert ArgumentCaptor<ModelRun> modelRunArgumentCaptor = captorForClass(ModelRun.class); verify(runService).saveModelRun(modelRunArgumentCaptor.capture()); ModelRun value = modelRunArgumentCaptor.getValue(); assertThat(value.getInputDiseaseExtent()).hasSize(4); } @Test public void requestModelRunSavesCorrectOccurrenceRangeDates() throws Exception { // Arrange ModelRunService runService = mock(ModelRunService.class); DiseaseService diseaseService = mock(DiseaseService.class); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, true, true, diseaseService), mock(ModelRunPackageBuilder.class), mock(CovariateService.class), mock(ModelWrapperWebService.class)); DiseaseOccurrence oldest = mock(DiseaseOccurrence.class); DateTime oldDate = DateTime.parse("2013-02-27T08:06:46.000Z"); when(oldest.getOccurrenceDate()).thenReturn(oldDate); DiseaseOccurrence newest = mock(DiseaseOccurrence.class); DateTime newDate = DateTime.parse("2014-02-27T08:06:46.000Z"); when(newest.getOccurrenceDate()).thenReturn(newDate); List<DiseaseOccurrence> occurrencesForModelRun = Arrays.asList(newest, oldest); // Act target.requestModelRun(87, occurrencesForModelRun, null, null); // Assert ArgumentCaptor<ModelRun> modelRunArgumentCaptor = captorForClass(ModelRun.class); verify(runService).saveModelRun(modelRunArgumentCaptor.capture()); ModelRun value = modelRunArgumentCaptor.getValue(); assertThat(value.getOccurrenceDataRangeStartDate()).isEqualTo(oldDate); assertThat(value.getOccurrenceDataRangeEndDate()).isEqualTo(newDate); } private static final String UUID_REGEX = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"; @Test public void requestModelRunHandlesLongNames() throws Exception { // Arrange DiseaseService diseaseService = mock(DiseaseService.class); ModelRunService runService = mock(ModelRunService.class); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, true, true, diseaseService), mock(ModelRunPackageBuilder.class), mock(CovariateService.class), mock(ModelWrapperWebService.class)); DateTimeUtils.setCurrentMillisFixed(0); String longName = RandomStringUtils.randomAlphanumeric(300); when(diseaseService.getDiseaseGroupById(87).getAbbreviation()).thenReturn(longName); String expectedRunNameStart = longName.substring(0, 195) + "_" + LocalDateTime.now().toString("yyyy-MM-dd-HH-mm-ss") + "_"; // Act target.requestModelRun(87, Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)), null, null); // Assert ArgumentCaptor<ModelRun> modelRunArgumentCaptor = captorForClass(ModelRun.class); verify(runService).saveModelRun(modelRunArgumentCaptor.capture()); ModelRun value = modelRunArgumentCaptor.getValue(); assertThat(value.getName()).startsWith(expectedRunNameStart); assertThat(value.getName()).matches(expectedRunNameStart + UUID_REGEX); } @Test public void requestModelRunBuildsZipWithCorrectData() throws Exception { // Arrange ModelRunService runService = mock(ModelRunService.class); CovariateService covService = mock(CovariateService.class); DiseaseService diseaseService = mock(DiseaseService.class); List<DiseaseOccurrence> occurrences = Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)); List<DiseaseOccurrence> biasOccurrences = Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)); List<AdminUnitDiseaseExtentClass> extent = Arrays.asList( createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass() ); List<CovariateFile> covariateFiles = Arrays.asList( mock(CovariateFile.class), mock(CovariateFile.class), mock(CovariateFile.class) ); when(covService.getCovariateDirectory()).thenReturn("covDir"); when(diseaseService.getDiseaseExtentByDiseaseGroupId(87)).thenReturn(extent); ModelRunPackageBuilder zipBuilder = mock(ModelRunPackageBuilder.class); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, true, true, diseaseService), zipBuilder, covService, mock(ModelWrapperWebService.class)); DiseaseGroup diseaseGroup = diseaseService.getDiseaseGroupById(87); when(diseaseService.getCountOfUnfilteredBespokeBiasOccurrences(same(diseaseGroup))).thenReturn(0L); when(diseaseService.getDefaultBiasOccurrencesForModelRun(same(diseaseGroup), any(DateTime.class), any(DateTime.class))).thenReturn(biasOccurrences); when(covService.getCovariateFilesByDiseaseGroup(diseaseGroup)).thenReturn(covariateFiles); // Act target.requestModelRun(87, occurrences, null, null); // Assert verify(zipBuilder).buildPackage(startsWith("deng_"), same(diseaseGroup), same(occurrences), same(extent), same(biasOccurrences), same(covariateFiles), eq("covDir")); } @Test public void requestModelRunBuildsZipWithCorrectDataWhenBespokeBiasAvailable() throws Exception { // Arrange ModelRunService runService = mock(ModelRunService.class); CovariateService covService = mock(CovariateService.class); DiseaseService diseaseService = mock(DiseaseService.class); List<DiseaseOccurrence> occurrences = Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)); List<DiseaseOccurrence> biasOccurrences = Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)); List<AdminUnitDiseaseExtentClass> extent = Arrays.asList( createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass() ); List<CovariateFile> covariateFiles = Arrays.asList( mock(CovariateFile.class), mock(CovariateFile.class), mock(CovariateFile.class) ); when(covService.getCovariateDirectory()).thenReturn("covDir"); when(diseaseService.getDiseaseExtentByDiseaseGroupId(87)).thenReturn(extent); ModelRunPackageBuilder zipBuilder = mock(ModelRunPackageBuilder.class); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, true, true, diseaseService), zipBuilder, covService, mock(ModelWrapperWebService.class)); DiseaseGroup diseaseGroup = diseaseService.getDiseaseGroupById(87); when(diseaseService.getCountOfUnfilteredBespokeBiasOccurrences(same(diseaseGroup))).thenReturn(4L); when(diseaseService.getBespokeBiasOccurrencesForModelRun(same(diseaseGroup), any(DateTime.class), any(DateTime.class))).thenReturn(biasOccurrences); when(covService.getCovariateFilesByDiseaseGroup(diseaseGroup)).thenReturn(covariateFiles); // Act target.requestModelRun(87, occurrences, null, null); // Assert verify(zipBuilder).buildPackage(startsWith("deng_"), same(diseaseGroup), same(occurrences), same(extent), same(biasOccurrences), same(covariateFiles), eq("covDir")); } @Test public void requestModelRunBuildsZipWithCorrectDataWhenNotUsingBias() throws Exception { // Arrange ModelRunService runService = mock(ModelRunService.class); CovariateService covService = mock(CovariateService.class); DiseaseService diseaseService = mock(DiseaseService.class); List<DiseaseOccurrence> occurrences = Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)); List<AdminUnitDiseaseExtentClass> extent = Arrays.asList( createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass() ); List<CovariateFile> covariateFiles = Arrays.asList( mock(CovariateFile.class), mock(CovariateFile.class), mock(CovariateFile.class) ); when(covService.getCovariateDirectory()).thenReturn("covDir"); when(diseaseService.getDiseaseExtentByDiseaseGroupId(87)).thenReturn(extent); ModelRunPackageBuilder zipBuilder = mock(ModelRunPackageBuilder.class); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, true, false, diseaseService), zipBuilder, covService, mock(ModelWrapperWebService.class)); DiseaseGroup diseaseGroup = diseaseService.getDiseaseGroupById(87); when(diseaseService.getCountOfUnfilteredBespokeBiasOccurrences(same(diseaseGroup))).thenReturn(4L); when(diseaseService.getBespokeBiasOccurrencesForModelRun(same(diseaseGroup), any(DateTime.class), any(DateTime.class))).thenReturn( Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class))); when(covService.getCovariateFilesByDiseaseGroup(diseaseGroup)).thenReturn(covariateFiles); List<DiseaseOccurrence> biasOccurrences = null; // Act target.requestModelRun(87, occurrences, null, null); // Assert verify(zipBuilder).buildPackage(startsWith("deng_"), same(diseaseGroup), same(occurrences), same(extent), same(biasOccurrences), same(covariateFiles), eq("covDir")); } @Test public void requestModelRunBuildsZipWithCorrectDataSubmitsCorrectZipToWebService() throws Exception { // Arrange ModelRunService runService = mock(ModelRunService.class); CovariateService covService = mock(CovariateService.class); DiseaseService diseaseService = mock(DiseaseService.class); List<DiseaseOccurrence> occurrences = Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)); List<DiseaseOccurrence> biasOccurrences = Arrays.asList(mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class), mock(DiseaseOccurrence.class)); List<AdminUnitDiseaseExtentClass> extent = Arrays.asList( createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass(), createMockAdminUnitDiseaseExtentClass() ); List<CovariateFile> covariateFiles = Arrays.asList( mock(CovariateFile.class), mock(CovariateFile.class), mock(CovariateFile.class) ); when(covService.getCovariateDirectory()).thenReturn("covDir"); when(diseaseService.getDiseaseExtentByDiseaseGroupId(87)).thenReturn(extent); ModelRunPackageBuilder zipBuilder = mock(ModelRunPackageBuilder.class); ModelWrapperWebService webService = mock(ModelWrapperWebService.class); ModelRunRequester target = createMockModelRunRequester(runService, mockDiseaseAndService(87, true, true, diseaseService), zipBuilder, covService, webService); DiseaseGroup diseaseGroup = diseaseService.getDiseaseGroupById(87); when(diseaseService.getCountOfUnfilteredBespokeBiasOccurrences(same(diseaseGroup))).thenReturn(0L); when(diseaseService.getDefaultBiasOccurrencesForModelRun(same(diseaseGroup), any(DateTime.class), any(DateTime.class))).thenReturn(biasOccurrences); when(covService.getCovariateFilesByDiseaseGroup(diseaseGroup)).thenReturn(covariateFiles); File zipFile = Files.createTempFile("abc", "xzy").toFile(); when(zipBuilder.buildPackage(startsWith("deng_"), same(diseaseGroup), same(occurrences), same(extent), same(biasOccurrences), same(covariateFiles), eq("covDir"))).thenReturn(zipFile); // Act target.requestModelRun(87, occurrences, null, null); // Assert verify(webService).startRun(any(URI.class), same(zipFile)); assertThat(zipFile).doesNotExist(); // Should have been deleted } private AdminUnitDiseaseExtentClass createMockAdminUnitDiseaseExtentClass() { AdminUnitDiseaseExtentClass mock = mock(AdminUnitDiseaseExtentClass.class); when(mock.getAdminUnitGlobalOrTropical()).thenReturn(mock(AdminUnitGlobalOrTropical.class)); when(mock.getDiseaseExtentClass()).thenReturn(mock(DiseaseExtentClass.class)); return mock; } private ModelRunRequester createMockModelRunRequester(ModelRunService runService, DiseaseService mockDiseaseService, ModelRunPackageBuilder modelRunPackageBuilder1, CovariateService covariateService, ModelWrapperWebService webService) throws IOException, ZipException { when(webService.startRun(any(URI.class), any(File.class))).thenReturn(mock(JsonModelRunResponse.class)); when(runService.getModelRunRequestServersByUsage()).thenReturn(new ArrayList<String>()); return new ModelRunRequester(webService, modelRunPackageBuilder1, covariateService, mockDiseaseService, runService, Arrays.asList("http://api:key@a:1245/path")); } private DiseaseService mockDiseaseAndService(int diseaseGroupId, boolean automaticRuns, boolean useBias, DiseaseService mockDiseaseService) { DiseaseService diseaseService = mockDiseaseService == null ? mock(DiseaseService.class) : mockDiseaseService; DiseaseGroup diseaseGroup = mock(DiseaseGroup.class); when(diseaseService.getDiseaseGroupById(diseaseGroupId)).thenReturn(diseaseGroup); when(diseaseService.getDiseaseGroupById(diseaseGroupId).getAbbreviation()).thenReturn("deng"); when(diseaseService.modelModeRequiresBiasDataForDisease(diseaseGroup)).thenReturn(useBias); when(diseaseService.getDiseaseGroupById(diseaseGroupId).isAutomaticModelRunsEnabled()).thenReturn(automaticRuns); return diseaseService; } }