001: /*
002: DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003:
004: Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005:
006: The contents of this file are subject to the terms of either the GNU
007: General Public License Version 2 only ("GPL") or the Common
008: Development and Distribution License("CDDL") (collectively, the
009: "License"). You may not use this file except in compliance with the
010: License. You can obtain a copy of the License at
011: http://www.netbeans.org/cddl-gplv2.html
012: or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: specific language governing permissions and limitations under the
014: License. When distributing the software, include this License Header
015: Notice in each file and include the License file at
016: nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: particular file as subject to the "Classpath" exception as provided
018: by Sun in the GPL Version 2 section of the License file that
019: accompanied this code. If applicable, add the following below the
020: License Header, with the fields enclosed by brackets [] replaced by
021: your own identifying information:
022: "Portions Copyrighted [year] [name of copyright owner]"
023:
024: Contributor(s):
025:
026: The Original Software is NetBeans. The Initial Developer of the Original
027: Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: Microsystems, Inc. All Rights Reserved.
029:
030: If you wish your version of this file to be governed by only the CDDL
031: or only the GPL Version 2, indicate your decision by adding
032: "[Contributor] elects to include this software in this distribution
033: under the [CDDL or GPL Version 2] license." If you do not indicate a
034: single choice of license, a recipient has the option to distribute
035: your version of this file under either the CDDL, the GPL Version 2 or
036: to extend the choice of license to its licensees as provided above.
037: However, if you add GPL Version 2 code and therefore, elected the GPL
038: Version 2 license, then the option applies only if the new code is
039: made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.visualweb.gravy;
043:
044: import org.netbeans.jellytools.JellyTestCase;
045: import org.netbeans.junit.*;
046: import org.netbeans.jemmy.*;
047: import org.netbeans.jemmy.util.PNGEncoder;
048: import org.netbeans.jemmy.util.Dumper;
049: import org.netbeans.xtest.util.NativeKill;
050:
051: //import com.sun.rave.gravy.winsys.DockablePaneOperator;
052:
053: import java.awt.*;
054: import java.awt.event.HierarchyEvent;
055: import java.awt.event.AWTEventListener;
056: import java.awt.event.HierarchyListener;
057:
058: import java.io.*;
059:
060: import java.util.Properties;
061: import java.util.Iterator;
062: import java.util.Map;
063:
064: /**
065: *
066: * @author Alexandre (Shura) Iline (alexandre.iline@sun.com)
067: */
068: public class RaveTestCase extends JellyTestCase {
069:
070: /** Full Thread Dump feature in case of failure is disabled by default
071: */
072: public boolean doFullThreadDump = Boolean.valueOf(
073: System.getProperty("xtest.FullThreadDump.do", "false"))
074: .booleanValue();
075:
076: TestProperties props;
077:
078: public RaveTestCase(String testName) {
079: super (testName);
080: props = new TestProperties();
081: dumpScreen = true;
082: }
083:
084: protected TestProperties getTestProperties() {
085: return (props);
086: }
087:
088: //@todo
089:
090: protected boolean waitNoEvent = true;
091:
092: // all code until end of class should be removed after JellyTestCase corresponding change - adding waitNoEvent member
093:
094: /** Overriden method from JUnit framework execution to perform conditional
095: * screen shot and conversion from TimeoutExpiredException to AssertionFailedError. <br>
096: * Waits a second before test execution.
097: * @throws Throwable Throwable
098: */
099: public void runBare() throws Throwable {
100:
101: //close the damn window
102: // if(Util.getMainWindow().
103: // findSubComponent(new DockablePaneOperator.DockablePaneFinder("JUnitTestRunnerExecutor"))
104: // != null) {
105: // new DockablePaneOperator("JUnitTestRunnerExecutor").hide();
106: // }
107: // workaround for JDK bug 4924516 (see below)
108: Toolkit.getDefaultToolkit().addAWTEventListener(
109: distributingHierarchyListener,
110: HierarchyEvent.HIERARCHY_EVENT_MASK);
111: // wait
112: if (waitNoEvent) {
113: new EventTool().waitNoEvent(1000);
114: }
115: try {
116: super .runBare();
117: } catch (ThreadDeath td) {
118: // ThreadDead must be re-throwed immediately
119: throw td;
120: } catch (Throwable th) {
121: // suite is notified about test failure so it can do some debug actions
122: try {
123: failNotify(th);
124: } catch (Exception e3) {
125: }
126: // screen capture is performed when test fails and in dependency on system property
127: if (captureScreen) {
128: try {
129: PNGEncoder.captureScreen(getWorkDir()
130: .getAbsolutePath()
131: + File.separator + "screen.png");
132: } catch (Exception e1) {
133: }
134: }
135: // XML dump is performed when test fails and in dependency on system property
136: if (dumpScreen) {
137: try {
138: Dumper.dumpAll(getWorkDir().getAbsolutePath()
139: + File.separator + "screen.xml");
140: } catch (Exception e2) {
141: }
142: }
143: // Full Thread Dump is performed when test fails and in dependency on system property
144: if (doFullThreadDump) {
145: try {
146: doFullThreadDump();
147: } catch (Exception e4) {
148: e4.printStackTrace();
149: System.out
150: .println("Dump for all threads is not created");
151: }
152: }
153: // closes all modal dialogs in dependency on systems property
154: if (closeAllModal)
155: try {
156: closeAllModal();
157: } catch (Exception e) {
158: }
159: if (th instanceof JemmyException) {
160: // all instancies of JemmyException are re-throwed as AssertionError (test failed)
161: throw new AssertionFailedErrorException(
162: th.getMessage(), th);
163: } else {
164: throw th;
165: }
166: } finally {
167: // workaround for JDK bug 4924516 (see below)
168: Toolkit.getDefaultToolkit().removeAWTEventListener(
169: distributingHierarchyListener);
170: }
171: }
172:
173: public static Properties getDeploymentTargetProperties(
174: String path_to_file) {
175: Properties properties = new Properties();
176: try {
177: System.out.println("path to file is \"" + path_to_file
178: + "\".");
179: properties.load(new FileInputStream(path_to_file));
180: } catch (Exception e) {
181: System.out.println("Properties can not be loaded!");
182: System.out.println("e=" + e.toString());
183: return null;
184: }
185: return properties;
186: }
187:
188: public static Properties getDeploymentTargetProperties() {
189: String sep = File.separator;
190: String path = System.getProperty("xtest.data.dir");
191: path = path + sep + "DeploymentTargets.properties";
192: return getDeploymentTargetProperties(path);
193: }
194:
195: public static Properties getDefaultDeploymentTargetProperties() {
196: String sep = File.separator;
197: String path = System.getProperty("xtest.data.dir");
198: path = path + sep + "DefaultDeploymentTargets.properties";
199: return getDeploymentTargetProperties(path);
200: }
201:
202: private void doFullThreadDump() {
203: try {
204: String xtestWorkdir = System.getProperty("xtest.workdir");
205: File idePidFile = new File(xtestWorkdir, "ide.pid");
206: LineNumberReader reader = new LineNumberReader(
207: new FileReader(idePidFile));
208: String line = reader.readLine();
209: assertNotNull("Cannot read PID from file " + idePidFile,
210: line);
211: long pid = Long.parseLong(line);
212: System.out.println();
213: System.out.println("Full Thread Dump - BEGIN");
214: boolean result = NativeKill.dumpProcess(pid);
215: TestUtils.wait(2000);
216: System.out.println("Full Thread Dump - END");
217: System.out.println();
218: assertTrue("NativeKill.dumpProcess(" + pid + ") failed.",
219: result);
220: } catch (IOException ioe) {
221: System.out.println("IOException was thrown!");
222: ioe.printStackTrace();
223: }
224: try {
225: FileOutputStream fos = new FileOutputStream(getWorkDir()
226: .getAbsolutePath()
227: + File.separator + "threads.dump");
228: PrintWriter pw = new PrintWriter(fos);
229: pw.println("Full thread dump Java HotSpot(TM) Client VM");
230: pw.println();
231: Map threadsMap = Thread.getAllStackTraces();
232: Iterator keys = threadsMap.keySet().iterator();
233: Iterator values = threadsMap.values().iterator();
234: Thread key;
235: StackTraceElement[] value;
236: while (keys.hasNext()) {
237: key = ((Thread) (keys.next()));
238: String daemon = key.isDaemon() ? " daemon" : "";
239: pw.println("\"" + key.getName() + "\"" + daemon
240: + " prio=" + key.getPriority() + " id="
241: + key.getId() + " ThreadGroup="
242: + key.getThreadGroup().getName());
243: value = ((StackTraceElement[]) (values.next()));
244: for (int i = 0; i < value.length; i++)
245: pw.println(" " + value[i].toString());
246: pw.println();
247: }
248: pw.close();
249: } catch (FileNotFoundException fnfe) {
250: System.out.println("FileNotFoundException was thrown!");
251: fnfe.printStackTrace();
252: } catch (IOException ioe) {
253: System.out.println("IOException was thrown!");
254: ioe.printStackTrace();
255: }
256: }
257:
258: /* Workaround for JDK bug http://developer.java.sun.com/developer/bugParade/bugs/4924516.html.
259: * Also see issue http://www.netbeans.org/issues/show_bug.cgi?id=32466.
260: * ------------------------------------------------------------------------------------------
261: * It can be removed when it is fixed (probably in JDK1.5.0). The following
262: * listener is added to Toolkit at runBare() method and removed when it finishes.
263: * It distributes HierarchyEvent to all listening components and its subcomponents.
264: */
265: private static final RaveTestCase.DistributingHierarchyListener distributingHierarchyListener = new RaveTestCase.DistributingHierarchyListener();
266:
267: private static class DistributingHierarchyListener implements
268: AWTEventListener {
269:
270: public DistributingHierarchyListener() {
271: }
272:
273: public void eventDispatched(java.awt.AWTEvent aWTEvent) {
274: HierarchyEvent hevt = null;
275: if (aWTEvent instanceof HierarchyEvent) {
276: hevt = (HierarchyEvent) aWTEvent;
277: }
278: if (hevt != null
279: && ((HierarchyEvent.SHOWING_CHANGED & hevt
280: .getChangeFlags()) != 0)) {
281: distributeShowingEvent(hevt.getComponent(), hevt);
282: }
283: }
284:
285: private static void distributeShowingEvent(Component c,
286: HierarchyEvent hevt) {
287: //HierarchyListener[] hierarchyListeners = c.getHierarchyListeners();
288: // Need to use component.getListeners because it is not synchronized
289: // and it not cause deadlock
290: HierarchyListener[] hierarchyListeners = (HierarchyListener[]) (c
291: .getListeners(HierarchyListener.class));
292: if (hierarchyListeners != null) {
293: for (int i = 0; i < hierarchyListeners.length; i++) {
294: hierarchyListeners[i].hierarchyChanged(hevt);
295: }
296: }
297: if (c instanceof Container) {
298: Container cont = (Container) c;
299: int n = cont.getComponentCount();
300: for (int i = 0; i < n; i++) {
301: distributeShowingEvent(cont.getComponent(i), hevt);
302: }
303: }
304: }
305: }
306: }
|