org.apache.taverna.commandline.TavernaCommandLineTest.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.taverna.commandline.TavernaCommandLineTest.java

Source

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.taverna.commandline;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URI;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.comparator.NameFileComparator;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.apache.taverna.commandline.WorkflowTestSuite.Workflows;
import org.apache.taverna.scufl2.api.container.WorkflowBundle;
import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
import org.apache.taverna.scufl2.rdfxml.RDFXMLReader;

/**
 * Regression tests for Taverna Command-line Tool.
 */
@RunWith(WorkflowTestSuite.class)
public class TavernaCommandLineTest {

    private static String baseVersion = "2.4.0";
    private static boolean baseVersionReleased = true;

    private static String testVersion = "3.0.1-SNAPSHOT";
    private static boolean testVersionReleased = false;
    private static boolean testVersionSupportsScufl2 = true;

    private static String script = "executeworkflow.sh";
    private static String baseName = "taverna-commandline-" + baseVersion;
    private static String testName = "taverna-command-line-" + testVersion;
    private static String releasedLocation = "https://launchpad.net/taverna/t2/";
    private static String unreleasedLocation = "http://build.mygrid.org.uk/ci/job/t3-taverna-commandline-product/lastSuccessfulBuild/net.sf.taverna.t2$taverna-commandline/artifact/net.sf.taverna.t2/taverna-commandline/";

    private static String baseVersionLocation = (baseVersionReleased ? releasedLocation : unreleasedLocation)
            + baseVersion + "/+download/" + baseName + ".zip";
    private static String testVersionLocation = (testVersionReleased ? releasedLocation : unreleasedLocation)
            + testVersion + "/" + testName + (testVersionReleased ? ".zip" : "-bin.zip");

    private static String baseCommand;
    private static String testCommand;

    private static File buildDirectory;

    private File workflowDirectory;
    private File baseOutput;
    private File testOutput;
    private boolean secure;
    private List<File> inputs;
    private String ignorePort;
    private String message;

    public TavernaCommandLineTest(File workflowDirectory) throws Exception {
        this.workflowDirectory = workflowDirectory;
        if (buildDirectory == null) {
            String buildDirectoryLocation = System.getProperty("buildDirectory");
            if (buildDirectoryLocation == null) {
                buildDirectoryLocation = System.getProperty("user.dir") + System.getProperty("file.separator")
                        + "target";
            }
            buildDirectory = new File(buildDirectoryLocation);
            buildDirectory.mkdirs();
        }
        if (baseCommand == null) {
            File commandDirectory = new File(buildDirectory, baseName);
            if (!commandDirectory.exists()) {
                System.out.println("Fetching " + baseName);
                fetchTaverna(baseVersionLocation, baseName);
            }
            baseCommand = new File(baseName, script).getPath();
        }
        if (testCommand == null) {
            File commandDirectory = new File(buildDirectory, testName);
            if (!commandDirectory.exists()) {
                System.out.println("Fetching " + testName);
                fetchTaverna(testVersionLocation, testName);
            }
            testCommand = new File(testName, script).getPath();
        }
        File outputsDirectory = new File(buildDirectory, "test-outputs");
        baseOutput = new File(outputsDirectory, workflowDirectory.getName() + "-" + baseVersion);
        testOutput = new File(outputsDirectory, workflowDirectory.getName() + "-" + testVersion);
        secure = workflowDirectory.getName().startsWith("secure");
        inputs = getInputs();
        ignorePort = getIgnorePort();
        message = "Running {0} with version {1}";
    }

    @Workflows
    public static List<File> workflows() {
        List<File> workflows = new ArrayList<File>();
        for (File workflowDirectory : getResources("workflows")) {
            workflows.add(workflowDirectory);
        }
        for (File workflowDirectory : getResources("myexperiment")) {
            workflows.add(workflowDirectory);
        }
        return workflows;
    }

    @Before
    public void setup() throws Exception {
        if (!baseOutput.exists()) {
            if (baseVersion.equals("2.3.0") && workflowDirectory.getName().equals("tool"))
                return;// version 2.3.0 is missing tool plugin
            String workflow = getWorkflow().toASCIIString();
            System.out.println(MessageFormat.format(message, workflow, baseVersion)
                    + (inputs.size() > 0 ? " using input values" : ""));
            runWorkflow(baseCommand, workflow, baseOutput, true, secure, false);
            assertTrue(String.format("No output produced for %s", workflowDirectory.getName()),
                    baseOutput.exists());
        }
    }

    public boolean testExcluded() {
        // version 3.0.0 is missing biomoby activity
        if (testVersion.startsWith("3.") && workflowDirectory.getName().contains("biomoby"))
            return true;
        // version 3.0.0 is missing tool activity
        if (testVersion.startsWith("3.")
                && workflowDirectory.getName().equals("unix_external_tools_with_zip_and_unzip"))
            return true;
        if (testVersion.startsWith("3.")
                && workflowDirectory.getName().equals("unix_numerically_adding_two_values"))
            return true;
        if (testVersion.startsWith("3.")
                && workflowDirectory.getName().equals("unix_tool_service_using_string_replacement"))
            return true;
        // version 3.0.0 is missing looping configuration
        if (testVersion.startsWith("3.") && workflowDirectory.getName().equals("ebi_interproscan_newservices"))
            return true;
        if (testVersion.startsWith("3.") && workflowDirectory.getName().equals("biomartandembossanalysis"))
            return true;
        return false;
    }

    @Test
    public void testWorkflowWithoutInputs() throws Exception {
        assumeTrue(!testExcluded());
        assumeTrue(baseOutput.exists());
        assumeTrue(inputs.isEmpty());
        FileUtils.deleteDirectory(testOutput);
        String workflow = getWorkflow().toASCIIString();
        System.out.println(MessageFormat.format(message, workflow, testVersion));
        runWorkflow(testCommand, workflow, testOutput, true, secure, false);
        assertTrue(String.format("No output produced for %s", workflowDirectory.getName()), testOutput.exists());
        assertOutputsEquals(baseOutput, testOutput);
    }

    @Test
    public void testWorkflowWithInputValues() throws Exception {
        assumeTrue(!testExcluded());
        assumeTrue(baseOutput.exists());
        assumeTrue(inputs.size() > 0);
        FileUtils.deleteDirectory(testOutput);
        String workflow = getWorkflow().toASCIIString();
        System.out.println(MessageFormat.format(message, workflow, testVersion) + " using input values");
        runWorkflow(testCommand, workflow, testOutput, true, secure, false);
        assertTrue(String.format("No output produced for %s", workflowDirectory.getName()), testOutput.exists());
        assertOutputsEquals(baseOutput, testOutput);
    }

    @Test
    public void testWorkflowWithInputFiles() throws Exception {
        assumeTrue(!testExcluded());
        assumeTrue(baseOutput.exists());
        assumeTrue(inputs.size() > 0);
        FileUtils.deleteDirectory(testOutput);
        String workflow = getWorkflow().toASCIIString();
        System.out.println(MessageFormat.format(message, workflow, testVersion) + " using input files");
        runWorkflow(testCommand, workflow, testOutput, false, secure, false);
        assertTrue(String.format("No output produced for %s", workflowDirectory.getName()), testOutput.exists());
        assertOutputsEquals(baseOutput, testOutput);
    }

    @Test
    @Ignore
    public void testWorkflowWithDatabase() throws Exception {
        assumeTrue(!testExcluded());
        assumeTrue(baseOutput.exists());
        assumeTrue(inputs.size() > 0);
        FileUtils.deleteDirectory(testOutput);
        String workflow = getWorkflow().toASCIIString();
        System.out.println(MessageFormat.format(message, workflow, testVersion) + " using database");
        runWorkflow(testCommand, workflow, testOutput, true, secure, true);
        assertTrue(String.format("No output produced for %s", workflowDirectory.getName()), testOutput.exists());
        assertOutputsEquals(baseOutput, testOutput);
    }

    @Test
    public void testScufl2Workflow() throws Exception {
        assumeTrue(!testExcluded());
        assumeTrue(baseOutput.exists());
        assumeTrue(testVersionSupportsScufl2);

        FileUtils.deleteDirectory(testOutput);
        String workflow = getScufl2Workflow().toASCIIString();
        System.out.println(MessageFormat.format(message, workflow, testVersion)
                + (inputs.size() > 0 ? " using input values" : ""));
        runWorkflow(testCommand, workflow, testOutput, true, secure, true);
        assertTrue(String.format("No output produced for %s", workflowDirectory.getName()), testOutput.exists());
        assertOutputsEquals(baseOutput, testOutput);
    }

    private synchronized void runWorkflow(String command, String workflow, File outputsDirectory,
            boolean inputValues, boolean secure, boolean database) throws Exception {
        ProcessBuilder processBuilder = new ProcessBuilder("sh", command);
        processBuilder.redirectErrorStream(true);
        processBuilder.directory(buildDirectory);
        List<String> args = processBuilder.command();
        for (File input : inputs) {
            if (inputValues) {
                args.add("-inputvalue");
                args.add(input.getName());
                args.add(IOUtils.toString(new FileReader(input)));
            } else {
                args.add("-inputfile");
                args.add(input.getName());
                args.add(input.getAbsolutePath());
            }
        }
        args.add("-outputdir");
        args.add(outputsDirectory.getPath());
        if (secure) {
            args.add("-cmdir");
            args.add(getClass().getResource("/security").getFile());
            args.add("-cmpassword");
        }
        if (database) {
            args.add("-embedded");
        }
        args.add(workflow);
        Process process = processBuilder.start();
        if (secure) {
            PrintStream outputStream = new PrintStream(process.getOutputStream());
            outputStream.println("test");
            outputStream.flush();
        }
        waitFor(process);
    }

    private URI getWorkflow() throws Exception {
        File workflow = new File(workflowDirectory, workflowDirectory.getName() + ".t2flow");
        if (!workflow.exists()) {
            workflow = new File(workflowDirectory, workflowDirectory.getName() + ".url");
            return new URI(IOUtils.toString(new FileReader(workflow)));
        }
        return workflow.toURI();
    }

    private URI getScufl2Workflow() throws Exception {
        File workflow = new File(buildDirectory, workflowDirectory.getName() + ".wfbundle");
        // if (!workflow.exists()) {
        WorkflowBundleIO workflowBundleIO = new WorkflowBundleIO();
        WorkflowBundle bundle = workflowBundleIO.readBundle(getWorkflow().toURL(), null);
        workflowBundleIO.writeBundle(bundle, workflow, RDFXMLReader.APPLICATION_VND_TAVERNA_SCUFL2_WORKFLOW_BUNDLE);
        // }
        return workflow.toURI();
    }

    private synchronized int waitFor(Process process) throws IOException {
        while (true) {
            try {
                wait(500);
            } catch (InterruptedException e) {
            }
            IOUtils.copy(process.getInputStream(), System.out);
            try {
                return process.exitValue();
            } catch (IllegalThreadStateException e) {
            }
        }
    }

    private void assertOutputsEquals(File directory1, File directory2) {
        File[] directory1Files = directory1.listFiles();
        File[] directory2Files = directory2.listFiles();
        // assert directories contain same number of files
        assertEquals(
                String.format("%s has %s files but %s has %s files", directory1.getName(), directory1Files.length,
                        directory2.getName(), directory2Files.length),
                directory1Files.length, directory2Files.length);
        // sort files in directory
        Arrays.sort(directory1Files, NameFileComparator.NAME_SYSTEM_COMPARATOR);
        Arrays.sort(directory2Files, NameFileComparator.NAME_SYSTEM_COMPARATOR);
        for (int i = 0; i < directory1Files.length; i++) {
            assertFilesEqual(directory1Files[i], directory2Files[i],
                    !directory1Files[i].getName().equals(ignorePort));
        }
    }

    private void assertDirectoriesEquals(File directory1, File directory2, boolean checkFileContents) {
        if (directory1.exists()) {
            assertTrue(String.format("%s exists but %s does not", directory1, directory2), directory2.exists());
        } else {
            assertFalse(String.format("%s does not exists but %s does", directory1, directory2),
                    directory2.exists());
        }
        File[] directory1Files = directory1.listFiles();
        File[] directory2Files = directory2.listFiles();
        // assert directories contain same number of files
        assertEquals(
                String.format("%s has %s files but %s has %s files", directory1.getName(), directory1Files.length,
                        directory2.getName(), directory2Files.length),
                directory1Files.length, directory2Files.length);
        // sort files in directory
        Arrays.sort(directory1Files, NameFileComparator.NAME_SYSTEM_COMPARATOR);
        Arrays.sort(directory2Files, NameFileComparator.NAME_SYSTEM_COMPARATOR);
        for (int i = 0; i < directory1Files.length; i++) {
            assertFilesEqual(directory1Files[i], directory2Files[i], checkFileContents);
        }
    }

    private void assertFilesEqual(File file1, File file2, boolean checkFileContents) {
        if (file1.isHidden()) {
            assertTrue(String.format("%s is hidden but %s is not", file1, file2), file2.isHidden());
        } else {
            assertFalse(String.format("%s is not hidden but %s is", file1, file2), file2.isHidden());
            assertEquals(file1.getName(), file2.getName());
            if (file1.isDirectory()) {
                assertTrue(String.format("%s is a directory but %s is not", file1, file2), file2.isDirectory());
                assertDirectoriesEquals(file1, file2, checkFileContents);
            } else {
                assertFalse(String.format("%s is not a directory but %s is", file1, file2), file2.isDirectory());
                if (isZipFile(file1)) {
                    assertZipFilesEqual(file1, file2);
                } else if (checkFileContents) {
                    assertEquals(String.format("%s is a different length to %s", file1, file2), file1.length(),
                            file2.length());
                    try {
                        byte[] byteArray1 = IOUtils.toByteArray(new FileReader(file1));
                        byte[] byteArray2 = IOUtils.toByteArray(new FileReader(file2));
                        assertArrayEquals(String.format("%s != %s", file1, file2), byteArray1, byteArray2);
                    } catch (FileNotFoundException e) {
                        fail(e.getMessage());
                    } catch (IOException e) {
                        fail(e.getMessage());
                    }
                }
            }
        }
    }

    private void assertZipFilesEqual(File file1, File file2) {
        ZipFile zipFile1 = null;
        ZipFile zipFile2 = null;
        try {
            zipFile1 = new ZipFile(file1);
            zipFile2 = new ZipFile(file2);
        } catch (Exception e) {
            assertTrue(String.format("%s and %s are not both zip files"), zipFile1 == null);
        }
        if (zipFile1 != null && zipFile2 != null) {
            Enumeration<? extends ZipEntry> entries1 = zipFile1.entries();
            Enumeration<? extends ZipEntry> entries2 = zipFile2.entries();
            while (entries1.hasMoreElements()) {
                assertTrue(entries2.hasMoreElements());
                ZipEntry zipEntry1 = entries1.nextElement();
                ZipEntry zipEntry2 = entries2.nextElement();
                assertEquals(String.format("%s and %s are not both directories", zipEntry1, zipEntry2),
                        zipEntry1.isDirectory(), zipEntry2.isDirectory());
                assertEquals(String.format("%s and %s have different names", zipEntry1, zipEntry2),
                        zipEntry1.getName(), zipEntry2.getName());
                assertEquals(String.format("%s and %s have different sizes", zipEntry1, zipEntry2),
                        zipEntry1.getSize(), zipEntry2.getSize());
                try {
                    byte[] byteArray1 = IOUtils.toByteArray(zipFile1.getInputStream(zipEntry1));
                    byte[] byteArray2 = IOUtils.toByteArray(zipFile2.getInputStream(zipEntry2));
                    assertArrayEquals(String.format("%s != %s", zipEntry1, zipEntry2), byteArray1, byteArray2);
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            assertFalse(entries2.hasMoreElements());
        }
    }

    private boolean isZipFile(File file) {
        try {
            new ZipFile(file);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static File[] getResources(String directory) {
        return new File(TavernaCommandLineTest.class.getResource("/" + directory).getFile()).listFiles();
    }

    private List<File> getInputs() {
        File inputsDirectory = new File(workflowDirectory, "inputs");
        if (inputsDirectory.exists() && inputsDirectory.isDirectory()) {
            return Arrays.asList(inputsDirectory.listFiles());
        }
        return Collections.emptyList();
    }

    private String getIgnorePort() throws Exception {
        File ignorePort = new File(workflowDirectory, "ignorePort");
        if (ignorePort.exists()) {
            return IOUtils.toString(new FileReader(ignorePort));
        }
        return "";
    }

    private void fetchTaverna(String location, String name) throws Exception {
        File zipFile = new File(buildDirectory, name + ".zip");
        IOUtils.copy(new URL(location).openStream(), new FileOutputStream(zipFile));
        ProcessBuilder processBuilder = new ProcessBuilder("unzip", "-q", name);
        processBuilder.redirectErrorStream(true);
        processBuilder.directory(buildDirectory);
        System.out.println(processBuilder.command());
        Process process = processBuilder.start();
        waitFor(process);
    }

}