| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| * |
| */ |
| package org.apache.easyant.core; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.net.URISyntaxException; |
| import java.net.URL; |
| |
| import org.apache.easyant.core.configuration.EasyAntConfiguration; |
| import org.apache.easyant.core.configuration.EasyantConfigurationFactory; |
| import org.apache.tools.ant.BuildEvent; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.BuildListener; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.types.LogLevel; |
| import org.junit.After; |
| import org.junit.Rule; |
| import org.junit.rules.TemporaryFolder; |
| |
| /** |
| * A EasyAntBaseTest is a TestCase which executes targets from an easyant module for testing. |
| * |
| * This class provides a number of utility methods for particular build file tests which extend this class. |
| * |
| */ |
| public abstract class EasyAntBaseTest { |
| |
| protected static final String EASYANT_CACHE_DIR = "ivy.cache.dir"; |
| protected Project project; |
| protected EasyAntConfiguration conf; |
| |
| private StringBuffer logBuffer; |
| private StringBuffer fullLogBuffer; |
| private StringBuffer outBuffer; |
| private StringBuffer errBuffer; |
| private BuildException buildException; |
| |
| @Rule |
| public TemporaryFolder folder = new TemporaryFolder(); |
| |
| /** |
| * Automatically calls the target called "tearDown" from the build file tested if it exits. |
| * |
| * This allows to use Ant tasks directly in the build file to clean up after each test. Note that no "setUp" target |
| * is automatically called, since it's trivial to have a test target depend on it. |
| */ |
| @After |
| public void tearDown() throws Exception { |
| if (project == null) { |
| /* |
| * Maybe the EasyAntBaseTest was subclassed and there is no initialized project. So we could avoid getting a |
| * NPE. If there is an initialized project getTargets() does not return null as it is initialized by an |
| * empty HashSet. |
| */ |
| return; |
| } |
| final String tearDown = "tearDown"; |
| if (project.getTargets().containsKey(tearDown)) { |
| project.executeTarget(tearDown); |
| } |
| cleanTargetDirectory(); |
| } |
| |
| public void cleanTargetDirectory() { |
| if (project == null) { |
| throw new IllegalStateException("Project is not configured !"); |
| } |
| File targetDirectory = project.resolveFile(project.replaceProperties("${basedir}/target")); |
| targetDirectory.delete(); |
| } |
| |
| public void cleanCache() { |
| if (project == null) { |
| throw new IllegalStateException("Project is not configured !"); |
| } |
| File cacheDirectory = project.resolveFile(project.replaceProperties(project.getProperty(EASYANT_CACHE_DIR))); |
| cacheDirectory.delete(); |
| } |
| |
| /** |
| * run a target, expect for any build exception |
| * |
| * @param target |
| * target to run |
| * @param cause |
| * information string to reader of report |
| */ |
| public void expectBuildException(String target, String cause) { |
| expectSpecificBuildException(target, cause, null); |
| } |
| |
| /** |
| * Assert that only the given message has been logged with a priority <= INFO when running the given target. |
| */ |
| public void expectLog(String target, String log) { |
| executeTarget(target); |
| String realLog = getLog(); |
| assertEquals(log, realLog); |
| } |
| |
| /** |
| * Assert that the given substring is in the log messages. |
| */ |
| public void assertLogContaining(String substring) { |
| String realLog = getLog(); |
| assertTrue("expecting log to contain \"" + substring + "\" log was \"" + realLog + "\"", |
| realLog.contains(substring)); |
| } |
| |
| /** |
| * Assert that the given substring is not in the log messages. |
| */ |
| public void assertLogNotContaining(String substring) { |
| String realLog = getLog(); |
| assertFalse("didn't expect log to contain \"" + substring + "\" log was \"" + realLog + "\"", |
| realLog.contains(substring)); |
| } |
| |
| /** |
| * Assert that the given substring is in the output messages. |
| * |
| * @since Ant1.7 |
| */ |
| public void assertOutputContaining(String substring) { |
| assertOutputContaining(null, substring); |
| } |
| |
| /** |
| * Assert that the given substring is in the output messages. |
| * |
| * @param message |
| * Print this message if the test fails. Defaults to a meaningful text if <tt>null</tt> is passed. |
| * @since Ant1.7 |
| */ |
| public void assertOutputContaining(String message, String substring) { |
| String realOutput = getOutput(); |
| String realMessage = (message != null) ? message : "expecting output to contain \"" + substring |
| + "\" output was \"" + realOutput + "\""; |
| assertTrue(realMessage, realOutput.contains(substring)); |
| } |
| |
| /** |
| * Assert that the given substring is not in the output messages. |
| * |
| * @param message |
| * Print this message if the test fails. Defaults to a meaningful text if <tt>null</tt> is passed. |
| * @since Ant1.7 |
| */ |
| public void assertOutputNotContaining(String message, String substring) { |
| String realOutput = getOutput(); |
| String realMessage = (message != null) ? message : "expecting output to not contain \"" + substring |
| + "\" output was \"" + realOutput + "\""; |
| assertFalse(realMessage, realOutput.contains(substring)); |
| } |
| |
| /** |
| * Assert that the given message has been logged with a priority <= INFO when running the given target. |
| */ |
| public void expectLogContaining(String target, String log) { |
| executeTarget(target); |
| assertLogContaining(log); |
| } |
| |
| /** |
| * Assert that the given message has not been logged with a priority <= INFO when running the given target. |
| */ |
| public void expectLogNotContaining(String target, String log) { |
| executeTarget(target); |
| assertLogNotContaining(log); |
| } |
| |
| /** |
| * Gets the log the BuildFileTest object. Only valid if configureProject() has been called. |
| * |
| * @pre logBuffer!=null |
| * @return The log value |
| */ |
| public String getLog() { |
| return logBuffer.toString(); |
| } |
| |
| /** |
| * Assert that the given message has been logged with a priority >= VERBOSE when running the given target. |
| */ |
| public void expectDebuglog(String target, String log) { |
| executeTarget(target); |
| String realLog = getFullLog(); |
| assertEquals(log, realLog); |
| } |
| |
| /** |
| * Assert that the given substring is in the log messages. |
| */ |
| public void assertDebuglogContaining(String substring) { |
| String realLog = getFullLog(); |
| assertTrue("expecting debug log to contain \"" + substring + "\" log was \"" + realLog + "\"", |
| realLog.contains(substring)); |
| } |
| |
| /** |
| * Gets the log the BuildFileTest object. |
| * |
| * Only valid if configureProject() has been called. |
| * |
| * @pre fullLogBuffer!=null |
| * @return The log value |
| */ |
| public String getFullLog() { |
| return fullLogBuffer.toString(); |
| } |
| |
| /** |
| * execute the target, verify output matches expectations |
| * |
| * @param target |
| * target to execute |
| * @param output |
| * output to look for |
| */ |
| public void expectOutput(String target, String output) { |
| executeTarget(target); |
| String realOutput = getOutput(); |
| assertEquals(output, realOutput.trim()); |
| } |
| |
| /** |
| * Executes the target, verify output matches expectations and that we got the named error at the end |
| * |
| * @param target |
| * target to execute |
| * @param output |
| * output to look for |
| * @param error |
| * Description of Parameter |
| */ |
| public void expectOutputAndError(String target, String output, String error) { |
| executeTarget(target); |
| String realOutput = getOutput(); |
| assertEquals(output, realOutput); |
| String realError = getError(); |
| assertEquals(error, realError); |
| } |
| |
| public String getOutput() { |
| return cleanBuffer(outBuffer); |
| } |
| |
| public String getError() { |
| return cleanBuffer(errBuffer); |
| } |
| |
| public BuildException getBuildException() { |
| return buildException; |
| } |
| |
| private String cleanBuffer(StringBuffer buffer) { |
| StringBuilder cleanedBuffer = new StringBuilder(); |
| for (int i = 0; i < buffer.length(); i++) { |
| char ch = buffer.charAt(i); |
| if (ch != '\r') { |
| cleanedBuffer.append(ch); |
| } |
| } |
| return cleanedBuffer.toString(); |
| } |
| |
| /** |
| * configure and init to run the named project |
| * |
| * @param url |
| * path to project file to run |
| * @param logLevel |
| * a given {@link LogLevel} |
| * |
| * @throws BuildException |
| */ |
| public void configureAndInitProject(URL url, int logLevel) { |
| configureProject(url, logLevel); |
| initProject(); |
| } |
| |
| /** |
| * configure and init to run the named project |
| * |
| * @param url |
| * path to project file to run |
| * @throws BuildException |
| */ |
| public void configureAndInitProject(URL url) { |
| configureProject(url); |
| initProject(); |
| } |
| |
| /** |
| * Set up to run the named project |
| * |
| * @param url |
| * path to project file to run |
| * @throws BuildException |
| */ |
| public void configureProject(URL url) throws BuildException { |
| File f = null; |
| try { |
| f = new File(url.toURI()); |
| } catch (URISyntaxException e) { |
| throw new BuildException("Can't load project from url " + url.toString(), e); |
| } |
| configureProject(f.getAbsolutePath(), Project.MSG_DEBUG); |
| } |
| |
| /** |
| * Set up to run the named project |
| * |
| * @param url |
| * path to project file to run |
| * @param logLevel |
| * a given {@link LogLevel} |
| * |
| * @throws BuildException |
| */ |
| public void configureProject(URL url, int logLevel) throws BuildException { |
| File f = null; |
| try { |
| f = new File(url.toURI()); |
| } catch (URISyntaxException e) { |
| throw new BuildException("Can't load project from url " + url.toString(), e); |
| } |
| configureProject(f.getAbsolutePath(), logLevel); |
| } |
| |
| /** |
| * Sets up to run the named project |
| * |
| * @param filename |
| * name of project file to run |
| */ |
| public void configureProject(String filename) throws BuildException { |
| configureProject(filename, Project.MSG_DEBUG); |
| } |
| |
| /** |
| * Sets up to run the named project If you want to modify a few thing on the default configuration you should |
| * override this method |
| * |
| * @param filename |
| * name of project file to run |
| * @param logLevel |
| * a given {@link LogLevel} |
| */ |
| public void configureProject(String filename, int logLevel) throws BuildException { |
| conf = EasyantConfigurationFactory.getInstance().createDefaultConfiguration(); |
| conf.setMsgOutputLevel(logLevel); |
| conf.setBuildModule(new File(filename)); |
| conf.getDefinedProps().put(EasyAntMagicNames.SKIP_CORE_REVISION_CHECKER, "true"); |
| // to avoid side effects due to user settings we ignore this setting by |
| // default for test |
| conf.getDefinedProps().put(EasyAntMagicNames.IGNORE_USER_IVYSETTINGS, "true"); |
| conf.getDefinedProps().put(EasyAntMagicNames.PROJECT_IVY_INSTANCE, EasyAntMagicNames.EASYANT_IVY_INSTANCE); |
| |
| // Configure easyant ivy instance |
| conf.setEasyantIvySettingsUrl(this.getClass().getResource("/repositories/easyant-ivysettings-test.xml")); |
| try { |
| conf.getDefinedProps().put("ivy.cache.dir", folder.newFolder().getAbsolutePath()); |
| } catch (IOException e) { |
| throw new BuildException(e); |
| } |
| File projectModule = new File(filename); |
| if (!projectModule.exists()) { |
| throw new BuildException("Project " + projectModule.getAbsolutePath() + " does not exists"); |
| } |
| } |
| |
| /** |
| * Init the project instance with configuration |
| * |
| * @pre configureProject has been called |
| */ |
| public void initProject() { |
| if (conf == null) { |
| throw new RuntimeException("You must call the configureProject method before initProject()"); |
| } |
| // Flush the buffer |
| logBuffer = new StringBuffer(); |
| fullLogBuffer = new StringBuffer(); |
| // init the new project instance |
| project = new Project(); |
| project.addBuildListener(new AntTestListener(conf.getMsgOutputLevel())); |
| EasyAntEngine eaEngine = new EasyAntEngine(conf); |
| eaEngine.configureEasyAnt(project); |
| eaEngine.loadProject(project);//FIXME should be better handled |
| } |
| |
| /** |
| * Executes a target we have set up |
| * |
| * @pre initProject has been called |
| * @param targetName |
| * target to run |
| */ |
| public void executeTarget(String targetName) { |
| PrintStream sysOut = System.out; |
| PrintStream sysErr = System.err; |
| try { |
| sysOut.flush(); |
| sysErr.flush(); |
| outBuffer = new StringBuffer(); |
| PrintStream out = new PrintStream(new AntOutputStream(outBuffer)); |
| System.setOut(out); |
| errBuffer = new StringBuffer(); |
| PrintStream err = new PrintStream(new AntOutputStream(errBuffer)); |
| System.setErr(err); |
| logBuffer = new StringBuffer(); |
| fullLogBuffer = new StringBuffer(); |
| buildException = null; |
| project.executeTarget(targetName); |
| } finally { |
| System.setOut(sysOut); |
| System.setErr(sysErr); |
| } |
| |
| } |
| |
| /** |
| * Get the project which has been configured for a test. |
| * |
| * @return the Project instance for this test. |
| */ |
| public Project getProject() { |
| return project; |
| } |
| |
| /** |
| * Gets the directory of the project. |
| * |
| * @return the base dir of the project |
| */ |
| public File getProjectDir() { |
| return project.getBaseDir(); |
| } |
| |
| /** |
| * Runs a target, wait for a build exception. |
| * |
| * @param target |
| * target to run |
| * @param cause |
| * information string to reader of report |
| * @param msg |
| * the message value of the build exception we are waiting for set to null for any build exception to be |
| * valid |
| */ |
| public void expectSpecificBuildException(String target, String cause, String msg) { |
| try { |
| executeTarget(target); |
| } catch (org.apache.tools.ant.BuildException ex) { |
| buildException = ex; |
| if ((null != msg) && (!ex.getMessage().equals(msg))) { |
| fail("Should throw BuildException because '" + cause + "' with message '" + msg + "' (actual message '" |
| + ex.getMessage() + "' instead)"); |
| } |
| return; |
| } |
| fail("Should throw BuildException because: " + cause); |
| } |
| |
| /** |
| * run a target, expect an exception string containing the substring we look for (case sensitive match) |
| * |
| * @param target |
| * target to run |
| * @param cause |
| * information string to reader of report |
| * @param contains |
| * substring of the build exception to look for |
| */ |
| public void expectBuildExceptionContaining(String target, String cause, String contains) { |
| try { |
| executeTarget(target); |
| } catch (org.apache.tools.ant.BuildException ex) { |
| buildException = ex; |
| if ((null != contains) && (!ex.getMessage().contains(contains))) { |
| fail("Should throw BuildException because '" + cause + "' with message containing '" + contains |
| + "' (actual message '" + ex.getMessage() + "' instead)"); |
| } |
| return; |
| } |
| fail("Should throw BuildException because: " + cause); |
| } |
| |
| /** |
| * call a target, verify property is as expected |
| * |
| * @param target |
| * build file target |
| * @param property |
| * property name |
| * @param value |
| * expected value |
| */ |
| public void expectPropertySet(String target, String property, String value) { |
| executeTarget(target); |
| assertPropertyEquals(property, value); |
| } |
| |
| /** |
| * assert that a property equals a value; comparison is case sensitive. |
| * |
| * @param property |
| * property name |
| * @param value |
| * expected value |
| */ |
| public void assertPropertyEquals(String property, String value) { |
| String result = project.getProperty(property); |
| assertEquals("property " + property, value, result); |
| } |
| |
| /** |
| * assert that a property equals "true". |
| * |
| * @param property |
| * property name |
| */ |
| public void assertPropertySet(String property) { |
| assertPropertyEquals(property, "true"); |
| } |
| |
| /** |
| * assert that a property is null. |
| * |
| * @param property |
| * property name |
| */ |
| public void assertPropertyUnset(String property) { |
| assertPropertyEquals(property, null); |
| } |
| |
| /** |
| * call a target, verify named property is "true". |
| * |
| * @param target |
| * build file target |
| * @param property |
| * property name |
| */ |
| public void expectPropertySet(String target, String property) { |
| expectPropertySet(target, property, "true"); |
| } |
| |
| /** |
| * Call a target, verify property is null. |
| * |
| * @param target |
| * build file target |
| * @param property |
| * property name |
| */ |
| public void expectPropertyUnset(String target, String property) { |
| expectPropertySet(target, property, null); |
| } |
| |
| /** |
| * Retrieve a resource from the caller classloader to avoid assuming a vm working directory. The resource path must |
| * be relative to the package name or absolute from the root path. |
| * |
| * @param resource |
| * the resource to retrieve its url. |
| * @throws junit.framework.AssertionFailedError |
| * if the resource is not found. |
| */ |
| public URL getResource(String resource) { |
| URL url = getClass().getResource(resource); |
| assertNotNull("Could not find resource :" + resource, url); |
| return url; |
| } |
| |
| /** |
| * an output stream which saves stuff to our buffer. |
| */ |
| private static class AntOutputStream extends java.io.OutputStream { |
| private StringBuffer buffer; |
| |
| public AntOutputStream(StringBuffer buffer) { |
| this.buffer = buffer; |
| } |
| |
| public void write(int b) { |
| buffer.append((char) b); |
| } |
| } |
| |
| /** |
| * Our own personal build listener. |
| */ |
| private class AntTestListener implements BuildListener { |
| private int logLevel; |
| |
| /** |
| * Constructs a test listener which will ignore log events above the given level. |
| */ |
| public AntTestListener(int logLevel) { |
| this.logLevel = logLevel; |
| } |
| |
| /** |
| * Fired before any targets are started. |
| */ |
| public void buildStarted(BuildEvent event) { |
| } |
| |
| /** |
| * Fired after the last target has finished. This event will still be thrown if an error occurred during the |
| * build. |
| * |
| * @see BuildEvent#getException() |
| */ |
| public void buildFinished(BuildEvent event) { |
| } |
| |
| /** |
| * Fired when a target is started. |
| * |
| * @see BuildEvent#getTarget() |
| */ |
| public void targetStarted(BuildEvent event) { |
| // System.out.println("targetStarted " + |
| // event.getTarget().getName()); |
| } |
| |
| /** |
| * Fired when a target has finished. This event will still be thrown if an error occurred during the build. |
| * |
| * @see BuildEvent#getException() |
| */ |
| public void targetFinished(BuildEvent event) { |
| // System.out.println("targetFinished " + |
| // event.getTarget().getName()); |
| } |
| |
| /** |
| * Fired when a task is started. |
| * |
| * @see BuildEvent#getTask() |
| */ |
| public void taskStarted(BuildEvent event) { |
| // System.out.println("taskStarted " + |
| // event.getTask().getTaskName()); |
| } |
| |
| /** |
| * Fired when a task has finished. This event will still be throw if an error occurred during the build. |
| * |
| * @see BuildEvent#getException() |
| */ |
| public void taskFinished(BuildEvent event) { |
| // System.out.println("taskFinished " + |
| // event.getTask().getTaskName()); |
| } |
| |
| /** |
| * Fired whenever a message is logged. |
| * |
| * @see BuildEvent#getMessage() |
| * @see BuildEvent#getPriority() |
| */ |
| public void messageLogged(BuildEvent event) { |
| if (event.getPriority() > logLevel) { |
| // ignore event |
| return; |
| } |
| |
| if (event.getPriority() == Project.MSG_INFO || event.getPriority() == Project.MSG_WARN |
| || event.getPriority() == Project.MSG_ERR) { |
| logBuffer.append(event.getMessage()); |
| } |
| fullLogBuffer.append(event.getMessage()); |
| } |
| } |
| |
| } |