com.exadatum.xsuite.xmaven.bash.test.BashUnitMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bash-maven-plugin Show documentation
Show all versions of bash-maven-plugin Show documentation
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]);
}
}
}
}