1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  @test
  26  @summary See <rdar://problem/3429130>: Events: actionPerformed() method not called when it is button is clicked (system load related)
  27  @summary com.apple.junit.java.awt.Frame
  28  @library ../../../regtesthelpers
  29  @build VisibilityValidator
  30  @build RobotUtilities
  31  @build Waypoint
  32  @run junit NestedModelessDialogTest
  33  */
  34 
  35 ///////////////////////////////////////////////////////////////////////////////////////
  36 //  NestedModelessDialogTest.java
  37 // The test launches a parent frame. From this parent frame it launches a modal dialog
  38 // From the modal dialog it launches a modeless dialog with a text field in it and tries
  39 // to write into the text field. The test succeeds if you are successfully able to write
  40 // into this Nested Modeless Dialog
  41 /////////////////////////////////////////////////////////////////////////////////////
  42 
  43 // classes necessary for this test
  44 import junit.framework.*;
  45 import java.awt.*;
  46 import java.awt.event.*;
  47 import java.util.Enumeration;
  48 
  49 import test.java.awt.regtesthelpers.RobotUtilities;
  50 import test.java.awt.regtesthelpers.VisibilityValidator;
  51 import test.java.awt.regtesthelpers.Waypoint;
  52 
  53 
  54 public class NestedModelessDialogTest extends TestCase {
  55 
  56     public static Test suite() {
  57         return new TestSuite(NestedModelessDialogTest.class);
  58     }
  59 
  60     Waypoint[]             event_checkpoint = new Waypoint[3];
  61     VisibilityValidator[] win_checkpoint = new VisibilityValidator[2];
  62 
  63     IntermediateDialog     interDiag;
  64     TextDialog             txtDiag;
  65 
  66     // Global variables so the robot thread can locate things.
  67     Button[]             robot_button = new Button[2];
  68     TextField            robot_text = null;
  69 
  70     /**
  71      * Get called by test harness
  72      * @throws Exception
  73      */
  74 
  75     public void testModelessDialogs() throws Exception  {
  76         Frame        frame = null;
  77         String        result = "";
  78 
  79         event_checkpoint[0] = new Waypoint(); // "-Launch 1-"
  80         event_checkpoint[1] = new Waypoint(); // "-Launch 2-"
  81 
  82         try {
  83             // Thread.currentThread().setName("NestedModelessDialogTest Thread");
  84             // launch first frame with fistButton
  85             frame = new StartFrame();
  86             VisibilityValidator.setVisibleAndConfirm(frame);
  87 
  88             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
  89             RobotUtilities.click (robot_button[0]);
  90 
  91             // Dialog must be created and onscreen before we proceed.
  92             //   The event_checkpoint waits for the Dialog to be created.
  93             //   The win_checkpoint waits for the Dialog to be visible.
  94 
  95             event_checkpoint[0].requireClear();
  96             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
  97             assertTrue( "TestFrame actionPerformed() never called, see <rdar://problem/3429130>", event_checkpoint[0].isValid() );
  98 
  99             win_checkpoint[0].requireVisible();
 100             assertTrue( "Could not confirm intermediate dialog was visible", win_checkpoint[0].isValid() );
 101 
 102             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
 103             RobotUtilities.click (robot_button[1]);
 104 
 105             // Again, the Dialog must be created and onscreen before we proceed.
 106             //   The event_checkpoint waits for the Dialog to be created.
 107             //   The win_checkpoint waits for the Dialog to be visible.
 108 
 109             event_checkpoint[1].requireClear();
 110             Thread.sleep(250); // shouldn't need this, remove when 3429130 is addressed
 111             assertTrue( "IntermediateDialog actionPerformed() never called, see <rdar://problem/3429130>", event_checkpoint[1].isValid() );
 112 
 113             win_checkpoint[1].requireVisible();
 114             assertTrue( "Could not confirm test dialog was visible", win_checkpoint[1].isValid() );
 115 
 116             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
 117             RobotUtilities.click(robot_text);
 118 
 119             // I'm really not sure whether the click is needed for focus
 120             // but since it's asynchronous, as is the actually gaining of focus
 121             // we might as well do our best
 122             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
 123             try { EventQueue.invokeAndWait(new Runnable() { public void run() {} }); } catch (Exception e) {}
 124 
 125             RobotUtilities.pressKey(KeyEvent.VK_SHIFT);
 126             RobotUtilities.typeKey(KeyEvent.VK_H);
 127             RobotUtilities.releaseKey(KeyEvent.VK_SHIFT);
 128             RobotUtilities.typeKey(KeyEvent.VK_E);
 129             RobotUtilities.typeKey(KeyEvent.VK_L);
 130             RobotUtilities.typeKey(KeyEvent.VK_L);
 131             RobotUtilities.typeKey(KeyEvent.VK_O);
 132 
 133             //
 134             // NOTE THAT WE MAY HAVE MORE SYNCHRONIZATION WORK TO DO HERE.
 135             // CURRENTLY THERE IS NO GUARANTEE THAT THE KEYEVENT THAT THAT
 136             // TYPES THE 'O' HAS BEEN PROCESSED BEFORE WE GET THE RESULT
 137             //
 138 
 139             // This is a (lame) attempt at waiting for the last typeKey events to propagate
 140             // It's not quite right because robot uses CGRemoteOperations, which are asynchronous
 141             // But that's why I put in the Thread.sleep
 142             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
 143             try { EventQueue.invokeAndWait(new Runnable() { public void run() {} }); } catch (Exception e) {}
 144 
 145             // We really need to call this before the dialog that robot_text is in is disposed
 146             result = robot_text.getText();
 147 
 148             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
 149             RobotUtilities.clickAt(txtDiag, 14,10); // Click Close box of modeless dialog with textField
 150 
 151             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
 152             RobotUtilities.clickAt(interDiag, 14,10); // Click Close box of intermediate modal dialog
 153 
 154             Thread.sleep(250); // shouldn't need this, but Thread.sleep adds stability
 155             RobotUtilities.clickAt(frame, 14,10); // Click Close box of intermediate modal dialog
 156         }
 157         finally {
 158             frame.setVisible(false);
 159             frame.dispose();
 160         }
 161 
 162         String expected = "Hello";
 163         assertEquals("Bad result from getText().\n\nExpected: \n\t*" + expected +"*\nActual:\n\t*"+result +"*\n",expected, result );
 164 
 165     }
 166 
 167 
 168 //////////////////// Start Frame ///////////////////
 169 /**
 170  * Launches the first frame with a button in it
 171  */
 172 
 173 class StartFrame extends Frame {
 174      /**
 175      * Constructs a new instance.
 176      */
 177     public StartFrame() {
 178         super("First Frame");
 179         setLayout(new GridBagLayout());
 180         setLocation(375, 200);
 181         setSize(271,161);
 182         Button but = new Button("Make Intermediate");
 183         but.addActionListener(new java.awt.event.ActionListener() {
 184             public void actionPerformed(ActionEvent e) {
 185                 interDiag = new IntermediateDialog(StartFrame.this);
 186                 win_checkpoint[0] = new VisibilityValidator(interDiag);
 187                 interDiag.setSize(300, 200);
 188 
 189                 // may need listener to watch this move.
 190                 interDiag.setLocation(getLocationOnScreen());
 191                 interDiag.pack();
 192                 event_checkpoint[0].clear();
 193                 interDiag.setVisible(true);        // <--- thread stops here until the modal dialog is closed
 194             }
 195         });
 196         Panel  pan = new Panel();
 197         pan.add(but);
 198         add(pan);
 199         robot_button[0] = but;
 200         addWindowListener(new WindowAdapter() {
 201             public void windowClosing(WindowEvent e) {
 202                 setVisible(false);
 203                 dispose();
 204             }
 205         });
 206     }
 207 
 208  }
 209 
 210 ///////////////////////////// VARIOUS DIALOGS //////////////////////////////////
 211 
 212 
 213 /* A Dialog that launches a sub-dialog */
 214  class IntermediateDialog extends Dialog {
 215     Dialog m_parent;
 216 
 217     public IntermediateDialog(Frame parent) {
 218         super(parent, "Intermediate Modal", true /*Modal*/);
 219         m_parent = this;
 220         Button but = new Button("Make Text");
 221         but.addActionListener(new java.awt.event.ActionListener() {
 222             public void actionPerformed(ActionEvent e) {
 223                 txtDiag = new TextDialog(m_parent);
 224                 win_checkpoint[1] = new VisibilityValidator(txtDiag);
 225                 txtDiag.setSize(300, 100);
 226                 event_checkpoint[1].clear();
 227                 txtDiag.setVisible(true);    // <--- thread stops here until the modal dialog is closed
 228             }
 229         });
 230         Panel  pan = new Panel();
 231         pan.add(but);
 232         add(pan);
 233         pack();
 234         addWindowListener(new WindowAdapter() {
 235             public void windowClosing(WindowEvent e) {
 236                 setVisible(false);
 237                 dispose();
 238             }
 239         });
 240 
 241         // The robot needs to know about us, so set global
 242         robot_button[1] = but;
 243     }
 244   }
 245 
 246 /* A Dialog that just holds a text field */
 247  class TextDialog extends Dialog {
 248     public TextDialog(Dialog parent) {
 249         super(parent, "Modeless Dialog", false /*Modeless*/);
 250         TextField txt = new TextField("",10);
 251         Panel  pan = new Panel();
 252         pan.add(txt);
 253         add(pan);
 254         pack();
 255         addWindowListener(new WindowAdapter() {
 256             public void windowClosing(WindowEvent e) {
 257                 setVisible(false);
 258                 dispose();
 259             }
 260          });
 261 
 262 
 263         // The robot needs to know about us, so set global
 264          robot_text = txt;
 265   }
 266 
 267 }
 268 
 269     public static void main (String[] args) throws RuntimeException {
 270         try {
 271             TestResult tr = junit.textui.TestRunner.run(suite());
 272 
 273             int numErrors = tr.errorCount();
 274             if (numErrors != 0) {
 275                 Enumeration e = tr.errors();
 276                 while (e.hasMoreElements()) {
 277                     System.out.println(e.nextElement());
 278                 }
 279 
 280             }
 281             int numFailures = tr.failureCount();
 282             if (numFailures != 0) {
 283                 Enumeration e = tr.failures();
 284                 while (e.hasMoreElements()) {
 285                     System.out.println(e.nextElement());
 286                 }
 287             }
 288             if ((numErrors != 0) || (numFailures != 0)){
 289                 throw new RuntimeException("Test encountered " + numErrors + " errors and " + numFailures + " failures.");
 290             }
 291         }
 292         catch (Exception e) {
 293             throw new RuntimeException(e.getMessage());
 294         }
 295     }
 296 }
 297 
 298