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-2006 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.openide.util;
043:
044: import java.awt.AWTEvent;
045: import java.awt.Dialog;
046: import java.awt.Frame;
047: import java.awt.Graphics;
048: import java.awt.Toolkit;
049: import java.awt.event.AWTEventListener;
050: import java.awt.event.ActionEvent;
051: import java.awt.event.ActionListener;
052: import java.util.ArrayList;
053: import java.util.EventListener;
054: import javax.swing.JPanel;
055: import javax.swing.SwingUtilities;
056: import javax.swing.Timer;
057: import org.netbeans.junit.NbTestCase;
058:
059: /**
060: *
061: * @author Dafe Simonek
062: */
063: public class InitJobTest extends NbTestCase {
064: /** testing dialog instance */
065: Dialog dlg;
066: /** arrays which hold calls history */
067: ArrayList constructCalls, finishCalls, cancelCalls;
068: /** event dispatch thread */
069: Thread edThread;
070: /** test component */
071: SimpleInitComp comp;
072: /** parent, main frame */
073: private Frame frame;
074:
075: /** Creates a new instance of UtilProgressCursorTest */
076: public InitJobTest(String testName) {
077: super (testName);
078: }
079:
080: /** Run tests in EQ thread, as it touches Swing */
081: protected boolean runInEQ() {
082: return true;
083: }
084:
085: /** Basic testing of Utilities.attachInitJob, if calls to AsyncGUIJob
086: * impl conforms to the API behaviour described in javadoc *
087: */
088: public void testInitJob() throws Exception {
089: System.out.println("Testing simple init job run");
090: initializeSimple();
091: comp = new SimpleInitComp();
092: Utilities.attachInitJob(comp, comp);
093: frame = new Frame();
094: frame.setSize(100, 100);
095: frame.setVisible(true);
096: dlg = new Dialog(frame, true);
097: dlg.setSize(50, 50);
098: dlg.add(comp);
099: dlg.setVisible(true);
100: }
101:
102: public void testCancelAbility() throws Exception {
103: System.out.println("Testing cancel ability of async init job");
104: initializeSimple();
105: initCancelResults();
106: CancelInitComp comp = new CancelInitComp();
107: Utilities.attachInitJob(comp, comp);
108: frame = new Frame();
109: frame.setSize(100, 100);
110: frame.setVisible(true);
111: dlg = new Dialog(frame, true);
112: dlg.setSize(50, 50);
113: dlg.add(comp);
114: dlg.setVisible(true);
115: }
116:
117: /**********************************************************************/
118:
119: private void constructCalled(Thread thread, long time) {
120: constructCalls.add(new CallData(thread, time));
121: }
122:
123: private void finishCalled(Thread thread, long time) {
124: finishCalls.add(new CallData(thread, time));
125: }
126:
127: private void cancelCalled() {
128: cancelCalls.add(new CallData(Thread.currentThread(), System
129: .currentTimeMillis()));
130: }
131:
132: private void checkSimpleResults() {
133: if (constructCalls.size() != 1) {
134: fail("AsyncGUIJob.construct was called "
135: + constructCalls.size()
136: + " times intead of just once.");
137: }
138: if (finishCalls.size() != 1) {
139: fail("AsyncGUIJob.finish was called " + finishCalls.size()
140: + " times intead of just once.");
141: }
142: CallData constructCall = (CallData) constructCalls.get(0);
143: CallData finishCall = (CallData) finishCalls.get(0);
144: if (constructCall.thread.equals(edThread)) {
145: fail("AsyncGUIJob.construct *was* called from event dispatch thread, "
146: + "which is wrong.");
147: }
148: if (!finishCall.thread.equals(edThread)) {
149: fail("AsyncGUIJob.finish *was not* called from event dispatch thread, "
150: + "which is wrong.");
151: }
152: if (constructCall.time > finishCall.time) {
153: fail("AsyncGUIJob.finish was called before AsyncGUIJob.construct, "
154: + "which is wrong.");
155: }
156: AWTEventListener[] awtListeners = Toolkit.getDefaultToolkit()
157: .getAWTEventListeners(AWTEvent.PAINT_EVENT_MASK);
158: for (int i = 0; i < awtListeners.length; i++) {
159: if (awtListeners[i].getClass().equals(
160: AsyncInitSupport.class)) {
161: fail("Probable memory leak: AsyncInitSupport didn't detached "
162: + "from AWT toolkit.");
163: }
164: }
165: EventListener[] listeners = comp
166: .getListeners(AsyncInitSupport.class);
167: if (listeners.length != 0) {
168: fail("Probable memory leak: AsyncInitSupport didn't detached "
169: + "from component being inited " + comp);
170: }
171: }
172:
173: private void checkCancelResults() {
174: if (cancelCalls.size() != 1) {
175: fail("Cancellable.cancel was called " + cancelCalls.size()
176: + " times intead of just once.");
177: }
178: if (finishCalls.size() != 0) {
179: fail("AsyncGUIJob.finish should not been called at all, but was called "
180: + finishCalls.size() + " times.");
181: }
182: }
183:
184: private void initializeSimple() throws Exception {
185: constructCalls = new ArrayList();
186: finishCalls = new ArrayList();
187: if (SwingUtilities.isEventDispatchThread()) {
188: edThread = Thread.currentThread();
189: } else {
190: SwingUtilities.invokeAndWait(new Runnable() {
191: public void run() {
192: edThread = Thread.currentThread();
193: }
194: });
195: }
196: }
197:
198: private void initCancelResults() {
199: cancelCalls = new ArrayList();
200: }
201:
202: /** Structure for holding data of method call */
203: private final static class CallData {
204: Thread thread;
205: long time;
206:
207: public CallData(Thread thread, long time) {
208: this .thread = thread;
209: this .time = time;
210: }
211: }
212:
213: /** Disposer of windows */
214: private final class TimerListener implements ActionListener {
215: /** true for cancel test, false otherwise */
216: private boolean cancel;
217:
218: public TimerListener(boolean cancel) {
219: this .cancel = cancel;
220: }
221:
222: public void actionPerformed(ActionEvent e) {
223: dlg.dispose();
224: frame.dispose();
225: if (cancel) {
226: checkCancelResults();
227: } else {
228: checkSimpleResults();
229: }
230: }
231: }
232:
233: /** Testing component for asynchronous init
234: */
235: private final class SimpleInitComp extends JPanel implements
236: AsyncGUIJob {
237:
238: /** Worker method, can be called in any thread but event dispatch thread.
239: * Implement your time consuming work here.
240: * Always called and completed before {@link #finished} method.
241: *
242: */
243: public void construct() {
244: constructCalled(Thread.currentThread(), System
245: .currentTimeMillis());
246: }
247:
248: /** Method to update UI using given data constructed in {@link #construct}
249: * method. Always called in event dispatch thread, after {@link #construct}
250: * method completed its execution.
251: *
252: */
253: public void finished() {
254: finishCalled(Thread.currentThread(), System
255: .currentTimeMillis());
256: }
257:
258: public void paint(Graphics g) {
259: super .paint(g);
260: Timer timer = new Timer(1000, new TimerListener(false));
261: timer.setRepeats(false);
262: timer.start();
263: }
264:
265: } // end of SimpleInitComp
266:
267: /** Testing component for cancel during asynchronous init
268: */
269: private final class CancelInitComp extends JPanel implements
270: AsyncGUIJob, Cancellable {
271:
272: /** Worker method, can be called in any thread but event dispatch thread.
273: * Implement your time consuming work here.
274: * Always called and completed before {@link #finished} method.
275: *
276: */
277: public void construct() {
278: // perform loooong task
279: try {
280: Thread.sleep(2000);
281: } catch (InterruptedException exc) {
282: // continue...
283: }
284: }
285:
286: /** Method to update UI using given data constructed in {@link #construct}
287: * method. Always called in event dispatch thread, after {@link #construct}
288: * method completed its execution.
289: *
290: */
291: public void finished() {
292: finishCalled(Thread.currentThread(), System
293: .currentTimeMillis());
294: }
295:
296: public void paint(Graphics g) {
297: super .paint(g);
298: Timer timer = new Timer(1000, new TimerListener(true));
299: timer.setRepeats(false);
300: timer.start();
301: }
302:
303: /** Cancel processing of the job.
304: *
305: */
306: public boolean cancel() {
307: cancelCalled();
308: return true;
309: }
310:
311: } // end of SimpleInitComp
312:
313: }
|