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

org.bitbucket.bradleysmithllc.etlunit.maven.ETLUnitMojo Maven / Gradle / Ivy

There is a newer version: 4.6.0-eu
Show newest version
package org.bitbucket.bradleysmithllc.etlunit.maven;

/*
 * #%L
 * etlunit-maven
 * %%
 * Copyright (C) 2010 - 2014 bradleysmithllc
 * %%
 * 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 org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.bitbucket.bradleysmithllc.etlunit.*;
import org.bitbucket.bradleysmithllc.etlunit.feature.AbstractFeature;
import org.bitbucket.bradleysmithllc.etlunit.feature.ServiceLocatorFeatureLocator;
import org.bitbucket.bradleysmithllc.etlunit.feature.UserDirectedClassDirectorFeature;
import org.bitbucket.bradleysmithllc.etlunit.feature.debug.ConsoleFeatureModule;
import org.bitbucket.bradleysmithllc.etlunit.feature.debug.RunAllFeatureModule;
import org.bitbucket.bradleysmithllc.etlunit.io.FileBuilder;
import org.bitbucket.bradleysmithllc.etlunit.parser.ETLTestParser;
import org.bitbucket.bradleysmithllc.etlunit.parser.ETLTestValueObject;
import org.bitbucket.bradleysmithllc.etlunit.parser.ParseException;
import org.bitbucket.bradleysmithllc.etlunit.util.IOUtils;
import org.bitbucket.bradleysmithllc.etlunit.util.JSonBuilderProxy;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

/**
 * Goal to run etlunit tests
 *
 * @goal test
 * @phase test
 * @requiresDependencyResolution compile+runtime
 */
public class ETLUnitMojo
	extends AbstractMojo
{
	/**
	 * @parameter expression="${project}" default-value="${project}"
	 */
	protected MavenProject mavenProject;

	/**
	 * @parameter expression="${project.version}" default-value="${project.version}"
	 */
	protected String projectVersion;

	/**
	 * @parameter expression="${project.name}" default-value="${project.name}"
	 */
	protected String projectName;

	/**
	 * @parameter expression="${etlunit.override.configuration}"
	 */
	protected String etlunitOverrideConfiguration;

	/**
	 * @parameter expression="${maven.test.skip}"
	 */
	protected String skip;

	/**
	 * @parameter expression="${skipTests}"
	 */
	protected String skipTests;

	/**
	 * @parameter expression="${etlunit.skipTests}"
	 */
	protected String etlunitSkipTests;

	/**
	 * @parameter expression="${rootDirectory}" default-value="${basedir}"
	 */
	protected File baseDirectory;

	public void execute()
		throws MojoExecutionException
	{
		if (skip != null || skipTests != null || etlunitSkipTests != null)
		{
			// skip testing
			getLog().info("Tests skipped");
			return;
		}

		if (etlunitOverrideConfiguration != null)
		{
			System.setProperty("etlunit.override.configuration", etlunitOverrideConfiguration);
		}
		else
		{
			System.clearProperty("etlunit.override.configuration");
		}

		File src = getEtlunitSourceDirectoryRoot(baseDirectory);

		if (!src.exists())
		{
			src.mkdirs();
		}

		try
		{
			List classpathFiles = mavenProject.getTestClasspathElements();

			URL[] urls = new URL[classpathFiles.size()];

			getLog().debug("" + classpathFiles.size());

			// create a classpath system property that can be used downstream
			StringBuilder builder = new StringBuilder();

			for (int i = 0; i < classpathFiles.size(); ++i)
			{
				getLog().debug((String) classpathFiles.get(i));
				File path = new File((String) classpathFiles.get(i));
				urls[i] = path.toURL();

				if (builder.length() != 0)
				{
					builder.append(File.pathSeparator);
				}

				builder.append(path.getCanonicalPath());
			}

			System.setProperty("etlunit.maven.plugin.classpath", builder.toString());

			URLClassLoader ucl = new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());

			Thread.currentThread().setContextClassLoader(ucl);
			ServiceLocatorFeatureLocator loc = new ServiceLocatorFeatureLocator(ucl);

			Configuration con = loadConfiguration(baseDirectory, projectName, projectVersion, ucl);

			final ETLTestVM vm = new ETLTestVM(loc, con);

			// look for a test specification
			String testSpec = System.getProperty("etlunit-test");

			if (testSpec != null)
			{
				getLog().debug("Using test selector: " + testSpec);
				vm.addFeature(new UserDirectedClassDirectorFeature("maven-test-selector", testSpec));
			}

			// 'activate' the console output
			ConsoleFeatureModule console = new ConsoleFeatureModule();
			vm.addFeature(console);

			// install a dummy feature so a director can be installed which will accept all tests
			vm.addFeature(new RunAllFeatureModule());

			// install a feature to create surefire reports
			vm.addFeature(new AbstractFeature()
			{
				private final StatusReporter statusReporter = new SurefireStatusReporter(vm.getRuntimeSupport().getReportDirectory("surefire"));

				public String getFeatureName()
				{
					return "surefire-reporter";
				}

				@Override
				public long getPriorityLevel()
				{
					return 1L;
				}

				@Override
				public StatusReporter getStatusReporter()
				{
					return statusReporter;
				}
			});

			vm.installFeatures();

			//TEST!
			TestResults results = vm.runTests();

			// clean the temp directory
			getLog().info("Clearing temporary files . . .");
			FileUtils.deleteQuietly(vm.getRuntimeSupport().getTempRoot());

			TestResultMetrics metrics = results.getMetrics();

			if (metrics.getNumberOfErrors() > 0 || metrics.getNumberOfAssertionFailures() > 0)
			{
				throw new MojoExecutionException("Build failed with test errors");
			}

			if (metrics.getNumberOfTestsPassed() == 0)
			{
				throw new MojoExecutionException("Build failed with no tests to run");
			}
		}
		catch (Exception e)
		{
			throw new MojoExecutionException("", e);
		}
	}

	/**
	 * These methods from here on are helpers for other modules which are operating in the maven project model
	 * and want to locate standard artifacts without having to spread that information all around the other modules.
	 *
	 * @return
	 */
	public static File getSourceDirectoryRoot(File project_root)
	{
		return new FileBuilder(project_root).subdir("src").mkdirs().file();
	}

	public static Configuration loadConfiguration(
		File basedir,
		String projectName,
		String projectVersion,
		ClassLoader urlLoader
	) throws IOException
	{
		File src = new File(basedir, "src");
		File main = new File(src, "main");

		File test = new File(src, "test");

		File testResources = new File(test, "resources");
		File mainResources = new File(main, "resources");

		File testCfg = new File(testResources, "config");
		File mainCfg = new File(mainResources, "config");

		final Configuration con;
		try
		{
			ETLTestValueObject base =
				ETLTestParser.loadObject(
					new JSonBuilderProxy()
						.object()
						.key("project-root-directory")
						.value(basedir.getAbsolutePath())
						.key("vendor-binary-directory")
						.value(getBinDirectoryRoot(basedir).getAbsolutePath())
						.key("test-sources-directory")
						.value(getEtlunitSourceDirectoryRoot(basedir))
						.key("generated-source-directory")
						.value(getGeneratedSourceDirectoryRoot(basedir))
						.key("temp-directory")
						.value(getTempDirectoryRoot(basedir))
						.key("reports-directory")
						.value(getReportsDirectoryRoot(basedir))
						.key("resource-directory")
						.value(getResourceDirectory(basedir))
						.key("reference-directory")
						.value(getReferenceDirectory(basedir))
						.key("configuration-directory")
						.value(getConfigurationRoot(basedir))
						.key("project-version")
						.value(projectVersion)
						.key("project-name")
						.value(projectName)
						.key("project-user")
						.value(System.getProperty("user.name"))
						.endObject()
						.toString()
				);

			// split on colon for multiple
			String[] overrides = getUserProfiles();

			// merge together, preferring the override(s)
			con = Configuration.loadFromEnvironment(new File[]{
				mainCfg,
				testCfg
			}, overrides, urlLoader, base);

			// save off the resulting config file for reference
			File configTarget = new FileBuilder(getGeneratedSourceDirectoryRoot(basedir)).subdir("config").mkdirs().name("effective_configuration.json").file();

			IOUtils.writeBufferToFile(configTarget, new StringBuffer(con.getRoot().getJsonNode().toString()));

			return con;
		}
		catch (ParseException e)
		{
			throw new IOException(e);
		}
	}

	public static String[] getUserProfiles()
	{
		String override = getUserProfilesProperty();

		// split on colon for multiple
		return override == null ? new String[]{} : override.split(":");
	}

	public static void setUserProfile(String value)
	{
		setUserProfiles(value == null ? null : value.split(":"));
	}

	public static void setUserProfiles(String[] values)
	{
		if (values != null)
		{
			StringBuilder stb = new StringBuilder();

			boolean first = true;
			for (String value : values)
			{
				if (first)
				{
					first = false;
				}
				else
				{
					stb.append(":");
				}

				stb.append(value);
			}

			System.setProperty("etlunit.override.configuration", stb.toString());
		}
		else
		{
			System.clearProperty("etlunit.override.configuration");
		}
	}

	private static String getUserProfilesProperty()
	{
		return System.getProperty("etlunit.override.configuration");
	}

	protected static File getResourceDirectory(File basedir)
	{
		return getMainDirectory(basedir);
	}

	public static File getEtlunitSourceDirectoryRoot(File basedir)
	{
		return new FileBuilder(getTestDirectory(basedir)).subdir("etlunit").mkdirs().file();
	}

	public static File getBuildDirectoryRoot(File project_root)
	{
		return new FileBuilder(project_root).subdir("target").mkdirs().file();
	}

	public static File getGeneratedSourceDirectoryRoot(File project_root)
	{
		return new FileBuilder(getBuildDirectoryRoot(project_root)).subdir("generated-sources").mkdirs().file();
	}

	public static File getBinDirectoryRoot(File project_root)
	{
		return new FileBuilder(project_root).subdir("target").subdir("etlunit-bin").mkdirs().file();
	}

	public static File getReportsDirectoryRoot(File project_root)
	{
		return new FileBuilder(project_root).subdir("target").mkdirs().file();
	}

	public static File getLibDirectoryRoot(File project_root)
	{
		return new FileBuilder(project_root).subdir("target").subdir("etlunit-lib").mkdirs().file();
	}

	public static File getTempDirectoryRoot(File project_root)
	{
		return new FileBuilder(project_root).subdir("target").subdir("etlunit-temp").mkdirs().file();
	}

	public static File getEtlunitConfiguration(File project_root)
	{
		return new FileBuilder(getConfigurationRoot(project_root)).mkdirs().name("etlunit.json").file();
	}

	public static File getConfigurationRoot(File project_root)
	{
		return new FileBuilder(getTestDirectory(project_root)).subdir("resources").subdir("config").mkdirs().file();
	}

	public static File getFeatureSource(File project_root, String feature)
	{
		return new FileBuilder(getSourceDirectoryRoot(project_root)).subdir("main").subdir(feature).mkdirs().file();
	}

	public static File getMainDirectory(File project_root)
	{
		return new FileBuilder(getSourceDirectoryRoot(project_root)).subdir("main").mkdirs().file();
	}

	public static File getReferenceDirectory(File project_root)
	{
		return new FileBuilder(getMainDirectory(project_root)).subdir("reference").mkdirs().file();
	}

	public static File getTestDirectory(File project_root)
	{
		return new FileBuilder(getSourceDirectoryRoot(project_root)).subdir("test").mkdirs().file();
	}

	public static File getFeatureConfiguration(File project_root, String feature)
	{
		return new FileBuilder(getConfigurationRoot(project_root)).subdir(feature).mkdirs().file();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy