Java tutorial
/** * Copyright 2014 VU University Medical Center. * Licensed under the Apache License version 2.0 (see http://www.apache.org/licenses/LICENSE-2.0.html). */ package nl.vumc.biomedbridges.galaxy; import com.github.jmchilton.blend4j.galaxy.GalaxyInstance; import com.github.jmchilton.blend4j.galaxy.HistoriesClient; import com.github.jmchilton.blend4j.galaxy.ToolsClient; import com.github.jmchilton.blend4j.galaxy.WorkflowsClient; import com.github.jmchilton.blend4j.galaxy.beans.Dataset; import com.github.jmchilton.blend4j.galaxy.beans.History; import com.github.jmchilton.blend4j.galaxy.beans.HistoryContents; import com.github.jmchilton.blend4j.galaxy.beans.HistoryDetails; import com.github.jmchilton.blend4j.galaxy.beans.WorkflowDetails; import com.github.jmchilton.blend4j.galaxy.beans.WorkflowInputDefinition; import com.github.jmchilton.blend4j.galaxy.beans.WorkflowInputs; import com.github.jmchilton.blend4j.galaxy.beans.WorkflowOutputs; import com.github.jmchilton.blend4j.galaxy.beans.WorkflowStepDefinition; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; import com.sun.jersey.api.client.ClientResponse; import java.io.File; import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import nl.vumc.biomedbridges.core.Constants; import nl.vumc.biomedbridges.core.FileUtils; import nl.vumc.biomedbridges.core.Workflow; import nl.vumc.biomedbridges.galaxy.configuration.GalaxyConfiguration; import org.apache.http.HttpStatus; import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; /** * Unit tests for the GalaxyWorkflowEngine class. * * @author <a href="mailto:f.debruijn@vumc.nl">Freek de Bruijn</a> */ public class GalaxyWorkflowEngineTest { /** * The resources directory for the galaxy package. */ private static final String GALAXY_DIRECTORY = Paths.get("src", "test", "resources", "nl", "vumc", "biomedbridges", "galaxy") + File.separator; /** * Workflow output file path. */ private static final String TMP_DIRECTORY = Paths.get("tmp").toString(); /** * Test the configure method with nonsense configuration data. */ @Test public void testConfigureNonsense() { // todo: move this test and the next two tests to another test class: GalaxyConfigurationTest. assertNull(new GalaxyConfiguration().determineGalaxyInstance("nonsense")); } /** * Test the configure method with configuration data that appears to be valid but is not. */ @Test public void testConfigureInvalid() { final String configurationData = GalaxyConfiguration.PROPERTY_SEPARATOR + GalaxyConfiguration.KEY_VALUE_SEPARATOR + GalaxyConfiguration.GALAXY_INSTANCE_PROPERTY_KEY + GalaxyConfiguration.KEY_VALUE_SEPARATOR + GalaxyConfiguration.API_KEY_PROPERTY_KEY + GalaxyConfiguration.KEY_VALUE_SEPARATOR; assertNull(new GalaxyConfiguration().determineGalaxyInstance(configurationData)); } /** * Test the configure method with valid configuration data. */ @Test public void testConfigureValid() { final String apiKey = "some-api-key"; final String historyName = "some-history-name"; final String configurationData = GalaxyConfiguration.GALAXY_INSTANCE_PROPERTY_KEY + GalaxyConfiguration.KEY_VALUE_SEPARATOR + Constants.CENTRAL_GALAXY_URL + GalaxyConfiguration.PROPERTY_SEPARATOR + GalaxyConfiguration.API_KEY_PROPERTY_KEY + GalaxyConfiguration.KEY_VALUE_SEPARATOR + apiKey + GalaxyConfiguration.PROPERTY_SEPARATOR + GalaxyConfiguration.HISTORY_NAME_PROPERTY_KEY + GalaxyConfiguration.KEY_VALUE_SEPARATOR + historyName; final GalaxyConfiguration galaxyConfiguration = new GalaxyConfiguration(); assertNotNull(galaxyConfiguration.determineGalaxyInstance(configurationData)); assertEquals(apiKey, galaxyConfiguration.getGalaxyApiKey()); assertEquals(historyName, galaxyConfiguration.getGalaxyHistoryName()); } /** * Test the runWorkflow method with automatic downloading enabled and normal order for the output IDs. */ @Test public void testRunWorkflowAutomaticDownload() throws Exception { for (int outputIdCount = 0; outputIdCount < 3; outputIdCount++) runWorkflowTest(true, true, outputIdCount, true); } /** * Test the runWorkflow method with automatic downloading disabled and reversed order for the output IDs. */ @Test public void testRunWorkflowManualDownload() throws Exception { for (int outputIdCount = 0; outputIdCount < 3; outputIdCount++) runWorkflowTest(false, false, outputIdCount, false); } /** * Run the workflow test with two parameters. * * @param automaticDownload whether the automatic download option should be enabled or disabled. * @param historyReady whether uploading files and workflow running finishes within the time limits. * @param outputIdCount the number of output IDs the workflow should produce. * @param normalOutputIdOrder whether the normal or reversed order should be used for the output IDs. * @throws IOException if reading the workflow results fails. * @throws InterruptedException if any thread has interrupted the current thread while waiting for the workflow * engine. */ private void runWorkflowTest(final boolean automaticDownload, final boolean historyReady, final int outputIdCount, final boolean normalOutputIdOrder) throws InterruptedException, IOException { final String historyId = "history-id"; final String workflowId = "workflow-id"; final String workflowName = "workflow-name"; final String inputLabel = "input-label"; final Object dummyInputFile = new File(GALAXY_DIRECTORY + "TestWorkflow.ga"); final Collection<Object> inputValues = ImmutableList.of(dummyInputFile, dummyInputFile); final Map<String, List<String>> stateIds = new HashMap<>(); stateIds.put("running", historyReady ? new ArrayList<String>() : Arrays.asList("some-dataset-id")); stateIds.put("queued", new ArrayList<String>()); stateIds.put("ok", new ArrayList<String>()); final com.github.jmchilton.blend4j.galaxy.beans.Workflow blend4jWorkflow = new com.github.jmchilton.blend4j.galaxy.beans.Workflow(); blend4jWorkflow.setName(workflowName); blend4jWorkflow.setId(workflowId); final Set<Map.Entry<String, Object>> inputEntries = ImmutableSet .of(Maps.immutableEntry(inputLabel, (Object) new File("non-existing-file"))); final WorkflowInputDefinition workflowInputDefinition = new WorkflowInputDefinition(); workflowInputDefinition.setLabel(inputLabel); final Map<String, WorkflowInputDefinition> inputDefinitionMap = ImmutableMap.of(inputLabel, workflowInputDefinition); final String stepId = "1"; final Map<Object, Map<String, Object>> parameters = ImmutableMap.of((Object) stepId, (Map<String, Object>) ImmutableMap.of("parameter", (Object) "value")); final Map<String, WorkflowStepDefinition> workflowSteps = ImmutableMap.of(stepId, new WorkflowStepDefinition()); final String outputId1 = "oid-1"; final String outputId2 = "oid-2"; final GalaxyWorkflow galaxyWorkflowMock = Mockito.mock(GalaxyWorkflow.class); final GalaxyInstance galaxyInstanceMock = Mockito.mock(GalaxyInstance.class); final WorkflowsClient workflowsClientMock = Mockito.mock(WorkflowsClient.class); final ToolsClient toolsClientMock = Mockito.mock(ToolsClient.class); final ClientResponse clientResponse1 = Mockito.mock(ClientResponse.class); final ClientResponse clientResponse2 = Mockito.mock(ClientResponse.class); final HistoriesClient historiesClientMock = Mockito.mock(HistoriesClient.class); final History historyMock = Mockito.mock(History.class); final HistoryDetails historyDetailsMock = Mockito.mock(HistoryDetails.class); final WorkflowOutputs workflowOutputsMock = Mockito.mock(WorkflowOutputs.class); final WorkflowDetails workflowDetailsMock = Mockito.mock(WorkflowDetails.class); final Dataset datasetMock1 = Mockito.mock(Dataset.class); final Dataset datasetMock2 = Mockito.mock(Dataset.class); final HistoryUtils historyUtilsMock = Mockito.mock(HistoryUtils.class); if (automaticDownload) Mockito.when(galaxyWorkflowMock.getDownloadDirectory()).thenReturn(TMP_DIRECTORY); Mockito.when(galaxyInstanceMock.getWorkflowsClient()).thenReturn(workflowsClientMock); Mockito.when(galaxyInstanceMock.getHistoriesClient()).thenReturn(historiesClientMock); Mockito.when(galaxyInstanceMock.getToolsClient()).thenReturn(toolsClientMock); Mockito.when(historiesClientMock.create(Mockito.any(History.class))).thenReturn(historyMock); Mockito.when(historyMock.getId()).thenReturn(historyId); Mockito.when(galaxyWorkflowMock.getAllInputValues()).thenReturn(inputValues); Mockito.when(toolsClientMock.uploadRequest(Mockito.any(ToolsClient.FileUploadRequest.class))) .thenReturn(clientResponse1, clientResponse2); Mockito.when(clientResponse1.getStatus()).thenReturn(HttpStatus.SC_OK); Mockito.when(clientResponse2.getStatus()).thenReturn(HttpStatus.SC_INSUFFICIENT_STORAGE); Mockito.when(historiesClientMock.showHistory(historyId)).thenReturn(historyDetailsMock); Mockito.when(historyDetailsMock.getStateIds()).thenReturn(stateIds); Mockito.when(workflowsClientMock.runWorkflow(Mockito.any(WorkflowInputs.class))) .thenReturn(workflowOutputsMock); Mockito.when(workflowOutputsMock.getHistoryId()).thenReturn(historyId); Mockito.when(galaxyWorkflowMock.getName()).thenReturn(workflowName); Mockito.when(workflowsClientMock.getWorkflows()).thenReturn(ImmutableList.of(blend4jWorkflow)); Mockito.when(workflowsClientMock.showWorkflow(Mockito.eq(workflowId))).thenReturn(workflowDetailsMock); Mockito.when(galaxyWorkflowMock.getAllInputEntries()).thenReturn(inputEntries); Mockito.when(workflowDetailsMock.getInputs()).thenReturn(inputDefinitionMap); Mockito.when(galaxyWorkflowMock.getParameters()).thenReturn(parameters); Mockito.when(workflowDetailsMock.getSteps()).thenReturn(workflowSteps); final List<String> workflowOutputIds = getWorkflowOutputIds(outputIdCount, normalOutputIdOrder, outputId1, outputId2); Mockito.when(workflowOutputsMock.getOutputIds()).thenReturn(workflowOutputIds); final List<HistoryContents> historyContentsList = getHistoryContentsList(workflowOutputIds); Mockito.when(historiesClientMock.showHistoryContents(Mockito.eq(historyId))) .thenReturn(historyContentsList); Mockito.when(galaxyWorkflowMock.getAutomaticDownload()).thenReturn(automaticDownload); if (automaticDownload) { Mockito.when(historiesClientMock.showDataset(Mockito.eq(historyId), Mockito.eq(outputId1))) .thenReturn(datasetMock1); Mockito.when(datasetMock1.getDataType()).thenReturn(GalaxyWorkflowEngine.FILE_TYPE_TABULAR); Mockito.when(historiesClientMock.showDataset(Mockito.eq(historyId), Mockito.eq(outputId2))) .thenReturn(datasetMock2); Mockito.when(datasetMock2.getDataType()).thenReturn(GalaxyWorkflowEngine.FILE_TYPE_TEXT); } final Answer<Boolean> downloadDatasetAnswer = new Answer<Boolean>() { @Override public Boolean answer(final InvocationOnMock invocationOnMock) throws Throwable { final int datasetIdArgumentIndex = 3; final File outputFile = new File(GalaxyWorkflowEngine.OUTPUT_FILE_PATH); if (outputId2.equals(invocationOnMock.getArguments()[datasetIdArgumentIndex])) { if (outputFile.exists()) assertTrue(outputFile.delete()); } else { if (!outputFile.exists()) FileUtils.createFile(outputFile.getAbsolutePath(), "GalaxyWorkflowEngineTest.testRunWorkflow"); } return true; } }; Mockito.when(historyUtilsMock.downloadDataset(Mockito.eq(galaxyInstanceMock), Mockito.eq(historiesClientMock), Mockito.eq(historyId), Mockito.anyString(), Mockito.eq(GalaxyWorkflowEngine.OUTPUT_FILE_PATH))).thenAnswer(downloadDatasetAnswer); final GalaxyWorkflowEngine galaxyWorkflowEngine = new GalaxyWorkflowEngine(galaxyInstanceMock, historyId, historyUtilsMock); // Set all timers to zero to make the test as quick as possible. galaxyWorkflowEngine.setWaitTimers(0, 0, 0); // Downloading fails, so we expect the result to be false if automaticDownload is true and true otherwise. final boolean expectedResult = historyReady && (!automaticDownload || outputIdCount == 0); assertEquals(expectedResult, galaxyWorkflowEngine.runWorkflow(galaxyWorkflowMock)); } /** * Get the workflow output IDs for a specific test scenario. * * @param outputIdCount the number of output IDs to return. * @param normalOutputIdOrder whether to use normal or reversed order. * @param outputId1 the first output ID. * @param outputId2 the second output ID. * @return the workflow output IDs. */ private List<String> getWorkflowOutputIds(final int outputIdCount, final boolean normalOutputIdOrder, final String outputId1, final String outputId2) { final List<String> workflowOutputIds; if (outputIdCount == 0) workflowOutputIds = new ArrayList<>(); else if (outputIdCount == 1) workflowOutputIds = ImmutableList.of(normalOutputIdOrder ? outputId1 : outputId2); else { if (normalOutputIdOrder) workflowOutputIds = ImmutableList.of(outputId1, outputId2); else workflowOutputIds = ImmutableList.of(outputId2, outputId1); } return workflowOutputIds; } /** * Get the history contents list that corresponds to the workflow output IDs. * * @param workflowOutputIds the workflow output IDs. * @return the history contents list. */ private List<HistoryContents> getHistoryContentsList(final List<String> workflowOutputIds) { final List<HistoryContents> historyContentsList = new ArrayList<>(); for (final String workflowOutputId : workflowOutputIds) { final HistoryContents historyContents = new HistoryContents(); historyContents.setHid(workflowOutputId.hashCode()); historyContents.setName("name-for-" + workflowOutputId); historyContentsList.add(historyContents); } return historyContentsList; } /** * Test the downloadOutputFile method with invalid input. * * @throws IOException if a local file could not be created. */ @Test public void testDownloadOutputFile() throws IOException, NoSuchFieldException, IllegalAccessException { final String historyId = "history-id"; final String outputId = "output-id"; final GalaxyInstance galaxyInstanceMock = Mockito.mock(GalaxyInstance.class); final HistoriesClient historiesClientMock = Mockito.mock(HistoriesClient.class); final Dataset datasetMock = Mockito.mock(Dataset.class); final HistoryUtils historyUtilsMock = Mockito.mock(HistoryUtils.class); Mockito.when(galaxyInstanceMock.getHistoriesClient()).thenReturn(historiesClientMock); Mockito.when(historiesClientMock.showDataset(Mockito.eq(historyId), Mockito.eq(outputId))) .thenReturn(datasetMock); final GalaxyWorkflowEngine galaxyWorkflowEngine = new GalaxyWorkflowEngine(galaxyInstanceMock, historyId, historyUtilsMock); final Workflow workflow = galaxyWorkflowEngine.getWorkflow("workflow-name"); assertFalse(galaxyWorkflowEngine.downloadOutputFile(workflow, outputId)); } /** * Test the getOutputIdForOutputName method. */ @Test public void testGetOutputIdForOutputName() { final GalaxyWorkflowEngine galaxyWorkflowEngine = new GalaxyWorkflowEngine(null, null, null); assertNull(galaxyWorkflowEngine.getOutputIdForOutputName(null)); } /** * Test the runWorkflow method with a null Galaxy instance. */ @Test public void testRunWorkflowGalaxyNull() throws IOException, InterruptedException { final GalaxyWorkflowEngine galaxyWorkflowEngine = new GalaxyWorkflowEngine(null, null, null); assertFalse(galaxyWorkflowEngine.runWorkflow(null)); } }