001: /*
002: * SalomeTMF is a Test Management Framework
003: * Copyright (C) 2005 France Telecom R&D
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: * @author Marche Mikael
020: *
021: * Contact: mikael.marche@rd.francetelecom.com
022: */
023:
024: package salomeTMF_plug.abbotScriptRunner;
025:
026: import java.awt.Frame;
027: import java.io.File;
028: import java.io.PrintWriter;
029: import java.io.StringWriter;
030: import java.net.URL;
031: import java.util.HashMap;
032: import java.util.Hashtable;
033: import java.util.Iterator;
034: import java.util.List;
035: import java.util.Set;
036: import java.util.StringTokenizer;
037:
038: import javax.swing.SwingUtilities;
039:
040: import org.java.plugin.Plugin;
041: import org.java.plugin.PluginDescriptor;
042: import org.java.plugin.PluginManager;
043: import org.objectweb.salome_tmf.api.Util;
044: import org.objectweb.salome_tmf.data.Attachment;
045: import org.objectweb.salome_tmf.data.Environment;
046: import org.objectweb.salome_tmf.data.FileAttachment;
047: import org.objectweb.salome_tmf.ihm.main.SalomeTMF;
048: import org.objectweb.salome_tmf.ihm.main.SalomeTMFContext;
049: import org.objectweb.salome_tmf.plugins.core.TestDriver;
050:
051: import abbot.ExitException;
052: import abbot.finder.AWTHierarchy;
053: import abbot.finder.Hierarchy;
054: import abbot.finder.TestHierarchy;
055: import abbot.script.EventExceptionHandler;
056: import abbot.script.Script;
057: import abbot.script.Step;
058: import abbot.script.StepRunner;
059: import abbot.script.UIContext;
060: import abbot.util.AWT;
061: import abbot.util.AWTFixtureHelper;
062:
063: public class abbotScriptPlugin extends Plugin implements TestDriver {
064: String tmpLog = "";
065: String testDriverArg = "";
066: boolean toto = true;
067:
068: private Script testScript;
069: boolean isScriptRunning = false;
070: private ThreadGroup appGroup;
071:
072: private int nonce;
073: private StepRunner runner;
074: private TestHierarchy hierarchy;
075:
076: static final String EXIT_ON_FAILLURE = "StopOnFailure";
077: static final String EXIT_ON_ERROR = "StopOnError";
078: static final String SLOW_PLAYBACK = "SlowPlaybac";
079: static final String FORKED = "Forked";
080:
081: private static final int PASS = 0;
082: private static final int ERROR = 1;
083: private static final int INCO = 2;
084: private static final String FIXTURE_EXT = ".xml";
085: Frame view;
086:
087: String log;
088:
089: /* Plug-in Parameter */
090: boolean isSlowPlayback = false;
091: boolean isStopOnFailure = true;
092: boolean isStopOnError = true;
093: boolean isForked = false;
094:
095: int verdict;
096:
097: String currentEnvName = null;
098:
099: public abbotScriptPlugin(PluginManager manager,
100: PluginDescriptor descr) {
101: super (manager, descr);
102: testDriverArg = abbotScriptPlugin.EXIT_ON_FAILLURE + "="
103: + isStopOnError + "," + abbotScriptPlugin.EXIT_ON_ERROR
104: + "=" + isStopOnError + ","
105: + abbotScriptPlugin.SLOW_PLAYBACK + "="
106: + isSlowPlayback + "," + abbotScriptPlugin.FORKED + "="
107: + isForked;
108: view = SalomeTMFContext.getInstance().getSalomeFrame();
109: }
110:
111: protected void doStart() throws Exception {
112:
113: }
114:
115: protected void doStop() throws Exception {
116: // no-op
117: }
118:
119: /*********************** Interface TestDriver ****************************/
120: public void initTestDriver(URL urlSalome) {
121:
122: }
123:
124: /**
125: * @see salome.plugins.core.TestDriver
126: */
127: public void getHelp() {
128: Util.log("abbotScript TestDriver");
129: }
130:
131: /**
132: * @see salome.plugins.core.TestDriver
133: */
134: public String getDefaultTestDiverAgument() {
135: return testDriverArg;
136: }
137:
138: /**
139: * @see salome.plugins.core.TestDriver
140: */
141: public String modifyTestDiverAgument(String oldArg) {
142: boolean _isSlowPlayback = isSlowPlayback;
143: boolean _isStopOnFailure = isStopOnFailure;
144: boolean _isStopOnError = isStopOnError;
145: boolean _isForked = isForked;
146:
147: String strIsSlowPlayback;
148: String strIsStopOnFailure;
149: String strIsStopOnError;
150: String strIsForked;
151:
152: Hashtable res = analyseArg(oldArg);
153: strIsSlowPlayback = (String) res.get(SLOW_PLAYBACK);
154: strIsStopOnFailure = (String) res.get(EXIT_ON_FAILLURE);
155: strIsStopOnError = (String) res.get(EXIT_ON_ERROR);
156: strIsForked = (String) res.get(FORKED);
157:
158: if (strIsSlowPlayback != null
159: && strIsSlowPlayback.equals("true")) {
160: _isSlowPlayback = true;
161: }
162: if (strIsStopOnFailure != null
163: && strIsStopOnFailure.equals("true")) {
164: _isStopOnFailure = true;
165: }
166: if (strIsStopOnError != null && strIsStopOnError.equals("true")) {
167: _isStopOnError = true;
168: }
169: if (strIsForked != null && strIsForked.equals("true")) {
170: _isForked = true;
171: }
172:
173: SetUpDialog pSetUpDialog = new SetUpDialog(SalomeTMFContext
174: .getInstance().getSalomeFrame(), _isSlowPlayback,
175: _isStopOnFailure, _isStopOnError, _isForked);
176: pSetUpDialog.setVisible(true);
177: if (pSetUpDialog.getValue() != null) {
178: oldArg = pSetUpDialog.getValue();
179: }
180: return oldArg;
181: }
182:
183: Hashtable analyseArg(String oldArg) {
184: Hashtable res = new Hashtable();
185: StringTokenizer strToken = new StringTokenizer(oldArg, ",");
186: while (strToken.hasMoreTokens()) {
187: String elt = strToken.nextToken();
188: String[] result = elt.split("=");
189: if (result.length == 2) {
190: String key = result[0];
191: String value = result[1];
192: res.put(key, value);
193: } else {
194: Util.log("[abbotScriptPlugin] Argument corrupted");
195: }
196:
197: }
198:
199: return res;
200: }
201:
202: /**
203: * @see salome.plugins.core.TestDriver
204: */
205: public int runTest(String strTestScript,
206: org.objectweb.salome_tmf.data.AutomaticTest pTest,
207: Hashtable argTest, String plugArg) throws Exception {
208: log = "";
209: verdict = PASS;
210:
211: Hashtable res = analyseArg(plugArg);
212: String strIsSlowPlayback;
213: String strIsStopOnFailure;
214: String strIsStopOnError;
215: String strIsForked;
216:
217: strIsSlowPlayback = (String) res.get(SLOW_PLAYBACK);
218: strIsStopOnFailure = (String) res.get(EXIT_ON_FAILLURE);
219: strIsStopOnError = (String) res.get(EXIT_ON_ERROR);
220: strIsForked = (String) res.get(FORKED);
221:
222: if (strIsSlowPlayback != null
223: && strIsSlowPlayback.equals("true")) {
224: isSlowPlayback = true;
225: }
226: if (strIsStopOnFailure != null
227: && strIsStopOnFailure.equals("true")) {
228: isStopOnFailure = true;
229: }
230: if (strIsStopOnError != null && strIsStopOnError.equals("true")) {
231: isStopOnError = true;
232: }
233: if (strIsForked != null && strIsForked.equals("true")) {
234: isForked = true;
235: }
236:
237: Environment pCurrentEnv = (Environment) argTest
238: .get("salome_environmentObject");
239: try {
240: initTest(pCurrentEnv);
241: } catch (Exception e) {
242: setStatus("Error on init : " + e);
243: setStatus(getStackTrace(e));
244: verdict = INCO;
245: return verdict;
246: }
247: openScript(strTestScript);
248:
249: /* Analyse plugArg */
250: slowPlaybackToggle();
251: stopOnFailureToggle();
252: stopOnErrorToggle();
253: forkedToggle();
254:
255: isScriptRunning = true;
256:
257: runScript();
258: while (isScriptRunning) {
259: Thread.yield();
260: }
261: terminate();
262: return verdict;
263:
264: }
265:
266: /**
267: * @see salome.plugins.core.TestDriver
268: */
269: public String getTestLog() {
270: return log;
271: }
272:
273: /**
274: * @see salome.plugins.core.TestDriver
275: */
276: public void stopTest() throws Exception {
277: terminate();
278: }
279:
280: /**
281: * Odre d'édition du test
282: */
283: public void editTest(String testScript,
284: org.objectweb.salome_tmf.data.AutomaticTest pTest,
285: Hashtable arg, String plugParam) throws Exception {
286: }
287:
288: public void onDeleteTestScript(
289: org.objectweb.salome_tmf.data.AutomaticTest pTest) {
290: }
291:
292: public void updateTestScriptFromImport(String testScript,
293: org.objectweb.salome_tmf.data.AutomaticTest pTest) {
294: }
295:
296: public java.io.File choiceTest(
297: org.objectweb.salome_tmf.data.AutomaticTest pTest) {
298: java.io.File file = null;
299: javax.swing.JFileChooser fileChooser = new javax.swing.JFileChooser();
300: fileChooser.setApproveButtonText("Valider");
301: fileChooser.addChoosableFileFilter(new abbotFileFilter(
302: "Abbot GUI Test FrameWork", ".xml"));
303: int returnVal = fileChooser.showOpenDialog(null);
304: if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
305: file = fileChooser.getSelectedFile();
306: }
307: //TreePathParser pParser = new TreePathParser(file.getAbsolutePath());
308: return file;
309:
310: }
311:
312: /*********************************************************************************************************/
313:
314: private void initTest(Environment pCurrentEnv) throws Exception {
315: if (currentEnvName == null) {
316: currentEnvName = pCurrentEnv.getNameFromModel();
317: importFixtureFile(pCurrentEnv);
318: } else if (!currentEnvName.equals(pCurrentEnv
319: .getNameFromModel())) {
320: currentEnvName = pCurrentEnv.getNameFromModel();
321: importFixtureFile(pCurrentEnv);
322: }
323: }
324:
325: private void importFixtureFile(Environment pCurrentEnv)
326: throws Exception {
327: HashMap attachListEnv = pCurrentEnv.getAttachmentMapFromModel();
328: Set keysSet = attachListEnv.keySet();
329: for (Iterator iter = keysSet.iterator(); iter.hasNext();) {
330: Object elem = iter.next();
331: Attachment attach = (Attachment) attachListEnv.get(elem);
332: if (attach instanceof FileAttachment) {
333: String fileName = attach.getNameFromModel();
334: String ext = fileName.substring(fileName
335: .lastIndexOf("."), fileName.length());
336: if (ext.toLowerCase().equals(FIXTURE_EXT)) {
337: ((FileAttachment) attach).getFileFromDB();
338: }
339: }
340: //if (attach.getDescriptionFromModel().equals("[abbot fixtures]"));
341: }
342:
343: hierarchy = initContext(true);
344: hierarchy.setFiltered(view, true);
345: runner = new PluginStepRunner();
346: //runner.setTerminateOnError(true);
347: runner.setStopOnError(true);
348: runner.setStopOnFailure(true);
349: }
350:
351: /**********************************************************************************************************/
352:
353: private TestHierarchy initContext(boolean isRoot) {
354: TestHierarchy hierarchy = new TestHierarchy() {
355: private String desc = "Test hierarchy for ";
356:
357: public String toString() {
358: return desc;
359: }
360: };
361: AWTHierarchy.setDefault(hierarchy);
362: //initSecurityManager();
363: try {
364: //new EventExceptionHandler().install();
365: } catch (Exception e) {
366: e.printStackTrace();
367: }
368: return hierarchy;
369: }
370:
371: /* slow */
372: private void slowPlaybackToggle() {
373: if (testScript != null) {
374: testScript.setSlowPlayback(isSlowPlayback);
375: }
376: }
377:
378: /* stop on faillure */
379: private void stopOnFailureToggle() {
380: if (testScript != null) {
381: runner.setStopOnFailure(isStopOnFailure);
382: }
383: }
384:
385: /* stop on error */
386: private void stopOnErrorToggle() {
387: if (testScript != null) {
388: runner.setStopOnError(isStopOnError);
389: }
390: }
391:
392: /* run on new VM */
393: private void forkedToggle() {
394: if (testScript != null) {
395: testScript.setForked(isForked);
396: }
397: }
398:
399: /******************************** Engine ************************************************************/
400: private void openScript(String strFile) {
401: File file = new File(strFile);
402: setScript(file.getAbsolutePath());
403: }
404:
405: /** Set the current test script. */
406: private void setScript(String filename) {
407: Script script = filename != null ? new Script(filename,
408: hierarchy) : null;
409: setScript(script);
410: }
411:
412: private void setScript(Script script) {
413: if (script == testScript && script != null)
414: return;
415:
416: setStatus("Setting script to '" + script + "'");
417: if (script != null) {
418: try {
419: script.load();
420: } catch (Exception ise) {
421: System.out.println(ise);
422: setScript((String) null);
423: setStatus("Invalid Script" + ise.toString());
424: return;
425: }
426: }
427:
428: if (testScript != null) {
429: UIContext context = testScript.getUIContext();
430: if (context != null
431: && !context.equivalent(runner.getCurrentContext()))
432: runner.terminate();
433: }
434: testScript = script;
435:
436: if (script == null) {
437: setStatus("NoScript");
438: }
439: //setActionsEnabledState();
440: }
441:
442: private void runScript() {
443: if (testScript == null) {
444: System.out.println("null testScript");
445: return;
446: }
447: setStatus("Running test case " + testScript);
448:
449: setStatus("actions.run.start");
450: Runnable completion = new Runnable() {
451: public void run() {
452: System.out.println("Finish");
453: view.toFront();
454: }
455: };
456: runSteps(testScript, false, "actions.run.finish", completion);
457: }
458:
459: private void runSteps(final Step which, final boolean launch,
460: final String completionMessage, final Runnable onCompletion) {
461: setStatus("running " + which);
462: final List savedState = AWT.disableHierarchy(view);
463: Runnable action = new LaunchAction(which, savedState,
464: onCompletion, completionMessage, launch);
465: String groupName = "AUT Thread Group for " + this + ":"
466: + nonce++;
467: if (appGroup == null) {
468: appGroup = new ThreadGroup(groupName) {
469: public void uncaughtException(Thread t, Throwable thrown) {
470: if (!(thrown instanceof ExitException)
471: && !(thrown instanceof ThreadDeath)) {
472: setStatus("Application thread exception not caught: "
473: + t);
474: //System.out.println(thrown);
475: }
476: }
477: };
478: }
479: Thread launcher = new Thread(appGroup, action, "Script runner:"
480: + nonce);
481: launcher.setDaemon(true);
482: //view.getComponentBrowser().setEnabled(false);
483: //view.setEditor(null);
484: isScriptRunning = true;
485: launcher.start();
486: }
487:
488: /** Do everything we can to dispose of the application under test. */
489: private void terminate() {
490: //scriptTable.clearSelection();
491: try {
492: runner.terminate();
493: } catch (Throwable e) {
494: e.printStackTrace();
495: }
496: }
497:
498: /** Set the contents of the status message to the given exception. */
499: private String getStackTrace(Throwable thr) {
500: StringWriter writer = new StringWriter();
501: thr.printStackTrace(new PrintWriter(writer));
502: return writer.toString();
503: }
504:
505: private void setStatus(String msg) {
506: Util.log("[AbbotPlugin] log : " + msg);
507: log = log + msg + "\n";
508: }
509:
510: private void setStatus(String msg, String extended, int type) {
511: String toWrite = msg + "\n" + extended + "\n";
512: Util.log("[AbbotPlugin] log : " + toWrite);
513: log += toWrite;
514: verdict = type;
515: }
516:
517: /******************************************************************************************************/
518:
519: private class LaunchAction implements Runnable {
520: private final Step which;
521: private final List savedState;
522: private final Runnable onCompletion;
523: private final String completionMessage;
524: private final boolean launch;
525:
526: private LaunchAction(Step which, List savedState,
527: Runnable onCompletion, String completionMessage,
528: boolean launch) {
529: this .which = which;
530: this .savedState = savedState;
531: this .onCompletion = onCompletion;
532: this .completionMessage = completionMessage;
533: this .launch = launch;
534: }
535:
536: public void run() {
537: try {
538: if (launch) {
539: if (which instanceof Script) {
540: UIContext context = which instanceof UIContext ? (UIContext) which
541: : ((Script) which).getUIContext();
542: if (context != null)
543: context.launch(runner);
544: }
545: } else {
546: runner.run(which);
547: }
548: if (completionMessage != null) {
549: /* RUN FINISH */
550: setStatus(completionMessage);
551: }
552: } catch (Throwable e) {
553: // launch didn't work, get rid of it
554: if (launch)
555: terminate();
556: setStatus(e.getMessage(), getStackTrace(e), ERROR);
557: }
558: SwingUtilities.invokeLater(new Runnable() {
559: public void run() {
560: AWT.reenableHierarchy(savedState);
561: isScriptRunning = false;
562: //setActionsEnabledState();
563: if (onCompletion != null) {
564: onCompletion.run();
565: }
566: }
567: });
568: }
569: }
570:
571: private class PluginStepRunner extends StepRunner {
572: /** We use a single runner througout the editor's lifetime,
573: * so one saved UI context will suffice.
574: */
575: public PluginStepRunner() {
576: super (new AWTFixtureHelper());
577: }
578:
579: public Hierarchy getHierarchy() {
580: return abbotScriptPlugin.this .hierarchy;
581: }
582:
583: public void terminate() {
584: super .terminate();
585: // view.getComponentBrowser().refresh();
586: }
587: }
588:
589: /************************************************************************************************/
590:
591: }
|