001: /*
002: * Copyright 2001-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: *
016: */
017:
018: package bexee.ant;
019:
020: import java.io.File;
021: import java.io.PrintStream;
022: import java.net.URL;
023:
024: import junit.framework.TestCase;
025:
026: import org.apache.tools.ant.BuildEvent;
027: import org.apache.tools.ant.BuildException;
028: import org.apache.tools.ant.BuildListener;
029: import org.apache.tools.ant.Project;
030: import org.apache.tools.ant.ProjectHelper;
031:
032: /**
033: * A BuildFileTest is a TestCase which executes targets from an Ant buildfile
034: * for testing.
035: *
036: * This class provides a number of utility methods for particular build file
037: * tests which extend this class.
038: *
039: * @author Nico Seessle <nico@seessle.de>
040: * @author Conor MacNeill
041: */
042: public abstract class BuildFileTest extends TestCase {
043:
044: protected Project project;
045:
046: private StringBuffer logBuffer;
047: private StringBuffer fullLogBuffer;
048: private StringBuffer outBuffer;
049: private StringBuffer errBuffer;
050: private BuildException buildException;
051:
052: /**
053: * Constructor for the BuildFileTest object
054: *
055: * @param name string to pass up to TestCase constructor
056: */
057: public BuildFileTest(String name) {
058: super (name);
059: }
060:
061: /**
062: * run a target, expect for any build exception
063: *
064: *@param target target to run
065: *@param cause information string to reader of report
066: */
067: protected void expectBuildException(String target, String cause) {
068: expectSpecificBuildException(target, cause, null);
069: }
070:
071: /**
072: * Assert that only the given message has been logged with a
073: * priority >= INFO when running the given target.
074: */
075: protected void expectLog(String target, String log) {
076: executeTarget(target);
077: String realLog = getLog();
078: assertEquals(log, realLog);
079: }
080:
081: /**
082: * Assert that the given substring is in the log messages
083: */
084:
085: protected void assertLogContaining(String substring) {
086: String realLog = getLog();
087: assertTrue("expecting log to contain \"" + substring
088: + "\" log was \"" + realLog + "\"", realLog
089: .indexOf(substring) >= 0);
090: }
091:
092: /**
093: * Assert that the given message has been logged with a priority
094: * >= INFO when running the given target.
095: */
096: protected void expectLogContaining(String target, String log) {
097: executeTarget(target);
098: assertLogContaining(log);
099: }
100:
101: /**
102: * Gets the log the BuildFileTest object.
103: * only valid if configureProject() has
104: * been called.
105: * @pre logBuffer!=null
106: * @return The log value
107: */
108: protected String getLog() {
109: return logBuffer.toString();
110: }
111:
112: /**
113: * Assert that the given message has been logged with a priority
114: * >= DEBUG when running the given target.
115: */
116: protected void expectDebuglog(String target, String log) {
117: executeTarget(target);
118: String realLog = getFullLog();
119: assertEquals(log, realLog);
120: }
121:
122: /**
123: * Gets the log the BuildFileTest object.
124: * only valid if configureProject() has
125: * been called.
126: * @pre fullLogBuffer!=null
127: * @return The log value
128: */
129: protected String getFullLog() {
130: return fullLogBuffer.toString();
131: }
132:
133: /**
134: * execute the target, verify output matches expectations
135: *
136: *@param target target to execute
137: *@param output output to look for
138: */
139:
140: protected void expectOutput(String target, String output) {
141: executeTarget(target);
142: String realOutput = getOutput();
143: assertEquals(output, realOutput.trim());
144: }
145:
146: /**
147: * execute the target, verify output matches expectations
148: * and that we got the named error at the end
149: *@param target target to execute
150: *@param output output to look for
151: *@param error Description of Parameter
152: */
153:
154: protected void expectOutputAndError(String target, String output,
155: String error) {
156: executeTarget(target);
157: String realOutput = getOutput();
158: assertEquals(output, realOutput);
159: String realError = getError();
160: assertEquals(error, realError);
161: }
162:
163: protected String getOutput() {
164: return cleanBuffer(outBuffer);
165: }
166:
167: protected String getError() {
168: return cleanBuffer(errBuffer);
169: }
170:
171: protected BuildException getBuildException() {
172: return buildException;
173: }
174:
175: private String cleanBuffer(StringBuffer buffer) {
176: StringBuffer cleanedBuffer = new StringBuffer();
177: boolean cr = false;
178: for (int i = 0; i < buffer.length(); i++) {
179: char ch = buffer.charAt(i);
180: if (ch == '\r') {
181: cr = true;
182: continue;
183: }
184:
185: if (!cr) {
186: cleanedBuffer.append(ch);
187: } else {
188: cleanedBuffer.append(ch);
189: }
190: }
191: return cleanedBuffer.toString();
192: }
193:
194: /**
195: * set up to run the named project
196: *
197: * @param filename name of project file to run
198: */
199: protected void configureProject(String filename)
200: throws BuildException {
201: configureProject(filename, Project.MSG_DEBUG);
202: }
203:
204: /**
205: * set up to run the named project
206: *
207: * @param filename name of project file to run
208: */
209: protected void configureProject(String filename, int logLevel)
210: throws BuildException {
211: logBuffer = new StringBuffer();
212: fullLogBuffer = new StringBuffer();
213: project = new Project();
214: project.init();
215: project.setUserProperty("ant.file", new File(filename)
216: .getAbsolutePath());
217: project.addBuildListener(new AntTestListener(logLevel));
218: ProjectHelper helper = ProjectHelper.getProjectHelper();
219: project.addReference("ant.projectHelper", helper);
220: helper.parse(project, new File(filename));
221: }
222:
223: /**
224: * execute a target we have set up
225: * @pre configureProject has been called
226: * @param targetName target to run
227: */
228: protected void executeTarget(String targetName) {
229: PrintStream sysOut = System.out;
230: PrintStream sysErr = System.err;
231: try {
232: sysOut.flush();
233: sysErr.flush();
234: outBuffer = new StringBuffer();
235: PrintStream out = new PrintStream(new AntOutputStream(
236: outBuffer));
237: System.setOut(out);
238: errBuffer = new StringBuffer();
239: PrintStream err = new PrintStream(new AntOutputStream(
240: errBuffer));
241: System.setErr(err);
242: logBuffer = new StringBuffer();
243: fullLogBuffer = new StringBuffer();
244: buildException = null;
245: project.executeTarget(targetName);
246: } finally {
247: System.setOut(sysOut);
248: System.setErr(sysErr);
249: }
250:
251: }
252:
253: /**
254: * Get the project which has been configured for a test.
255: *
256: * @return the Project instance for this test.
257: */
258: protected Project getProject() {
259: return project;
260: }
261:
262: /**
263: * get the directory of the project
264: * @return the base dir of the project
265: */
266: protected File getProjectDir() {
267: return project.getBaseDir();
268: }
269:
270: /**
271: * run a target, wait for a build exception
272: *
273: *@param target target to run
274: *@param cause information string to reader of report
275: *@param msg the message value of the build exception we are waiting for
276: set to null for any build exception to be valid
277: */
278: protected void expectSpecificBuildException(String target,
279: String cause, String msg) {
280: try {
281: executeTarget(target);
282: } catch (org.apache.tools.ant.BuildException ex) {
283: buildException = ex;
284: if ((null != msg) && (!ex.getMessage().equals(msg))) {
285: fail("Should throw BuildException because '" + cause
286: + "' with message '" + msg
287: + "' (actual message '" + ex.getMessage()
288: + "' instead)");
289: }
290: return;
291: }
292: fail("Should throw BuildException because: " + cause);
293: }
294:
295: /**
296: * run a target, expect an exception string
297: * containing the substring we look for (case sensitive match)
298: *
299: *@param target target to run
300: *@param cause information string to reader of report
301: *@param contains substring of the build exception to look for
302: */
303: protected void expectBuildExceptionContaining(String target,
304: String cause, String contains) {
305: try {
306: executeTarget(target);
307: } catch (org.apache.tools.ant.BuildException ex) {
308: buildException = ex;
309: if ((null != contains)
310: && (ex.getMessage().indexOf(contains) == -1)) {
311: fail("Should throw BuildException because '" + cause
312: + "' with message containing '" + contains
313: + "' (actual message '" + ex.getMessage()
314: + "' instead)");
315: }
316: return;
317: }
318: fail("Should throw BuildException because: " + cause);
319: }
320:
321: /**
322: * call a target, verify property is as expected
323: *
324: * @param target build file target
325: * @param property property name
326: * @param value expected value
327: */
328:
329: protected void expectPropertySet(String target, String property,
330: String value) {
331: executeTarget(target);
332: assertPropertyEquals(property, value);
333: }
334:
335: /**
336: * assert that a property equals a value; comparison is case sensitive.
337: * @param property property name
338: * @param value expected value
339: */
340: protected void assertPropertyEquals(String property, String value) {
341: String result = project.getProperty(property);
342: assertEquals("property " + property, value, result);
343: }
344:
345: /**
346: * assert that a property equals "true"
347: * @param property property name
348: */
349: protected void assertPropertySet(String property) {
350: assertPropertyEquals(property, "true");
351: }
352:
353: /**
354: * assert that a property is null
355: * @param property property name
356: */
357: protected void assertPropertyUnset(String property) {
358: assertPropertyEquals(property, null);
359: }
360:
361: /**
362: * call a target, verify named property is "true".
363: *
364: * @param target build file target
365: * @param property property name
366: */
367: protected void expectPropertySet(String target, String property) {
368: expectPropertySet(target, property, "true");
369: }
370:
371: /**
372: * call a target, verify property is null
373: * @param target build file target
374: * @param property property name
375: */
376: protected void expectPropertyUnset(String target, String property) {
377: expectPropertySet(target, property, null);
378: }
379:
380: /**
381: * Retrieve a resource from the caller classloader to avoid
382: * assuming a vm working directory. The resource path must be
383: * relative to the package name or absolute from the root path.
384: * @param resource the resource to retrieve its url.
385: * @throws AssertionFailureException if resource is not found.
386: */
387: protected URL getResource(String resource) {
388: URL url = getClass().getResource(resource);
389: assertNotNull("Could not find resource :" + resource, url);
390: return url;
391: }
392:
393: /**
394: * an output stream which saves stuff to our buffer.
395: */
396: private static class AntOutputStream extends java.io.OutputStream {
397: private StringBuffer buffer;
398:
399: public AntOutputStream(StringBuffer buffer) {
400: this .buffer = buffer;
401: }
402:
403: public void write(int b) {
404: buffer.append((char) b);
405: }
406: }
407:
408: /**
409: * our own personal build listener
410: */
411: private class AntTestListener implements BuildListener {
412: private int logLevel;
413:
414: /**
415: * Constructs a test listener which will ignore log events
416: * above the given level
417: */
418: public AntTestListener(int logLevel) {
419: this .logLevel = logLevel;
420: }
421:
422: /**
423: * Fired before any targets are started.
424: */
425: public void buildStarted(BuildEvent event) {
426: }
427:
428: /**
429: * Fired after the last target has finished. This event
430: * will still be thrown if an error occured during the build.
431: *
432: * @see BuildEvent#getException()
433: */
434: public void buildFinished(BuildEvent event) {
435: }
436:
437: /**
438: * Fired when a target is started.
439: *
440: * @see BuildEvent#getTarget()
441: */
442: public void targetStarted(BuildEvent event) {
443: //System.out.println("targetStarted " + event.getTarget().getName());
444: }
445:
446: /**
447: * Fired when a target has finished. This event will
448: * still be thrown if an error occured during the build.
449: *
450: * @see BuildEvent#getException()
451: */
452: public void targetFinished(BuildEvent event) {
453: //System.out.println("targetFinished " + event.getTarget().getName());
454: }
455:
456: /**
457: * Fired when a task is started.
458: *
459: * @see BuildEvent#getTask()
460: */
461: public void taskStarted(BuildEvent event) {
462: //System.out.println("taskStarted " + event.getTask().getTaskName());
463: }
464:
465: /**
466: * Fired when a task has finished. This event will still
467: * be throw if an error occured during the build.
468: *
469: * @see BuildEvent#getException()
470: */
471: public void taskFinished(BuildEvent event) {
472: //System.out.println("taskFinished " + event.getTask().getTaskName());
473: }
474:
475: /**
476: * Fired whenever a message is logged.
477: *
478: * @see BuildEvent#getMessage()
479: * @see BuildEvent#getPriority()
480: */
481: public void messageLogged(BuildEvent event) {
482: if (event.getPriority() > logLevel) {
483: // ignore event
484: return;
485: }
486:
487: if (event.getPriority() == Project.MSG_INFO
488: || event.getPriority() == Project.MSG_WARN
489: || event.getPriority() == Project.MSG_ERR) {
490: logBuffer.append(event.getMessage());
491: }
492: fullLogBuffer.append(event.getMessage());
493:
494: }
495: }
496:
497: }
|