| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.netbeans.modules.progress.ui; |
| |
| import java.awt.Dimension; |
| import java.awt.EventQueue; |
| import java.awt.Frame; |
| import java.awt.GraphicsEnvironment; |
| import java.awt.Image; |
| import java.awt.RenderingHints; |
| import java.awt.Toolkit; |
| import java.awt.event.WindowEvent; |
| import java.awt.event.WindowListener; |
| import java.beans.PropertyChangeListener; |
| import java.util.Map; |
| import java.util.Random; |
| import java.util.Set; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.Future; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| import javax.swing.Action; |
| import javax.swing.JFrame; |
| import junit.framework.AssertionFailedError; |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| import org.netbeans.api.progress.ProgressHandle; |
| import org.openide.nodes.Node; |
| import org.openide.util.Exceptions; |
| import org.openide.windows.Mode; |
| import org.openide.windows.TopComponent; |
| import org.openide.windows.TopComponentGroup; |
| import org.openide.windows.WindowManager; |
| import org.netbeans.api.progress.ProgressHandleFactory; |
| import org.netbeans.api.progress.ProgressRunnable; |
| import org.netbeans.api.progress.ProgressUtils; |
| import org.netbeans.junit.MockServices; |
| import org.netbeans.junit.NbTestCase; |
| import org.openide.util.Lookup; |
| import org.openide.util.RequestProcessor; |
| import org.openide.windows.Workspace; |
| |
| /** |
| * |
| * @author Tim Boudreau |
| */ |
| public class RunOffEDTImplTest extends NbTestCase { |
| |
| public static Test suite() { |
| return GraphicsEnvironment.isHeadless() ? new TestSuite() : new TestSuite(RunOffEDTImplTest.class); |
| } |
| |
| public RunOffEDTImplTest(String name) { |
| super(name); |
| } |
| |
| public void setUp() { |
| MockServices.setServices(WM.class, RunOffEDTImpl.class); |
| } |
| |
| private static boolean canTestGlassPane() { |
| Map<?,?> hintsMap = (Map)(Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints")); //NOI18N |
| //Avoid translucent painting on, for example, remote X terminal |
| return hintsMap == null || !RenderingHints.VALUE_TEXT_ANTIALIAS_OFF.equals(hintsMap.get(RenderingHints.KEY_TEXT_ANTIALIASING)); |
| } |
| |
| public void testShowProgressDialogAndRun_3args_1_EQ() throws Exception { |
| final CountDownLatch latch = new CountDownLatch(1); |
| EventQueue.invokeLater(new Runnable() { |
| |
| @Override |
| public void run() { |
| try { |
| testShowProgressDialogAndRun_3args_1(); |
| } finally { |
| latch.countDown(); |
| } |
| } |
| }); |
| latch.await(); |
| } |
| |
| public void testShowProgressDialogAndRun_3args_2_EQ() throws Exception { |
| final CountDownLatch latch = new CountDownLatch(1); |
| EventQueue.invokeLater(new Runnable() { |
| |
| @Override |
| public void run() { |
| try { |
| testShowProgressDialogAndRun_3args_2(); |
| } catch (AssertionFailedError e) { |
| throw e; |
| } catch (Exception ex) { |
| throw new RuntimeException (ex); |
| } finally { |
| latch.countDown(); |
| } |
| } |
| }); |
| latch.await(); |
| } |
| |
| public void testShowProgressDialogAndRunLater() throws Exception { |
| final WM wm = Lookup.getDefault().lookup(WM.class); |
| //make sure main window is on screen before proceeding |
| wm.await(); |
| final JFrame jf = (JFrame) WindowManager.getDefault().getMainWindow(); |
| final CountDownLatch countDown = new CountDownLatch(1); |
| final AtomicBoolean glassPaneFound = new AtomicBoolean(false); |
| final boolean testGlassPane = canTestGlassPane(); |
| class R implements ProgressRunnable<String> { |
| volatile boolean hasRun; |
| @Override |
| public String run(ProgressHandle handle) { |
| try { |
| wm.waitForGlassPane(); |
| if (testGlassPane) { |
| glassPaneFound.set(jf.getGlassPane() instanceof RunOffEDTImpl.TranslucentMask); |
| } |
| hasRun = true; |
| return "Done"; |
| } finally { |
| countDown.countDown(); |
| } |
| } |
| } |
| R r = new R(); |
| Future<String> f = ProgressUtils.showProgressDialogAndRunLater(r, ProgressHandleFactory.createHandle("Something"), true); |
| assertNotNull (f); |
| assertEquals ("Done", f.get()); |
| countDown.await(); |
| assertTrue (r.hasRun); |
| assertFalse (f.isCancelled()); |
| assertTrue (f.isDone()); |
| assertEquals ("Done", f.get()); |
| assertTrue ("Glass pane not set", !testGlassPane || glassPaneFound.get()); |
| } |
| |
| public void testShowProgressDialogAndRunLaterEQ() throws Throwable { |
| EventQueue.invokeAndWait(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| testShowProgressDialogAndRunLater(); |
| } catch (Exception ex) { |
| throw new AssertionError(ex); |
| } |
| } |
| }); |
| } |
| |
| public void testShowProgressDialogAndRun_3args_1() { |
| assertEquals ("Done", ProgressUtils.showProgressDialogAndRun(new CB(), "Doing Stuff", true)); |
| } |
| |
| public void testShowProgressDialogAndRun_3args_2() throws InterruptedException { |
| final WM wm = Lookup.getDefault().lookup(WM.class); |
| //make sure main window is on screen before proceeding |
| wm.await(); |
| final JFrame jf = (JFrame) WindowManager.getDefault().getMainWindow(); |
| final CountDownLatch countDown = new CountDownLatch(1); |
| final AtomicBoolean glassPaneFound = new AtomicBoolean(false); |
| final boolean testGlassPane = canTestGlassPane(); |
| class R implements Runnable { |
| volatile boolean hasRun; |
| @Override |
| public void run() { |
| try { |
| wm.waitForGlassPane(); |
| if (testGlassPane) { |
| glassPaneFound.set(jf.getGlassPane() instanceof RunOffEDTImpl.TranslucentMask); |
| } |
| hasRun = true; |
| } finally { |
| countDown.countDown(); |
| } |
| } |
| } |
| R r = new R(); |
| ProgressUtils.showProgressDialogAndRun(r, "Something"); |
| countDown.await(); |
| assertTrue (r.hasRun); |
| assertTrue ("Glass pane not set", !testGlassPane || glassPaneFound.get()); |
| } |
| |
| public void testStressWithRandomContention() throws InterruptedException, Exception { |
| Random r = new Random(123456789); |
| for (int i = 0; i < 30; i++) { |
| testShowProgressDialogAndRun_3args_1(); |
| createRandomContention(r); |
| testShowProgressDialogAndRun_3args_1_EQ(); |
| createRandomContention(r); |
| testShowProgressDialogAndRun_3args_2(); |
| createRandomContention(r); |
| testShowProgressDialogAndRun_3args_2_EQ(); |
| } |
| } |
| |
| private void createRandomContention(final Random r) throws Exception { |
| if (r.nextInt(10) > 7) { |
| RequestProcessor rp = new RequestProcessor(this.getClass().getName()); |
| for (int i= 0; i < r.nextInt(5); i++) { |
| rp.post(new Runnable() { |
| |
| @Override |
| public void run() { |
| try { |
| //No, Jesse, this will not affect the test |
| //passing or failing unless something else is |
| //broken |
| Thread.sleep(r.nextInt(200)); |
| } catch (InterruptedException ex) { |
| //do nothing |
| } |
| } |
| }); |
| EventQueue.invokeAndWait(new Runnable() { |
| |
| @Override |
| public void run() { |
| try { |
| Thread.sleep(r.nextInt(200)); |
| } catch (InterruptedException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| }); |
| } |
| } |
| } |
| |
| private class CB implements ProgressRunnable<String> { |
| |
| @Override |
| public String run(ProgressHandle handle) { |
| handle.switchToDeterminate(5); |
| for (int i= 0; i < 5; i++) { |
| handle.progress("Job " + i, i); |
| } |
| return "Done"; |
| } |
| |
| } |
| |
| private static final class JF extends JFrame { |
| boolean inited; |
| private final CountDownLatch waitForGlassPane = new CountDownLatch(1); |
| |
| JF () { |
| super ("Main Window"); |
| inited = true; |
| } |
| |
| @Override |
| public void addNotify() { |
| super.addNotify(); |
| inited = true; |
| } |
| |
| @Override |
| public void setGlassPane(java.awt.Component glassPane) { |
| super.setGlassPane(glassPane); |
| if (inited && glassPane instanceof RunOffEDTImpl.TranslucentMask) { |
| waitForGlassPane.countDown(); |
| } |
| } |
| |
| } |
| |
| public static final class WM extends WindowManager implements WindowListener { |
| |
| private final JF jf = new JF(); |
| private CountDownLatch latch = new CountDownLatch(1); |
| public WM() { |
| jf.addWindowListener(this); |
| jf.setPreferredSize(new Dimension(400, 400)); |
| jf.setVisible(true); |
| } |
| |
| public void waitForGlassPane() { |
| try { |
| jf.waitForGlassPane.await(); |
| } catch (InterruptedException ex) { |
| Exceptions.printStackTrace(ex); |
| } |
| } |
| |
| public void await() { |
| if (!jf.isDisplayable()) { |
| try { |
| latch.await(); |
| } catch (InterruptedException ex) { |
| throw new IllegalStateException(ex); |
| } |
| } |
| } |
| |
| @Override |
| public Mode findMode(String name) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public Mode findMode(TopComponent tc) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public Set<? extends Mode> getModes() { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public Frame getMainWindow() { |
| return jf; |
| } |
| |
| @Override |
| public void updateUI() { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected Component createTopComponentManager(TopComponent c) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public Workspace createWorkspace(String name, String displayName) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public Workspace findWorkspace(String name) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public Workspace[] getWorkspaces() { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public void setWorkspaces(Workspace[] workspaces) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public Workspace getCurrentWorkspace() { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public TopComponentGroup findTopComponentGroup(String name) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public void addPropertyChangeListener(PropertyChangeListener l) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public void removePropertyChangeListener(PropertyChangeListener l) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentOpen(TopComponent tc) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentClose(TopComponent tc) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentRequestActive(TopComponent tc) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentRequestVisible(TopComponent tc) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentDisplayNameChanged(TopComponent tc, String displayName) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentHtmlDisplayNameChanged(TopComponent tc, String htmlDisplayName) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentToolTipChanged(TopComponent tc, String toolTip) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentIconChanged(TopComponent tc, Image icon) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected void topComponentActivatedNodesChanged(TopComponent tc, Node[] activatedNodes) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected boolean topComponentIsOpened(TopComponent tc) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected Action[] topComponentDefaultActions(TopComponent tc) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| protected String topComponentID(TopComponent tc, String preferredID) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public TopComponent findTopComponent(String tcID) { |
| throw new UnsupportedOperationException("Not supported yet."); |
| } |
| |
| @Override |
| public void windowOpened(WindowEvent e) { |
| latch.countDown(); |
| } |
| |
| @Override |
| public void windowClosing(WindowEvent e) { |
| //do nothing |
| } |
| |
| @Override |
| public void windowClosed(WindowEvent e) { |
| //do nothing |
| } |
| |
| @Override |
| public void windowIconified(WindowEvent e) { |
| //do nothing |
| } |
| |
| @Override |
| public void windowDeiconified(WindowEvent e) { |
| //do nothing |
| } |
| |
| @Override |
| public void windowActivated(WindowEvent e) { |
| //do nothing |
| } |
| |
| @Override |
| public void windowDeactivated(WindowEvent e) { |
| //do nothing |
| } |
| } |
| } |