eu.diversify.disco.experiments.testing.Tester.java Source code

Java tutorial

Introduction

Here is the source code for eu.diversify.disco.experiments.testing.Tester.java

Source

/**
 *
 * This file is part of Disco.
 *
 * Disco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Disco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Disco.  If not, see <http://www.gnu.org/licenses/>.
 */
/**
 *
 * This file is part of Disco.
 *
 * Disco is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any
 * later version.
 *
 * Disco is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Disco. If not, see <http://www.gnu.org/licenses/>.
 */
package eu.diversify.disco.experiments.testing;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.io.IOUtils;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;

/**
 * Generic acceptance test for experiments.
 */
public class Tester {

    private final String experimentName;
    private final ArrayList<String> expectedCsvFiles;
    private final ArrayList<String> expectedPdfFiles;

    public Tester(String experimentName, String... expectedFiles) {
        this.experimentName = experimentName;
        this.expectedCsvFiles = new ArrayList<String>();
        this.expectedPdfFiles = new ArrayList<String>();
        for (String file : expectedFiles) {
            final String extension = getExtension(file);
            if (extension.equals(".csv")) {
                expectedCsvFiles.add(file);
            } else if (extension.equals(".pdf")) {
                expectedPdfFiles.add(file);
            } else {
                String message = String.format("Unsupported file extension '%s' (file: %s)", extension, file);
                throw new IllegalArgumentException(message);
            }
        }
    }

    private String getExtension(String file) {
        final Pattern regex = Pattern.compile("[^\\.]+(\\.\\w+)\\s*$");
        final Matcher matcher = regex.matcher(file);
        if (matcher.matches()) {
            return matcher.group(1);
        } else {
            final String message = String.format("Unable to extract extension from '%s'", file);
            throw new IllegalArgumentException(message);
        }
    }

    public List<String> getExpectedCsvFiles() {
        return Collections.unmodifiableList(expectedCsvFiles);
    }

    public List<String> getExpectedPdfFiles() {
        return Collections.unmodifiableList(expectedPdfFiles);
    }

    public void test() throws IOException, InterruptedException {
        unzipDistribution(getDistributionName());
        final Run execution = new Run(getWorkingDirectory(), getRunCommand());
        checkReadMeFile();
        checkLicenseAndCopyrightAreDisplayed(execution);
        checkNoErrorIsReported(execution);
        checkCsvFilesAreGenerated();
        checkPdfAreGenerated();
    }

    private void unzipDistribution(String archiveName) throws IOException {
        String fileName = escape(archiveName);
        ZipFile zipFile = new ZipFile(fileName);
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            if (!entry.isDirectory()) {
                File entryDestination = new File("target/", entry.getName());
                entryDestination.getParentFile().mkdirs();
                InputStream in = zipFile.getInputStream(entry);
                OutputStream out = new FileOutputStream(entryDestination);
                IOUtils.copy(in, out);
                IOUtils.closeQuietly(in);
                IOUtils.closeQuietly(out);
            }
        }
    }

    private void checkReadMeFile() throws IOException {
        File readme = new File(String.format("target/%s/README", experimentName));
        assertThat("readme provided", readme.exists());

        final String content = readContentOf(readme);
        assertThat("is about experiment", content, containsString(experimentName));
        assertThat("explain how to run", content, containsString(getRunCommand()));

    }

    private String readContentOf(File readme) throws IOException {
        final StringBuffer buffer = new StringBuffer();
        for (String line : Files.readAllLines(readme.toPath(), Charset.defaultCharset())) {
            buffer.append(line);
        }
        return buffer.toString();
    }

    private void checkCsvFilesAreGenerated() {
        for (String name : expectedCsvFiles) {
            final String path = String.format("target/%s/%s", experimentName, name);
            File csvFile = new File(path);
            assertThat(path, csvFile.exists());
        }
    }

    private void checkPdfAreGenerated() {
        for (String name : expectedPdfFiles) {
            final String path = String.format("target/%s/%s", experimentName, name);
            File pdfFile = new File(path);
            assertThat(path, pdfFile.exists());
        }
    }

    private void checkNoErrorIsReported(Run execution) {
        assertThat("error reported in stdout!" + execution.summary(), execution.getStandardOutput(),
                not(containsString("Exception")));
        assertThat("error reported in stderr!" + execution.summary(), execution.getStandardError(),
                not(containsString("Exception")));
    }

    private void checkLicenseAndCopyrightAreDisplayed(Run execution) {
        assertThat("copyright displayed", execution.getStandardOutput(),
                containsString("Copyright (C) 2013 SINTEF ICT"));
        assertThat("license displayed", execution.getStandardOutput(), containsString("LGPLv3+"));
    }

    private String escape(String directory) {
        return directory.replaceAll("\"", "");
    }

    public String getDistributionName() {
        return String.format("%s-dist.zip", experimentName);
    }

    public String getWorkingDirectory() {
        return String.format("target/%s", experimentName);
    }

    public String getRunCommand() {
        return String.format("java -jar %s-final.jar", experimentName);
    }

    private static final class Run {

        private final String standardOutput;
        private final String standardError;

        public Run(String directory, String commandLine) throws IOException, InterruptedException {
            ProcessBuilder builder = new ProcessBuilder(commandLine.split("\\s+"));
            builder.directory(new File(directory));
            Process p = builder.start();
            standardOutput = readStandardOutput(p).toString();
            standardError = readStandardError(p).toString();
            p.waitFor();
        }

        public String getStandardOutput() {
            return standardOutput;
        }

        public String getStandardError() {
            return standardError;
        }

        /**
         * @return a string containing the data collected from both the standard
         * output and the standard error
         */
        public String summary() {
            final StringBuilder result = new StringBuilder();

            result.append(EOL);
            result.append(EOL);
            result.append(SEPARATOR).append(EOL);
            result.append("STDOUT:").append(EOL);
            result.append(getStandardOutput());
            result.append(SEPARATOR).append(EOL);
            result.append("STDERR:").append(EOL);
            result.append(getStandardError());

            return result.toString();

        }

        private static final String EOL = System.lineSeparator();
        private static final String SEPARATOR = "------------";

        private StringBuilder readStandardOutput(Process p) throws IOException {
            BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
            StringBuilder output = new StringBuilder();
            String line = null;
            while ((line = stdInput.readLine()) != null) {
                output.append(line).append(EOL);
            }
            return output;
        }

        private StringBuilder readStandardError(Process p) throws IOException {
            BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            StringBuilder error = new StringBuilder();
            String line = "";
            while ((line = stdError.readLine()) != null) {
                error.append(line).append(EOL);
            }
            return error;
        }
    }
}