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