001: package abbot.script;
002:
003: import java.awt.*;
004: import java.io.*;
005: import java.util.Iterator;
006:
007: import javax.swing.*;
008: import java.util.*;
009:
010: import junit.extensions.abbot.*;
011: import junit.extensions.abbot.Timer;
012: import org.jdom.Element;
013:
014: import abbot.tester.Robot;
015:
016: /**
017: * Verify the script works as advertised.
018: */
019: public class ScriptTest extends ResolverFixture implements XMLConstants {
020:
021: private Script script;
022: private File baseDir;
023: private File otherRoot;
024: private static final String ENCODING = "UTF-8";
025:
026: protected void setUp() throws IOException {
027: script = new Script(getHierarchy());
028:
029: // Create a base dir
030:
031: baseDir = File.createTempFile("baseDir", "");
032: baseDir.deleteOnExit();
033:
034: // Configure a file in another root to make sure that we get absolute
035: // paths
036:
037: if (System.getProperty("os.name").toLowerCase().startsWith(
038: "window")) {
039: otherRoot = new File("w:\\root");
040: } else {
041: otherRoot = new File("/newroot");
042: }
043:
044: // Finally set the location relative to location on the script
045: // so all start at the same position
046: //
047:
048: script.setRelativeTo(baseDir);
049:
050: //
051:
052: ComponentReference.cacheOnCreation = false;
053: }
054:
055: protected void tearDown() {
056: ComponentReference.cacheOnCreation = true;
057: }
058:
059: public static Reader stringToReader(String script) throws Throwable {
060: ByteArrayInputStream ba = new ByteArrayInputStream(script
061: .getBytes(ENCODING));
062: InputStreamReader reader = new InputStreamReader(ba, ENCODING);
063: return reader;
064: }
065:
066: public void testDefaultDescription() {
067: String filename = script.getFile().getName();
068: assertTrue(
069: "Default script description should omit the filename "
070: + "if the script is a temporary file: "
071: + script.getDescription(), script
072: .getDescription().indexOf(filename) == -1);
073: }
074:
075: // need an automatic way to generate all component ref attributes
076: // using a hand-coded array isn't any more reliable than the original
077: // edits of abbot.xsd.
078: /*
079: public void testComponentValidation() throws Throwable {
080: Frame f = new Frame(getName());
081: ComponentReference ref = script.addComponent(f);
082: Iterator iter = VALID_ATTRIBUTES.iterator();
083: // Make sure our XSD has included ALL the valid cref attributes
084: while (iter.hasNext()) {
085: ref.setAttribute((String)iter.next(), "0");
086: }
087: script.save();
088: script.load();
089: }
090: */
091:
092: public void testLaunchAsUIContext() {
093: script.clear();
094: Launch launch = new Launch(script, getName(), "any.cls.name",
095: "method", new String[] { "[]" });
096: script.addStep(launch);
097: assertEquals("Launch should be UIContext", launch, script
098: .getUIContext());
099: }
100:
101: public void testFixtureAsUIContext() {
102: script.clear();
103: Fixture fixture = new Fixture(script, new HashMap());
104: script.addStep(fixture);
105: assertEquals("Fixture should be UIContext", fixture, script
106: .getUIContext());
107: }
108:
109: public void testCatchInvalidScript() throws Throwable {
110: String bogus = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
111: + "<AWTTestScript desc=\"ignored\">\r\n"
112: + " <terminate/>\r\n" + " <component id=\"id\"/>\r\n"
113: + "</AWTTestScript>\r\n\r\n";
114: try {
115: script.load(stringToReader(bogus));
116: fail("Expected an invalid script exception");
117: } catch (InvalidScriptException ise) {
118: }
119: }
120:
121: public void testInValidLaunchLocation() throws Throwable {
122: String valid = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
123: + "<AWTTestScript>\r\n"
124: + " <sequence/>\r\n"
125: + " <launch class=\"none\" method=\"main\" args=\"[]\"/>\r\n"
126: + "</AWTTestScript>\r\n\r\n";
127: try {
128: script.load(stringToReader(valid));
129: fail("A script with a launch step in other than position 0 should be detected as invalid");
130: } catch (InvalidScriptException e) {
131: }
132: }
133:
134: public void testTerminatePositionValidation() throws Throwable {
135: String valid = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
136: + "<AWTTestScript>\r\n"
137: + " <terminate/>\r\n"
138: + " <launch class=\"none\" method=\"main\" args=\"[]\"/>\r\n"
139: + "</AWTTestScript>\r\n\r\n";
140: try {
141: script.load(stringToReader(valid));
142: fail("A script with a terminate step in other than last position should be detected as invalid");
143: } catch (InvalidScriptException e) {
144: }
145: }
146:
147: public void testDirty() throws Throwable {
148: script.save();
149: script.getFile().deleteOnExit();
150: script.load();
151: assertTrue("Script should not be dirty immediately after load",
152: !script.isDirty());
153: script.addStep(new Script(getHierarchy()));
154: assertTrue("Script should be dirty after modifications", script
155: .isDirty());
156: script.removeStep(0);
157: assertTrue("Script should not be dirty", !script.isDirty());
158: }
159:
160: static final String ID = "button";
161: static final String TEXT = "\u65E5\u008Aencoded";
162: static final String CLASS = "javax.swing.JButton";
163: private static final String unicodeData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
164: + "<AWTTestScript>\r\n"
165: + " <component class=\""
166: + CLASS
167: + "\" id=\""
168: + ID
169: + "\" text=\""
170: + TEXT
171: + "\" />\r\n"
172: + " <terminate />\r\n" + "</AWTTestScript>\r\n\r\n";
173:
174: public void testWrite() throws Throwable {
175: StringWriter writer = new StringWriter();
176: Element el = new Element(XMLConstants.TAG_COMPONENT)
177: .setAttribute(XMLConstants.TAG_ID, ID).setAttribute(
178: XMLConstants.TAG_TEXT, TEXT).setAttribute(
179: XMLConstants.TAG_CLASS, CLASS);
180: ComponentReference ref = script.addComponentReference(el);
181: assertEquals("Incorrect tag encoding", TEXT, ref
182: .getAttribute(XMLConstants.TAG_TEXT));
183: script.addStep(new Terminate(script, (String) null));
184: script.save(writer);
185:
186: // Note that this is all Unicode, NOT UTF-8
187: assertEquals("Incorrect XML written", unicodeData, writer
188: .toString());
189: }
190:
191: public void testRead() throws Throwable {
192: try {
193: script.load(stringToReader(unicodeData));
194: assertEquals("Wrong number of references", 1, script
195: .getComponentReferences().size());
196: assertEquals("Wrong number of steps", 1, script.size());
197: ComponentReference ref = (ComponentReference) script
198: .getComponentReferences().iterator().next();
199: // Ensure all attributes are saved with unicode
200: assertEquals("Wrong tag", TEXT, ref
201: .getAttribute(XMLConstants.TAG_TEXT));
202: } catch (InvalidScriptException ise) {
203: fail(ise.getMessage());
204: }
205: }
206:
207: /** Ensure that a nested script maintains its own context. */
208: public void testNestedReference() throws Throwable {
209: Script nested = new Script(getHierarchy());
210: nested.load(stringToReader(unicodeData));
211: script.addStep(nested);
212: assertEquals("Wrong resolver", script, script.getResolver());
213: assertEquals("Wrong nested resolver", nested, nested
214: .getResolver());
215: assertEquals("Wrong resolver for nested step", nested,
216: ((Step) nested.steps().get(0)).getResolver());
217:
218: String nestedScriptData = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
219: + "<AWTTestScript>\r\n"
220: + " <script filename=\"nested.xml\" >\r\n"
221: + " </script>\r\n" + "</AWTTestScript>\r\n\r\n";
222: script.load(stringToReader(nestedScriptData));
223: nested = (Script) script.steps().get(0);
224: assertEquals("Wrong resolver for nested script", nested, nested
225: .getResolver());
226: }
227:
228: /** A nested script should have *only* its filename attribute saved. */
229: public void testSaveNestedScript() throws Throwable {
230: String fullNestedScript = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
231: + "<AWTTestScript>\r\n"
232: + " <script filename=\"nested.xml\" >\r\n"
233: + " <comment desc=\"Filler\" />\r\n"
234: + " </script>\r\n" + "</AWTTestScript>\r\n\r\n";
235: String savedNestedScript = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n"
236: + "<AWTTestScript>\r\n"
237: + " <script filename=\"nested.xml\" />\r\n"
238: + "</AWTTestScript>\r\n\r\n";
239: script.load(stringToReader(fullNestedScript));
240: StringWriter writer = new StringWriter();
241: script.save(writer);
242: assertEquals("Incorrectly saved", savedNestedScript, writer
243: .toString());
244: Script nested = (Script) script.steps().get(0);
245: assertEquals("Wrong relative directory", script.getDirectory(),
246: nested.getRelativeTo());
247: }
248:
249: public void testForceUseForwardSlashesInSavedPaths()
250: throws IOException {
251: // Configure the script to be in a sub dir with user.home as
252: // relative to location making use of forward slashes
253: //
254:
255: File userDir = new File(System.getProperty("user.home"));
256: File scriptLocation = new File(userDir, "relative\\example.xml");
257: File relativeLocation = new File(userDir, "");
258:
259: //
260:
261: script.setRelativeTo(relativeLocation);
262: script.setFile(scriptLocation);
263:
264: //
265:
266: assertTrue("Relative path contains backslashes", script
267: .getFilename().indexOf("\\") == -1);
268:
269: assertEquals("Relative path is incorrect",
270: "relative/example.xml", script.getFilename());
271:
272: }
273:
274: public void testRelativeSimple() {
275:
276: File relative = new File(baseDir, "relative.xml");
277: script.setRelativeTo(baseDir);
278: script.setFile(relative);
279:
280: assertTrue("Script file should be absolute", script.getFile()
281: .isAbsolute());
282: assertEquals("Script filename should now be relative", script
283: .getFilename(), "relative.xml");
284: }
285:
286: public void testSimpleAbsolute() {
287:
288: File relative = new File(baseDir, "relative.xml");
289: script.setRelativeTo(otherRoot);
290: script.setFile(relative);
291:
292: assertTrue("Script file should be absolute", script.getFile()
293: .isAbsolute());
294: assertEquals("Script filename should now be relative", script
295: .getFilename(), relative.getPath());
296: }
297:
298: public void testRelativeParent() {
299:
300: File relative = new File(baseDir, "relative.xml");
301: script.setRelativeTo(new File(baseDir, "child"));
302: script.setFile(relative);
303:
304: assertTrue("Script file should be absolute", script.getFile()
305: .isAbsolute());
306: assertEquals("Script filename should now be relative", script
307: .getFilename(), "../relative.xml");
308: }
309:
310: public void testRelativeChild() {
311:
312: File relative = new File(baseDir, "child/relative.xml");
313: script.setRelativeTo(baseDir);
314: script.setFile(relative);
315:
316: assertTrue("Script file should be absolute", script.getFile()
317: .isAbsolute());
318: assertEquals("Script filename should now be relative", script
319: .getFilename(), "child/relative.xml");
320: }
321:
322: public void testFarTooRelative() {
323: File relative = new File(otherRoot, "../../../../..");
324: try {
325: Script.resolveRelativeReferences(relative);
326: fail("Should have throw exception to consuming too much of the path");
327: } catch (IllegalArgumentException ise) {
328: // Do nothing, this is fine
329: }
330: }
331:
332: public void testMoveRelativeParentParent() throws IOException {
333:
334: String relativePath = "one/relative.xml";
335: String subSubPath = "../../relative.xml";
336:
337: File oneDir = new File(baseDir, "one");
338: File twoDir = new File(oneDir, "two");
339: File threeDir = new File(twoDir, "three");
340:
341: // Make the root of the script something sensible, as on
342: // some platform this could be just any old tmp directory
343: //
344:
345: File targetFile = new File(baseDir, relativePath);
346: script.setFile(targetFile);
347:
348: // R: baseDir/one/two/three
349: // FI: baseDir/one/relative.xml
350: // FO: ../../relative.xml
351:
352: script.setRelativeTo(threeDir);
353: assertEquals("Wrong relative filename (parent parent)",
354: subSubPath, script.getFilename());
355: assertEquals("Wrong relative dir (parent parent)", threeDir,
356: script.getRelativeTo());
357: assertEquals("File should be the same (parent parent)",
358: targetFile, script.getFile());
359:
360: }
361:
362: public void testMoveRelativeParent() throws IOException {
363:
364: String relativePath = "one/relative.xml";
365: String subPath = "../relative.xml";
366:
367: File oneDir = new File(baseDir, "one");
368: File twoDir = new File(oneDir, "two");
369:
370: // Make the root of the script something sensible, as on
371: // some platform this could be just any old tmp directory
372: //
373:
374: File targetFile = new File(baseDir, relativePath);
375: script.setFile(targetFile);
376:
377: // R: baseDir/one/two
378: // FI: baseDir/one/relative.xml
379: // FO: ../relative.xml
380:
381: script.setRelativeTo(twoDir);
382: assertEquals("Wrong relative filename (parent)", subPath,
383: script.getFilename());
384: assertEquals("Wrong relative dir (parent)", twoDir, script
385: .getRelativeTo());
386: assertEquals("File should be the same (parent)", targetFile,
387: script.getFile());
388:
389: }
390:
391: public void testMoveRelative() throws IOException {
392:
393: String name = "relative.xml";
394: String relativePath = "one/relative.xml";
395:
396: File oneDir = new File(baseDir, "one");
397:
398: // Make the root of the script something sensible, as on
399: // some platform this could be just any old tmp directory
400: //
401:
402: File targetFile = new File(baseDir, relativePath);
403: script.setFile(targetFile);
404:
405: // R: baseDir/one
406: // FI: baseDir/one/relative.xml
407: // FO: relative.xml
408:
409: script.setRelativeTo(oneDir);
410: assertEquals("Wrong relative filename (sameDir)", name, script
411: .getFilename());
412: assertEquals("Wrong relative dir (sameDir)", oneDir, script
413: .getRelativeTo());
414: assertEquals("File should be the same (sameDir)", targetFile,
415: script.getFile());
416:
417: }
418:
419: public void testMoveRelativeChild() throws IOException {
420:
421: String relativePath = "one/relative.xml";
422:
423: // Make the root of the script something sensible, as on
424: // some platform this could be just any old tmp directory
425: //
426:
427: File targetFile = new File(baseDir, relativePath);
428: script.setFile(targetFile);
429:
430: // R: baseDir
431: // FI: baseDir/one/relative
432: // FO: one/relative.xml
433:
434: script.setRelativeTo(baseDir);
435: assertEquals("Wrong relative filename (child)", relativePath,
436: script.getFilename());
437: assertEquals("Wrong relative dir (child)", baseDir, script
438: .getRelativeTo());
439: assertEquals("File should be the same (child)", targetFile,
440: script.getFile());
441:
442: }
443:
444: /** Any given component, if added multiple times, should result in the
445: * same component reference.
446: */
447: public void testReferenceReuse() throws Throwable {
448: JTextField tf = new JTextField();
449: showFrame(tf);
450:
451: ComponentReference ref = script.addComponent(tf);
452: assertEquals("New reference does not match the component"
453: + " from which it was created", tf, ref.getComponent());
454:
455: ComponentReference ref2 = script.addComponent(tf);
456: assertEquals(
457: "Same component should always result in the same ref",
458: ref, ref2);
459:
460: assertEquals("Reverse lookup of reference by component failed",
461: ref, script.getComponentReference(tf));
462: }
463:
464: /** Any number of unique components should all result in unique
465: * references.
466: */
467: public void testUniqueReferences() {
468: JTextField tf1 = new JTextField();
469: JTextField tf2 = new JTextField();
470: JButton b1 = new JButton("Button");
471: JButton b2 = new JButton("Button");
472: JPanel pane = new JPanel();
473: pane.add(tf1);
474: pane.add(tf2);
475: pane.add(b1);
476: pane.add(b2);
477: showFrame(pane);
478:
479: ComponentReference cr1 = script.addComponent(tf1);
480: ComponentReference cr2 = script.addComponent(tf2);
481: assertTrue("Should get two unique text field references",
482: cr1 != cr2);
483:
484: ComponentReference cr3 = script.addComponent(b1);
485: ComponentReference cr4 = script.addComponent(b2);
486: assertTrue("Should get two unique button references",
487: cr3 != cr4);
488: }
489:
490: public void testReferenceOrdering() throws Throwable {
491: HashMap map = new HashMap();
492: ComponentReference cr1 = new ComponentReference(getResolver(),
493: JButton.class, map);
494: ComponentReference cr2 = new ComponentReference(getResolver(),
495: JButton.class, map);
496: ComponentReference cr3 = new ComponentReference(getResolver(),
497: JButton.class, map);
498: Script s1 = new Script(getHierarchy());
499: Script s2 = new Script(getHierarchy());
500: s1.addComponentReference(cr1);
501: s1.addComponentReference(cr2);
502: s1.addComponentReference(cr3);
503: s2.addComponentReference(cr3);
504: s2.addComponentReference(cr2);
505: s2.addComponentReference(cr1);
506:
507: Iterator iter1 = s1.getComponentReferences().iterator();
508: Iterator iter2 = s2.getComponentReferences().iterator();
509: while (iter1.hasNext()) {
510: assertTrue("Reference counts don't match", iter2.hasNext());
511: assertEquals("Reference ordering not maintained", iter1
512: .next(), iter2.next());
513: }
514: }
515:
516: /** When referencing a new reference's parent, make sure we don't map it
517: inappropriately to an existing reference.
518: */
519: public void testCreateProperWindowAncestor() {
520: JOptionPane pane = new JOptionPane();
521: Dialog d = pane.createDialog(null, getName());
522: showWindow(d);
523: ComponentReference ref1 = script.addComponent(d);
524: hideWindow(d);
525: final JFileChooser chooser = new JFileChooser();
526: SwingUtilities.invokeLater(new Runnable() {
527: public void run() {
528: chooser.showOpenDialog(null);
529: }
530: });
531: // Wait for the dialog to post
532: Window w;
533: Timer timer = new Timer();
534: while ((w = SwingUtilities.getWindowAncestor(chooser)) == null) {
535: if (timer.elapsed() > 5000)
536: fail("File chooser has no window");
537: getRobot().sleep();
538: }
539: assertTrue("Wrong window selected: " + d, d != w);
540:
541: timer.reset();
542: while (!w.isShowing()) {
543: if (timer.elapsed() > 5000)
544: fail("File chooser window is not showing");
545: getRobot().sleep();
546: }
547:
548: // NOTE: making the JFileChooser reference triggered a bug where this
549: // reference's dialog/window would mistakenly use the existing dialog
550: // reference (ref1) instead of creating a new one.
551: ComponentReference ref2 = script.addComponent(chooser);
552: ComponentReference ref3 = script.addComponent(w);
553: assertTrue("Dialog for file chooser " + ref2
554: + " should get a unique reference for "
555: + Robot.toString(w) + ", instead got " + ref3, !ref1
556: .equals(ref3));
557: }
558:
559: private class DefaultStep extends Step {
560: public DefaultStep(Resolver r) {
561: super (r, new HashMap());
562: }
563:
564: public void runStep() {
565: }
566:
567: public String getXMLTag() {
568: return "defaultstep";
569: }
570:
571: public String getUsage() {
572: return "blah";
573: }
574:
575: public String getDefaultDescription() {
576: return "dummy step for " + getName();
577: }
578: }
579:
580: public void testLineReporting() {
581: Script script = new Script(getHierarchy());
582: Step step = new DefaultStep(script);
583: script.addStep(step);
584: assertEquals("Wrong file reported for first step", script
585: .getFile(), Script.getFile(step));
586: assertEquals("Wrong line number for first step", 3, Script
587: .getLine(step));
588:
589: HashMap map = new HashMap();
590: ComponentReference cr1 = new ComponentReference(script,
591: JButton.class, map);
592: ComponentReference cr2 = new ComponentReference(script,
593: JButton.class, map);
594: assertEquals("Wrong line number after refs added", 5, Script
595: .getLine(step));
596:
597: Sequence seq = new Sequence(script, "");
598: script.addStep(seq);
599: assertEquals("Wrong line number for added sequence", 6, Script
600: .getLine(seq));
601:
602: step = new DefaultStep(script);
603: seq.addStep(step);
604: assertEquals("Wrong line number for step within sequence", 7,
605: Script.getLine(step));
606:
607: seq = new Sequence(script, "");
608: script.addStep(seq);
609: assertEquals("Wrong line number for step after sequence", 9,
610: Script.getLine(seq));
611:
612: step = new DefaultStep(script);
613: script.addStep(step);
614: assertEquals("Wrong line number for step after empty sequence",
615: 10, Script.getLine(step));
616: }
617:
618: public void testIDChangeDetection() {
619: Script script = new Script(getHierarchy());
620: JLabel label = new JLabel(getName());
621: showFrame(label);
622: ComponentReference ref = script.addComponent(label);
623: assertEquals("Default id lookup failed with " + ref.getID(),
624: ref, script.getComponentReference(ref.getID()));
625:
626: ref.setAttribute(XMLConstants.TAG_ID, "goober");
627: assertEquals("Changed ref id not detected: " + ref.getID(),
628: ref, script.getComponentReference(ref.getID()));
629: }
630:
631: public ScriptTest(String name) {
632: super (name);
633: }
634:
635: public static void main(String[] args) {
636: TestHelper.runTests(args, ScriptTest.class);
637: }
638: }
|