001package org.andromda.maven.plugin.cartridge;
002
003import java.io.File;
004import java.io.IOException;
005import junit.framework.Test;
006import junit.framework.TestResult;
007import org.andromda.core.common.ExceptionUtils;
008import org.andromda.maven.plugin.AndroMDAMojo;
009import org.apache.commons.io.FileUtils;
010import org.apache.maven.plugin.MojoExecutionException;
011import org.apache.maven.plugin.MojoFailureException;
012
013
014/**
015 * Provides the ability to compare cartridge output with existing output.
016 *
017 * @phase generate-test-sources
018 * @goal test
019 * @requiresDependencyResolution test
020 * @description runs AndroMDA Cartridge tests
021 * @author Chad Brandon
022 * @author Bob Fields
023 */
024public class CartridgeTestMojo
025    extends AbstractCartridgeTestMojo
026{
027    /**
028     * @see org.apache.maven.plugin.Mojo#execute()
029     */
030    public void execute()
031        throws MojoExecutionException, MojoFailureException
032    {
033        if (!this.skip)
034        {
035            final File expectedOutputArchive = this.expectedOutputArchive;
036            if (!expectedOutputArchive.exists() || !expectedOutputArchive.isFile())
037            {
038                if (this.testFailureIgnore)
039                {
040                    this.getLog().error("The path specifying the expectedOutputArchive '" +
041                            this.expectedOutputArchive + "' must be a file");
042                }
043                else
044                {
045                    throw new MojoExecutionException("The path specifying the expectedOutputArchive '" +
046                            this.expectedOutputArchive + "' must be a file");
047                }
048            }
049            final File expectedOutputDir = this.expectedDirectory;
050            if (!expectedOutputDir.exists())
051            {
052                expectedOutputDir.mkdirs();
053            }
054            else if (!expectedOutputDir.isDirectory())
055            {
056                throw new MojoExecutionException("The path specifying the expectedDirectory '" +
057                    this.expectedDirectory + "' must be a directory");
058            }
059            else if (!this.lastModifiedCheck)
060            {
061                try
062                {
063                    FileUtils.cleanDirectory(expectedOutputDir);
064                }
065                catch (IOException ex)
066                {
067                    throw new MojoExecutionException("Could not clean the expectedDirectory '" +
068                            this.expectedDirectory + "'");
069                }
070            }
071
072            final File actualOutputDir = this.actualDirectory;
073            if (!actualOutputDir.exists())
074            {
075                actualOutputDir.mkdirs();
076            }
077            else if (!actualOutputDir.isDirectory())
078            {
079                throw new MojoExecutionException("The path specifying the actualOutputDir '" +
080                    this.actualDirectory + "' must be a directory");
081            }
082            else if (!this.lastModifiedCheck)
083            {
084                try
085                {
086                    FileUtils.cleanDirectory(actualOutputDir);
087                }
088                catch (IOException ex)
089                {
090                    throw new MojoExecutionException("Could not clean the actualOutputDir '" +
091                            this.actualDirectory + "'");
092                }
093            }
094
095            try
096            {
097                this.getLog().info("-----------------------------------------------------------------------------");
098                this.getLog().info("          A n d r o M D A   C a r t r i d g e   T e s t   S u i t e          ");
099                this.getLog().info("-----------------------------------------------------------------------------");
100                this.getLog().info("configurationUri=" + this.configurationUri);
101                this.getLog().info("actualDirectory=" + this.actualDirectory);
102                this.getLog().info("expectedDirectory=" + this.expectedDirectory);
103                this.getLog().info("expectedOutputArchive=" + this.expectedOutputArchive);
104                this.getLog().info("lastModifiedCheck=" + this.lastModifiedCheck);
105                if (this.testFailureIgnore)
106                {
107                    this.getLog().info("testFailureIgnore=" + this.testFailureIgnore);
108                }
109
110                // - change scope of test dependencies to runtime
111                // TODO Add test dependencies required to compile all of the generated source code, and run testCompile for all cartridges
112                this.changeScopeForTestDependencies();
113                // TODO Clear the error list, carried over from a previous cartridge run failure.
114
115                // - first run AndroMDA with the test configuration
116                final AndroMDAMojo andromdaMojo = new AndroMDAMojo();
117                andromdaMojo.setConfigurationUri(this.configurationUri);
118                andromdaMojo.setProject(this.project);
119                andromdaMojo.setSettings(this.settings);
120                andromdaMojo.setPropertyFiles(this.propertyFiles);
121                andromdaMojo.setLastModifiedCheck(this.lastModifiedCheck);
122                andromdaMojo.setModelOutputHistory(new File(this.actualDirectory, ".."));
123                // TODO This causes the build output expected directory to compile when running javadocs.
124                //andromdaMojo.setBuildSourceDirectory(this.actualDirectory);
125                andromdaMojo.execute();
126
127                // - unpack the expected output archive
128                this.unpack(
129                    expectedOutputArchive,
130                    this.expectedDirectory);
131
132                final CartridgeTest cartridgeTest = CartridgeTest.instance();
133                cartridgeTest.setActualOutputPath(this.actualDirectory.getAbsolutePath());
134                cartridgeTest.setExpectedOutputPath(this.expectedDirectory.getAbsolutePath());
135                cartridgeTest.setActualOutputDirectory(null);
136                cartridgeTest.setExpectedOutputDirectory(null);
137                cartridgeTest.setBinarySuffixes(this.binaryOutputSuffixes);
138
139                final CartridgeTestFormatter formatter = new CartridgeTestFormatter();
140
141                // - set the report location
142                final File report = new File(this.reportDirectory, this.project.getArtifactId() + ".txt");
143                formatter.setReportFile(report);
144                formatter.setTestFailureIgnore(this.testFailureIgnore);
145                final TestResult result = new TestResult();
146                result.addListener(formatter);
147                final Test suite = CartridgeTest.suite();
148                formatter.startTestSuite(this.project.getName());
149                suite.run(result);
150                this.getLog().info("");
151                this.getLog().info("Results:");
152                this.getLog().info(formatter.endTestSuite(suite));
153                cartridgeTest.shutdown();
154
155                if (result.failureCount() > 0 || result.errorCount() > 0)
156                {
157                    if (this.testFailureIgnore)
158                    {
159                        this.getLog().error("There are test failures, failureCount=" + result.failureCount() + " errorCount=" + result.errorCount()
160                                + ", Cartridge=" + this.project.getArtifactId());
161                    }
162                    else
163                    {
164                        throw new MojoExecutionException("There are test failures, failureCount=" + result.failureCount() + " errorCount=" + result.errorCount());
165                    }
166                }
167            }
168            catch (final Throwable throwable)
169            {
170                if (throwable instanceof MojoExecutionException && !this.testFailureIgnore)
171                {
172                    throw (MojoExecutionException)throwable;
173                }
174                else if (this.testFailureIgnore)
175                {
176                    this.getLog().error("An error occurred while testing cartridge '" +
177                        this.project.getArtifactId() + '\'',
178                        ExceptionUtils.getRootCause(throwable));
179                }
180                else
181                {
182                    throw new MojoExecutionException("An error occurred while testing cartridge '" +
183                            this.project.getArtifactId() + '\'',
184                            ExceptionUtils.getRootCause(throwable));
185                }
186            }
187        }
188        else
189        {
190            this.getLog().info("Skipping cartridge tests");
191        }
192    }
193}