001: package abbot.script;
002:
003: import java.io.*;
004: import java.util.ArrayList;
005:
006: import junit.extensions.abbot.*;
007: import junit.framework.*;
008: import abbot.Log;
009: import abbot.script.ForkedStepRunner.*;
010: import abbot.util.ProcessOutputHandler;
011:
012: /**
013: * Verify the sequence works as advertised.
014: */
015: // FIXME verify forked version has same classpath!
016: public class ForkedStepRunnerTest extends ResolverFixture {
017:
018: private final static String LS = System
019: .getProperty("line.separator");
020: private final static String OUTPUT_TEXT = "This is the output stream";
021: private final static String ERROR_TEXT = "This is the error stream";
022:
023: /** Steps are identified across processes by their encoded locations
024: * within the script.
025: */
026: public void testStepEncoding() throws Throwable {
027: String dummyStep = "<assert class=\"java.lang.Boolean\" "
028: + "method=\"getBoolean\" "
029: + "value=\"false\" args=\"no-such-property\"/>";
030: String src = "<AWTTestScript>" + " <sequence><!--0-->" /* A */
031: + " <sequence><!--0,1-->" + " " + dummyStep
032: + "<!--0,1,1-->" /* B */
033: + " </sequence>" + " <sequence><!--0,2-->"
034: + " </sequence>" + " </sequence>"
035: + " <sequence><!--1-->" + " <sequence><!--1,1-->"
036: + " " + dummyStep + "<!--1,1,1-->" + " "
037: + dummyStep + "<!--1,1,2-->" /* C */
038: + " </sequence>" + " <sequence><!--1,2-->" /* D */
039: + " </sequence>" + " </sequence>"
040: + "</AWTTestScript>";
041: Script script = loadScript(src);
042: // A
043: Step step = script.getStep(0);
044: String code = ForkedStepRunner.encodeStep(script, step);
045: assertEquals("Wrong encoding", "0", code);
046: assertEquals("Wrong decoding", step, ForkedStepRunner
047: .decodeStep(script, code));
048: // B
049: step = ((Sequence) ((Sequence) script.getStep(0)).getStep(1))
050: .getStep(1);
051: code = ForkedStepRunner.encodeStep(script, step);
052: assertEquals("Wrong nested encoding", "0,1,1", code);
053: assertEquals("Wrong nested decoding", step, ForkedStepRunner
054: .decodeStep(script, code));
055: // C
056: step = ((Sequence) ((Sequence) script.getStep(1)).getStep(1))
057: .getStep(2);
058: code = ForkedStepRunner.encodeStep(script, step);
059: assertEquals("Wrong nested encoding", "1,1,2", code);
060: assertEquals("Wrong nested decoding", step, ForkedStepRunner
061: .decodeStep(script, code));
062: // D
063: step = ((Sequence) script.getStep(1)).getStep(2);
064: code = ForkedStepRunner.encodeStep(script, step);
065: assertEquals("Wrong nested encoding", "1,2", code);
066: assertEquals("Wrong nested decoding", step, ForkedStepRunner
067: .decodeStep(script, code));
068:
069: step = script;
070: code = ForkedStepRunner.encodeStep(script, step);
071: assertEquals("Wrong nested encoding", "-1", code);
072: assertEquals("Wrong nested decoding", step, ForkedStepRunner
073: .decodeStep(script, code));
074:
075: }
076:
077: public void testFork() throws Throwable {
078: ForkedStepRunner fs = new ForkedStepRunner();
079: String[] args = { getClass().getName(), "fork", };
080: final StringBuffer sb = new StringBuffer();
081: final StringBuffer sbe = new StringBuffer();
082: Process p;
083: try {
084: p = fs.fork(null, args);
085: } catch (IOException io) {
086: throw new AssertionFailedError("VM fork failed");
087: }
088: try {
089: ProcessOutputHandler handler = new ProcessOutputHandler(p) {
090: protected void handleOutput(byte[] buf, int len) {
091: sb.append(new String(buf, 0, len));
092: }
093:
094: protected void handleError(byte[] buf, int len) {
095: sbe.append(new String(buf, 0, len));
096: }
097: };
098: // FIXME add a timeout
099: p.waitFor();
100: assertEquals("Wrong exit value", 0, p.exitValue());
101: handler.waitFor();
102: assertEquals("Wrong output from subprocess", OUTPUT_TEXT
103: + LS, sb.toString());
104: assertEquals("Wrong error from subprocess",
105: ERROR_TEXT + LS, sbe.toString());
106: } finally {
107: p.destroy();
108: }
109: }
110:
111: /** Run a script to completion. */
112: public void testForkedStepRunner() throws Throwable {
113: // Empty script that does nothing
114: String src = "<AWTTestScript></AWTTestScript>";
115: Script script = loadScript(src);
116: final ArrayList events = new ArrayList();
117: ForkedStepRunner fs = new ForkedStepRunner();
118: fs.addStepListener(new StepListener() {
119: public void stateChanged(StepEvent event) {
120: events.add(event);
121: }
122: });
123: fs.run(script);
124: assertEquals("Wrong number of events", 2, events.size());
125: assertEquals("Wrong step source, event 0", script,
126: ((StepEvent) events.get(0)).getStep());
127: assertEquals("Wrong step id, event 0", StepEvent.STEP_START,
128: ((StepEvent) events.get(0)).getType());
129: assertEquals("Wrong step source, event 1", script,
130: ((StepEvent) events.get(1)).getStep());
131: assertEquals("Wrong step id, event 1", StepEvent.STEP_END,
132: ((StepEvent) events.get(1)).getType());
133: }
134:
135: public void testForkedApplicationPrematureExit() throws Throwable {
136: String src = "<AWTTestScript><call method=\"exit\" class=\""
137: + Exit.class.getName() + "\"/></AWTTestScript>";
138: Script script = loadScript(src);
139: final ArrayList events = new ArrayList();
140: ForkedStepRunner fs = new ForkedStepRunner();
141: fs.addStepListener(new StepListener() {
142: public void stateChanged(StepEvent event) {
143: events.add(event);
144: }
145: });
146: try {
147: fs.run(script);
148: fail("Expected a forked error");
149: } catch (ForkedFailure e) {
150: fail("Expected a forked error, not a failure: " + e);
151: } catch (ForkedError e) {
152: }
153: }
154:
155: /** Should be able to catch a failure from a forked script exactly like
156: * you would from a regular one.
157: */
158: public void testForkedFailure() throws Throwable {
159: String src = "<AWTTestScript>"
160: + "<assert method=\"assertFrameShowing\" args=\"no such window\"/>"
161: + "</AWTTestScript>";
162: ForkedStepRunner fs = new ForkedStepRunner();
163: Script script = loadScript(src);
164: try {
165: fs.run(script);
166: fail("The failure was not propagated");
167: } catch (ForkedFailure ff) {
168: assertEquals("Error not set in runner", ff, fs
169: .getError(script));
170: StringWriter s = new StringWriter();
171: ff.printStackTrace(new PrintWriter(s));
172: String trace = s.toString();
173: assertTrue("No stack trace in failure: " + trace, trace
174: .indexOf("at ") != -1);
175: } catch (Throwable t) {
176: fail("Wrong exception thrown: " + t);
177: } finally {
178: fs.terminate();
179: }
180: }
181:
182: /** Should be able to catch an error from a forked script exactly like
183: * you would from a regular one.
184: */
185: public void testForkedError() throws Throwable {
186: String src = "<AWTTestScript>"
187: + "<launch class=\"nonsense class\" method=\"main\" args=\"[]\"/>"
188: + "</AWTTestScript>";
189: ForkedStepRunner fs = new ForkedStepRunner();
190: Script script = loadScript(src);
191: try {
192: fs.run(script);
193: fail("No error propagated");
194: } catch (ForkedError fe) {
195: assertEquals("Error not set in runner", fe, fs
196: .getError(script));
197: String expected = "java.lang.ClassNotFoundException";
198: assertTrue("Wrong error: " + fe, fe.toString().startsWith(
199: expected));
200: StringWriter s = new StringWriter();
201: fe.printStackTrace(new PrintWriter(s));
202: String trace = s.toString();
203: assertTrue("Error is missing stack trace: " + trace, trace
204: .indexOf("at ") != -1);
205: } catch (Throwable thr) {
206: fail("Wrong error: " + thr);
207: } finally {
208: fs.terminate();
209: }
210: }
211:
212: /** Ensure the forked script has the same directory root as the
213: * original.
214: */
215: public void testForkedScriptDirectory() throws Throwable {
216: String included = getName() + "2";
217: String src = "<AWTTestScript>" + " <script filename=\""
218: + included + "\"/>" + " <terminate/>"
219: + "</AWTTestScript>";
220: // Create the included script first so that the including one doesn't
221: // barf on load
222: Script script2 = new Script(getHierarchy());
223: File dir = new File(script2.getDirectory(), getName());
224: if (!dir.mkdir() && !dir.exists() && !dir.isDirectory())
225: fail("Could not create temporary directory");
226: dir.deleteOnExit();
227: File s2 = new File(dir, included);
228: s2.deleteOnExit();
229: script2.setFile(s2);
230: script2.save();
231: ForkedStepRunner fs = new ForkedStepRunner();
232: Script script = loadScript(src);
233: script.setFile(new File(dir, getName()));
234: fs.run(script);
235: assertEquals("No errors expected", null, fs.getError(script));
236: }
237:
238: private Script loadScript(String src) throws Throwable {
239: StringReader reader = new StringReader(src);
240: Script script = new Script(getHierarchy());
241: script.load(reader);
242: return script;
243: }
244:
245: public ForkedStepRunnerTest(String name) {
246: super (name);
247: }
248:
249: public static class Exit {
250: public static void exit() {
251: System.exit(0);
252: }
253: }
254:
255: public static void main(String[] args) {
256: args = Log.init(args);
257: // special case for self-test
258: if (args.length == 1 && args[0].equals("fork")) {
259: System.out.println(OUTPUT_TEXT);
260: System.err.println(ERROR_TEXT);
261: System.exit(0);
262: }
263: TestHelper.runTests(args, ForkedStepRunnerTest.class);
264: }
265: }
|