All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.exadatum.xsuite.xmaven.bash.test.BashUnitMojo Maven / Gradle / Ivy

Go to download

Bash Maven Plugin is used to generate documentation as well as to run unit test for bash scripts.

The newest version!
package com.exadatum.xsuite.xmaven.bash.test;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.maven.shared.filtering.MavenFilteringException;
import org.apache.maven.shared.filtering.MavenResourcesExecution;
import org.apache.maven.shared.filtering.MavenResourcesFiltering;
import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
import org.junit.runner.Description;
import org.junit.runner.notification.Failure;

/*-
 * #%L
 * Bash Unit Test Plugin
 * %%
 * Copyright (C) 2016 - 2017 Exadatum Software Services Pvt. Ltd.
 * %%
 * Licensed 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.
 * #L%
 */

import com.exadatum.xsuit.xmaven.RunListenerDelegate;

/**
 * Bash Maven Plugin.
 */
@Mojo(name = "test")
public class BashUnitMojo extends AbstractMojo {

  /**
   * Test case file prefix.
   */
  protected static final String BASH_SCRIPT_TEST_FILE_PREFIX = "test-";
  /**
   * Skip execution of all the tests.
   */
  @Parameter(property = "skipTests", defaultValue = "false")
  private boolean skipTests;
  /**
   * Skip execution of all the tests.
   */
  @Parameter(property = "maven.test.skip", defaultValue = "false")
  private boolean mavenSkipTests;

  /**
   * Maven resource filtering component.
   */
  @Component(role = MavenResourcesFiltering.class, hint = "default")
  private MavenResourcesFiltering mavenResourcesFiltering;

  /**
   * Maven project instance.
   */
  @Component
  private MavenProject mavenProject;

  /**
   * Maven session instance.
   */
  @Component
  private MavenSession mavenSession;

  /**
   * Files that has various environment variables declared.
   */
  @Parameter
  private String envVariableFiles;

  /**
   * Directory where all bash scripts are stored.
   */
  @Parameter
  private String scriptsSrcDirectory = "src/main/bin";

  /**
   * Directory where all tests are stored.
   */
  @Parameter
  private String scriptsTestDirectory = "src/test/bin";

  /**
   * Test shared setup script across all bash tests.
   */
  @Parameter
  private String globalTestSetupScript = "src/test/bin/test-setup.sh";

  /**
   * Test shared cleanup script across all bash tests.
   */
  @Parameter
  private String globalTestCleanupScript = "src/test/bin/test-cleanup.sh";

  /**
   * Bash environment variable file extension.
   */
  @Parameter
  private String envFileExtension = ".sh";

  /**
   * Bash script file extension.
   */
  @Parameter
  private String scriptFileExtension = ".sh";

  /**
   * Directory where test reports are generated.
   */
  @Parameter
  private String reportsDirectory = "target/surefire-reports";

  /**
   * Flag to check if any of the test cases are failed.
   */
  private boolean anyTestFailed;

  /**
   * Comma seperated of JUnit RunListener implementations.
   */
  @Parameter
  private String runListeners = "com.exadatum.xsuit.xmaven.AntXmlRunListener";

  /**
   * Delegate used to send JUnit RunListener events.
   */
  private RunListenerDelegate runListenerDelegate;

  /**
   * The character encoding scheme to be applied when filtering resources.
   */
  @Parameter(defaultValue = "${project.build.sourceEncoding}")
  private String encoding = "utf-8";

  /**
   * The output directory into which to copy the resources if filtering is used.
   */
  @Parameter(defaultValue = "${project.build.directory}")
  private File outputDirectory;

  /**
   * Resources to be copied to the output directory. It is provided to to
   * support resource filtering with property substitution.
   */
  @Parameter
  private List resources = new ArrayList();

  /**
   * Additional properties to be used at the time of resource filtering.
   */
  @Parameter
  private Properties properties;

  /**
   *
   * @param destination
   *          File path
   * @return Buffered output stream for file
   * @throws FileNotFoundException
   *           if file not exists
   */
  private static BufferedOutputStream createAppendableStream(
      final File destination) throws FileNotFoundException {
    return new BufferedOutputStream(new FileOutputStream(destination, true));
  }

  /**
   * Execute.
   *
   * @throws MojoExecutionException
   *           the mojo execution exception
   * @throws MojoFailureException
   *           the mojo failure exception
   */
  @Override
  public void execute() throws MojoExecutionException, MojoFailureException {

    try {
      if (skipTests || mavenSkipTests) {
        return;
      }
      generateResources();
      System.setProperty("reportsDirectory", reportsDirectory);
      runListenerDelegate = new RunListenerDelegate(runListeners.split(","));
      Description description = Description
          .createSuiteDescription(mavenProject.getArtifactId());
      runListenerDelegate.testRunStarted(description);
      runBashUnitTests();
      runListenerDelegate.testRunFinished(null);
    } catch (Exception e) {
      throw new MojoExecutionException("Failed to execute pig unit tests", e);
    }
    if (anyTestFailed) {
      throw new MojoFailureException("There are test failures");
    }
  }

  /**
   *
   * @throws MavenFilteringException
   *           if not able to filter resource
   * @throws ComponentLookupException
   *           if no resources are fetched
   */
  private void generateResources()
      throws MavenFilteringException, ComponentLookupException {
    if (resources.isEmpty()) {
      return;
    }

    MavenResourcesExecution mavenResourcesExecution = new MavenResourcesExecution();
    // mavenResourcesFiltering.enableLogging(logger);
    mavenResourcesExecution.setResources(resources);
    mavenResourcesExecution.setMavenProject(mavenProject);
    mavenResourcesExecution.setMavenSession(mavenSession);
    mavenResourcesExecution.setOutputDirectory(outputDirectory);
    mavenResourcesExecution.setEncoding(encoding);
    mavenResourcesExecution.setUseDefaultFilterWrappers(true);
    mavenResourcesExecution.setFileFilters(new ArrayList());
    if (properties != null) {
      mavenResourcesExecution.setAdditionalProperties(properties);
    }
    mavenResourcesFiltering.filterResources(mavenResourcesExecution);
  }

  /**
   * Gets the maven project.
   *
   * @return the maven project
   */
  MavenProject getMavenProject() {
    return mavenProject;
  }

  /**
   * Sets the maven project.
   *
   * @param mavenProject
   *          the new maven project
   */
  void setMavenProject(final MavenProject mavenProject) {
    this.mavenProject = mavenProject;
  }

  /**
   * Gets the maven session.
   *
   * @return the maven session
   */
  MavenSession getMavenSession() {
    return mavenSession;
  }

  /**
   * Sets the maven session.
   *
   * @param mavenSession
   *          the new maven session
   */
  void setMavenSession(final MavenSession mavenSession) {
    this.mavenSession = mavenSession;
  }

  /**
   *
   * @param bashScript
   *          Bash script
   * @param bashScriptTestsDirectory
   *          bash script test directory
   * @throws Exception
   *           if not able to run bash script
   */
  void runBashScriptAllTests(final File bashScript,
      final File bashScriptTestsDirectory) throws Exception {

    File[] bashTests = bashScriptTestsDirectory.listFiles(new FileFilter() {
      @Override
      public boolean accept(final File path) {
        return path.isFile()
            && path.getName().startsWith(BASH_SCRIPT_TEST_FILE_PREFIX);
      }
    });

    File scriptsTestOutputFolder = new File(
        mavenProject.getBuild().getDirectory(), "test");
    scriptsTestOutputFolder.mkdirs();
    File scriptTestOutputFolder = new File(scriptsTestOutputFolder,
        bashScript.getName());
    if (scriptTestOutputFolder.exists()) {
      boolean result = scriptTestOutputFolder.delete();
      if (!result) {
        throw new IllegalStateException("Failed to delete directory "
            + scriptTestOutputFolder.getAbsolutePath());
      }
    }
    scriptTestOutputFolder.mkdirs();
    for (int i = 0; i < bashTests.length; i++) {
      File tempMergedScriptTestFile = new File(scriptTestOutputFolder,
          bashTests[i].getName());
      tempMergedScriptTestFile.setExecutable(true);
      BufferedOutputStream outputStream = createAppendableStream(
          tempMergedScriptTestFile);
      globalSetup(outputStream);
      runBashScriptSingleTest(bashScript, bashTests[i], outputStream,
          tempMergedScriptTestFile);
      globalTearDown(outputStream);
      outputStream.close();
      tempMergedScriptTestFile.setExecutable(true);
      executeBashScriptTest(bashScript, tempMergedScriptTestFile);
    }

  }

  /**
   *
   * @param bashScript
   *          Bash script
   * @param tempMergedScriptTestFile
   *          test merged script file
   * @throws Exception
   *           if not able to execute
   */
  private void executeBashScriptTest(final File bashScript,
      final File tempMergedScriptTestFile) throws Exception {
    ProcessBuilder builder = new ProcessBuilder()
        .command("/bin/bash", "-c",
            tempMergedScriptTestFile.getAbsolutePath())
        .redirectErrorStream(true);
    Process process = builder.start();
    InputStream inputStream = process.getInputStream();
    BufferedReader bufferedReader = new BufferedReader(
        new InputStreamReader(inputStream));
    String line = bufferedReader.readLine();
    while (line != null) {
      if (line.startsWith("TEST_RESULT=")) {
        String[] tokens = line.split("=");
        String[] testResultTokens = tokens[1].split("_####_");
        Description testDescription = Description
            .createTestDescription(bashScript.getName(), testResultTokens[2]);
        runListenerDelegate.testStarted(testDescription);
        if (testResultTokens[0].equals("FAILED")) {
          anyTestFailed = true;
          Failure failure = new Failure(testDescription,
              new AssertionError(testResultTokens[1]));
          runListenerDelegate.testFailure(failure);
        } else if (testResultTokens[0].equals("UNEXPECTED_EXIT")) {
          Failure failure = new Failure(testDescription,
              new AssertionError("Unexpected exit"));
          runListenerDelegate.testFailure(failure);
          anyTestFailed = true;
        } else if (testResultTokens[0].equals("SUCCESSFUL")) {
          System.out.println("Nothing to do");
        } else {
          throw new IllegalArgumentException(
              "Unknown test result " + testResultTokens[0]);
        }
        runListenerDelegate.testFinished(testDescription);
      } else {
        System.out.println(line);
      }
      line = bufferedReader.readLine();
    }
  }

  /**
   *
   * @param outputStream
   *          Outputstream instance
   * @throws Exception
   *           if setting up failed
   */
  private void globalSetup(final OutputStream outputStream) throws Exception {

    outputStream.write(("\n#START Test Framework\n").getBytes());
    InputStream inputStream = BashUnitMojo.class.getClassLoader()
        .getResourceAsStream("test-framework.sh");
    IOUtils.copy(inputStream, outputStream);
    outputStream.write(("\n#END Test Framework\n").getBytes());

    outputStream
        .write(("\n#START Global Environment Setup File\n").getBytes());
    if (new File(globalTestSetupScript).isFile()) {
      IOUtils.copy(new FileInputStream(globalTestSetupScript), outputStream);
    } else {
      outputStream
          .write(("\n#END No Environment Setup File found\n").getBytes());
    }
    outputStream.write(("\n#END Global Environment Setup File\n").getBytes());

    if (envVariableFiles != null) {
      String[] envVariableFilePaths = envVariableFiles.split(",");
      outputStream
          .write(("\n#START Environment Variable Files\n").getBytes());
      for (int i = 0; i < envVariableFilePaths.length; i++) {
        outputStream.write(
            ("\n#START => " + envVariableFilePaths[i] + "\n").getBytes());
        IOUtils.copy(new FileInputStream(envVariableFilePaths[i]),
            outputStream);
        outputStream.write(
            ("\n#END => " + envVariableFilePaths[i] + "\n").getBytes());
      }
      outputStream.write(("\n#END Environment Variable Files\n").getBytes());
    }

  }

  /**
   *
   * @param outputStream
   *          Outputstream
   * @throws Exception
   *           if not able to complete
   */
  private void globalTearDown(final OutputStream outputStream)
      throws Exception {
    outputStream
        .write(("\n#START Global Environment Cleanup File\n").getBytes());
    if (new File(globalTestCleanupScript).isFile()) {
      IOUtils.copy(new FileInputStream(globalTestCleanupScript),
          outputStream);
    } else {
      outputStream
          .write(("\n#END No Environment cleanup file found\n").getBytes());
    }
    outputStream
        .write(("\n#END Global Environment Cleanup File\n").getBytes());

  }

  /**
   *
   * @param bashScript
   *          Bash script
   * @param bashScriptTestFile
   *          Bash script test file
   * @param outputStream
   *          output stream
   * @param tempMergedScriptTestFile
   *          test merged script test file
   * @throws Exception
   *           if not able to run bash script
   */
  void runBashScriptSingleTest(final File bashScript,
      final File bashScriptTestFile, final BufferedOutputStream outputStream,
      final File tempMergedScriptTestFile) throws Exception {

    outputStream.write(
        ("\n#START => " + bashScript.getAbsolutePath() + "\n").getBytes());
    IOUtils.copy(new FileInputStream(bashScript), outputStream);
    outputStream.write(
        ("\n#End => " + bashScript.getAbsolutePath() + "\n").getBytes());

    outputStream
        .write(("\n#START => " + bashScriptTestFile.getAbsolutePath() + "\n")
            .getBytes());
    IOUtils.copy(new FileInputStream(bashScriptTestFile), outputStream);
    outputStream
        .write(("\n#End => " + bashScriptTestFile.getAbsolutePath() + "\n")
            .getBytes());
  }

  /**
   * Run pig unit tests.
   *
   * @throws Exception
   *           the exception
   */
  void runBashUnitTests() throws Exception {
    File basedir = mavenProject.getBasedir();
    File testResourcesDir = new File(basedir, scriptsTestDirectory);
    if (testResourcesDir.exists()) {
      File[] scriptTestsDirs = testResourcesDir.listFiles(new FileFilter() {
        @Override
        public boolean accept(final File path) {
          return path.isDirectory()
              && path.getName().endsWith(scriptFileExtension);
        }
      });

      for (int i = 0; i < scriptTestsDirs.length; i++) {
        File script = new File(scriptsSrcDirectory,
            scriptTestsDirs[i].getName());
        runBashScriptAllTests(script, scriptTestsDirs[i]);
      }
    }

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy