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.

There is a newer version: 1.0.7
Show newest version
package com.exadatum.xsuite.xmaven.bash.test;

/*-
 * #%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 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;

import com.exadatum.xsuite.xmaven.bash.test.RunListenerDelegate;

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

	protected static final String BASH_SCRIPT_TEST_FILE_PREFIX = "test_";

	@Component
	private MavenProject mavenProject;

	@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";

	/**
	 * Skip execution of all the tests
	 */
	@Parameter(property = "skipTests", defaultValue = "false")
	protected boolean skipTests;

	/**
	 * Skip execution of all the tests
	 */
	@Parameter(property = "maven.test.skip", defaultValue = "false")
	protected boolean mavenSkipTests;

	/**
	 * 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.sensorium.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();

	@Component(role = MavenResourcesFiltering.class, hint = "default")
	protected MavenResourcesFiltering mavenResourcesFiltering;

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

	/**
	 * 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");
		}
	}

	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;
	}

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

	void runBashScriptAllTests(File bashScript, File bashScriptTestsDirectory)
			throws Exception {

		File[] bashTests = bashScriptTestsDirectory.listFiles(new FileFilter() {
			@Override
			public boolean accept(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);
		}

	}

	private void executeBashScriptTest(File bashScript,
			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")) {
					// nothing to do.
				} else {
					throw new IllegalArgumentException("Unknown test result "
							+ testResultTokens[0]);
				}
				runListenerDelegate.testFinished(testDescription);
			} else {
				System.out.println(line);
			}
			line = bufferedReader.readLine();
		}
	}

	private static BufferedOutputStream createAppendableStream(File destination)
			throws FileNotFoundException {
		return new BufferedOutputStream(new FileOutputStream(destination, true));
	}

	/**
	 * Test global setup.
	 *
	 * @param pigScriptTestsDirectory
	 *            the pig script tests directory
	 * @param bashTests
	 * @param bashScript
	 * @throws Exception
	 *             the exception
	 */
	private void globalSetup(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());
		}

	}

	private void globalTearDown(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());

	}

	void runBashScriptSingleTest(File bashScript, File bashScriptTestFie,
			BufferedOutputStream outputStream, 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 => "
				+ bashScriptTestFie.getAbsolutePath() + "\n").getBytes());
		IOUtils.copy(new FileInputStream(bashScriptTestFie), outputStream);
		outputStream
				.write(("\n#End => " + bashScriptTestFie.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(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]);
			}
		}

	}

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

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

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy