package com.simpligility.maven.plugins.android;
import static org.easymock.EasyMock.*;
import java.io.File;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.DebugConfigurationListener;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
import org.apache.maven.plugin.descriptor.MojoDescriptor;
import org.apache.maven.plugin.testing.AbstractMojoTestCase;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.path.DefaultPathTranslator;
import org.apache.maven.project.path.PathTranslator;
import org.codehaus.plexus.component.configurator.ComponentConfigurator;
import org.codehaus.plexus.component.configurator.ConfigurationListener;
import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.logging.console.ConsoleLogger;
import org.junit.Assert;
import org.powermock.reflect.Whitebox;
import com.simpligility.maven.plugins.android.AbstractAndroidMojo;
import com.simpligility.maven.plugins.android.standalonemojos.ManifestUpdateMojo;
import com.simpligility.maven.plugins.android.standalonemojos.MojoProjectStub;
public abstract class AbstractAndroidMojoTestCase<T extends AbstractAndroidMojo> extends AbstractMojoTestCase {
protected MavenSession session;
protected MojoExecution execution;
/**
* The Goal Name of the Plugin being tested.
* <p>
* Used to look for <code><configuration></code> section in the <code>plugin-config.xml</code>
* that will be used to configure the mojo from.
*
* @return the string name of the goal. (eg "version-update", "dex", etc...)
*/
public abstract String getPluginGoalName();
/**
* Copy the project specified into a temporary testing directory. Create the {@link MavenProject} and
* {@link ManifestUpdateMojo}, configure it from the <code>plugin-config.xml</code> and return the created Mojo.
* <p>
* Note: only configuration entries supplied in the plugin-config.xml are presently configured in the mojo returned.
* That means and 'default-value' settings are not automatically injected by this testing framework (or plexus
* underneath that is suppling this functionality)
*
* @param resourceProject
* the name of the goal to look for in the <code>plugin-config.xml</code> that the configuration will be
* pulled from.
* @param resourceProject
* the resourceProject path (in src/test/resources) to find the example/test project.
* @return the created mojo (unexecuted)
* @throws Exception
* if there was a problem creating the mojo.
*/
protected T createMojo(String resourceProject) throws Exception {
// Establish test details project example
String testResourcePath = "src/test/resources/" + resourceProject;
testResourcePath = FilenameUtils.separatorsToSystem(testResourcePath);
File exampleDir = new File(getBasedir(), testResourcePath);
Assert.assertTrue("Path should exist: " + exampleDir, exampleDir.exists());
// Establish the temporary testing directory.
String testingPath = "target/tests/" + this.getClass().getSimpleName() + "." + getName();
testingPath = FilenameUtils.separatorsToSystem(testingPath);
File testingDir = new File(getBasedir(), testingPath);
if (testingDir.exists()) {
FileUtils.cleanDirectory(testingDir);
} else {
Assert.assertTrue("Could not create directory: " + testingDir, testingDir.mkdirs());
}
// Copy project example into temporary testing directory
// to avoid messing up the good source copy, as mojo can change
// the AndroidManifest.xml file.
FileUtils.copyDirectory(exampleDir, testingDir);
// Prepare MavenProject
final MavenProject project = new MojoProjectStub(testingDir);
// Setup Mojo
PlexusConfiguration config = extractPluginConfiguration("android-maven-plugin", project.getFile());
@SuppressWarnings("unchecked")
final T mojo = (T) lookupMojo(getPluginGoalName(), project.getFile());
// Inject project itself
setVariableValueToObject(mojo, "project", project);
// Configure the rest of the pieces via the PluginParameterExpressionEvaluator
// - used for ${plugin.*}
MojoDescriptor mojoDesc = new MojoDescriptor();
// - used for error messages in PluginParameterExpressionEvaluator
mojoDesc.setGoal(getPluginGoalName());
MojoExecution mojoExec = new MojoExecution(mojoDesc);
// - Only needed if we start to use expressions like ${settings.*}, ${localRepository}, ${reactorProjects}
// MavenSession context = null; // Messy to declare, would rather avoid using it.
// - Used for ${basedir} relative paths
PathTranslator pathTranslator = new DefaultPathTranslator();
// - Declared to prevent NPE from logging events in maven core
Logger logger = new ConsoleLogger(Logger.LEVEL_DEBUG, mojo.getClass().getName());
MavenSession context = createNiceMock( MavenSession.class );
expect( context.getExecutionProperties() ).andReturn( project.getProperties() );
expect( context.getCurrentProject() ).andReturn( project );
replay( context );
// Declare evalator that maven itself uses.
ExpressionEvaluator evaluator = new PluginParameterExpressionEvaluator(
context, mojoExec, pathTranslator, logger, project, project.getProperties() );
// Lookup plexus configuration component
ComponentConfigurator configurator = (ComponentConfigurator) lookup(ComponentConfigurator.ROLE,"basic");
// Configure mojo using above
ConfigurationListener listener = new DebugConfigurationListener( logger );
configurator.configureComponent( mojo, config, evaluator, getContainer().getContainerRealm(), listener );
this.session = context;
this.execution = mojoExec;
Whitebox.setInternalState( mojo, "session", this.session );
Whitebox.setInternalState( mojo, "execution", this.execution );
return mojo;
}
/**
* Get the project directory used for this mojo.
*
* @param mojo the mojo to query.
* @return the project directory.
* @throws IllegalAccessException if unable to get the project directory.
*/
public File getProjectDir(AbstractAndroidMojo mojo) throws IllegalAccessException {
MavenProject project = (MavenProject) getVariableValueFromObject(mojo, "project");
return project.getFile().getParentFile();
}
}