1 /* 2 * Copyright (c) 2006, 2014, 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 @bug 6382144 27 @summary REGRESSION: InputVerifier and JOptionPane 28 @author oleg.sukhodolsky: area=awt.focus 29 @run main EndlessLoopTest 30 */ 31 32 /** 33 * EndlessLoopTest.java 34 * 35 * summary: REGRESSION: InputVerifier and JOptionPane 36 */ 37 38 import java.awt.AWTException; 39 import java.awt.BorderLayout; 40 import java.awt.Component; 41 import java.awt.Dialog; 42 import java.awt.Frame; 43 import java.awt.Point; 44 import java.awt.Robot; 45 import java.awt.TextArea; 46 import java.awt.Toolkit; 47 48 import java.awt.event.ActionEvent; 49 import java.awt.event.ActionListener; 50 import java.awt.event.InputEvent; 51 import java.awt.event.KeyEvent; 52 53 import javax.swing.InputVerifier; 54 import javax.swing.JButton; 55 import javax.swing.JComponent; 56 import javax.swing.JDialog; 57 import javax.swing.JFrame; 58 import javax.swing.JTextField; 59 60 public class EndlessLoopTest 61 { 62 63 //*** test-writer defined static variables go here *** 64 static volatile int n_iv_calls; 65 66 67 private static void init() 68 { 69 //*** Create instructions for the user here *** 70 71 String[] instructions = 72 { 73 "This is an AUTOMATIC test, simply wait until it is done.", 74 "The result (passed or failed) will be shown in the", 75 "message window below." 76 }; 77 Sysout.createDialog( ); 78 Sysout.printInstructions( instructions ); 79 80 JFrame frame = new JFrame(); 81 final JDialog dialog = new JDialog(frame, true); 82 JButton button = new JButton("press me"); 83 button.addActionListener(new ActionListener() { 84 public void actionPerformed(ActionEvent ae) { 85 dialog.dispose(); 86 } 87 }); 88 dialog.getContentPane().add(button); 89 dialog.pack(); 90 91 JTextField t1 = new JTextField(); 92 t1.setInputVerifier(new InputVerifier() { 93 public boolean verify(JComponent input) { 94 n_iv_calls++; 95 if (n_iv_calls == 1) { 96 dialog.setVisible(true); 97 } 98 return true; 99 } 100 }); 101 JTextField t2 = new JTextField(); 102 103 104 frame.getContentPane().add(t1, BorderLayout.NORTH); 105 frame.getContentPane().add(t2, BorderLayout.SOUTH); 106 frame.setSize(200, 200); 107 frame.setVisible(true); 108 109 Robot r = null; 110 try { 111 r = new Robot(); 112 } catch (AWTException e) { 113 EndlessLoopTest.fail(e); 114 } 115 116 try { 117 r.waitForIdle(); 118 119 mouseClickOnComp(r, t1); 120 r.waitForIdle(); 121 122 if (!t1.isFocusOwner()) { 123 throw new RuntimeException("t1 is not a focus owner"); 124 } 125 n_iv_calls = 0; 126 r.keyPress(KeyEvent.VK_TAB); 127 r.delay(10); 128 r.keyRelease(KeyEvent.VK_TAB); 129 r.waitForIdle(); 130 131 mouseClickOnComp(r, button); 132 r.waitForIdle(); 133 } catch (Exception e) { 134 EndlessLoopTest.fail(e); 135 } 136 137 if (n_iv_calls != 1) { 138 EndlessLoopTest.fail(new RuntimeException("InputVerifier was called " + n_iv_calls + " times")); 139 } 140 141 EndlessLoopTest.pass(); 142 143 }//End init() 144 145 146 static void mouseClickOnComp(Robot r, Component comp) { 147 Point loc = comp.getLocationOnScreen(); 148 loc.x += comp.getWidth() / 2; 149 loc.y += comp.getHeight() / 2; 150 r.mouseMove(loc.x, loc.y); 151 r.delay(10); 152 r.mousePress(InputEvent.BUTTON1_MASK); 153 r.delay(10); 154 r.mouseRelease(InputEvent.BUTTON1_MASK); 155 } 156 157 /***************************************************** 158 * Standard Test Machinery Section 159 * DO NOT modify anything in this section -- it's a 160 * standard chunk of code which has all of the 161 * synchronisation necessary for the test harness. 162 * By keeping it the same in all tests, it is easier 163 * to read and understand someone else's test, as 164 * well as insuring that all tests behave correctly 165 * with the test harness. 166 * There is a section following this for test- 167 * classes 168 ******************************************************/ 169 private static boolean theTestPassed = false; 170 private static boolean testGeneratedInterrupt = false; 171 private static String failureMessage = ""; 172 173 private static Thread mainThread = null; 174 175 private static int sleepTime = 300000; 176 177 // Not sure about what happens if multiple of this test are 178 // instantiated in the same VM. Being static (and using 179 // static vars), it aint gonna work. Not worrying about 180 // it for now. 181 public static void main( String args[] ) throws InterruptedException 182 { 183 mainThread = Thread.currentThread(); 184 try 185 { 186 init(); 187 } 188 catch( TestPassedException e ) 189 { 190 //The test passed, so just return from main and harness will 191 // interepret this return as a pass 192 return; 193 } 194 //At this point, neither test pass nor test fail has been 195 // called -- either would have thrown an exception and ended the 196 // test, so we know we have multiple threads. 197 198 //Test involves other threads, so sleep and wait for them to 199 // called pass() or fail() 200 try 201 { 202 Thread.sleep( sleepTime ); 203 //Timed out, so fail the test 204 throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" ); 205 } 206 catch (InterruptedException e) 207 { 208 //The test harness may have interrupted the test. If so, rethrow the exception 209 // so that the harness gets it and deals with it. 210 if( ! testGeneratedInterrupt ) throw e; 211 212 //reset flag in case hit this code more than once for some reason (just safety) 213 testGeneratedInterrupt = false; 214 215 if ( theTestPassed == false ) 216 { 217 throw new RuntimeException( failureMessage ); 218 } 219 } 220 221 }//main 222 223 public static synchronized void setTimeoutTo( int seconds ) 224 { 225 sleepTime = seconds * 1000; 226 } 227 228 public static synchronized void pass() 229 { 230 Sysout.println( "The test passed." ); 231 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 232 //first check if this is executing in main thread 233 if ( mainThread == Thread.currentThread() ) 234 { 235 //Still in the main thread, so set the flag just for kicks, 236 // and throw a test passed exception which will be caught 237 // and end the test. 238 theTestPassed = true; 239 throw new TestPassedException(); 240 } 241 theTestPassed = true; 242 testGeneratedInterrupt = true; 243 mainThread.interrupt(); 244 }//pass() 245 246 public static synchronized void fail( Exception whyFailed ) 247 { 248 Sysout.println( "The test failed: " + whyFailed ); 249 Sysout.println( "The test is over, hit Ctl-C to stop Java VM" ); 250 //check if this called from main thread 251 if ( mainThread == Thread.currentThread() ) 252 { 253 //If main thread, fail now 'cause not sleeping 254 throw new RuntimeException( whyFailed ); 255 } 256 theTestPassed = false; 257 testGeneratedInterrupt = true; 258 failureMessage = whyFailed.toString(); 259 mainThread.interrupt(); 260 }//fail() 261 262 }// class EndlessLoopTest 263 264 //This exception is used to exit from any level of call nesting 265 // when it's determined that the test has passed, and immediately 266 // end the test. 267 class TestPassedException extends RuntimeException 268 { 269 } 270 271 //*********** End Standard Test Machinery Section ********** 272 273 /**************************************************** 274 Standard Test Machinery 275 DO NOT modify anything below -- it's a standard 276 chunk of code whose purpose is to make user 277 interaction uniform, and thereby make it simpler 278 to read and understand someone else's test. 279 ****************************************************/ 280 281 /** 282 This is part of the standard test machinery. 283 It creates a dialog (with the instructions), and is the interface 284 for sending text messages to the user. 285 To print the instructions, send an array of strings to Sysout.createDialog 286 WithInstructions method. Put one line of instructions per array entry. 287 To display a message for the tester to see, simply call Sysout.println 288 with the string to be displayed. 289 This mimics System.out.println but works within the test harness as well 290 as standalone. 291 */ 292 293 class Sysout 294 { 295 private static TestDialog dialog; 296 297 public static void createDialogWithInstructions( String[] instructions ) 298 { 299 dialog = new TestDialog( new Frame(), "Instructions" ); 300 dialog.printInstructions( instructions ); 301 dialog.setVisible(true); 302 println( "Any messages for the tester will display here." ); 303 } 304 305 public static void createDialog( ) 306 { 307 dialog = new TestDialog( new Frame(), "Instructions" ); 308 String[] defInstr = { "Instructions will appear here. ", "" } ; 309 dialog.printInstructions( defInstr ); 310 dialog.setVisible(true); 311 println( "Any messages for the tester will display here." ); 312 } 313 314 315 public static void printInstructions( String[] instructions ) 316 { 317 dialog.printInstructions( instructions ); 318 } 319 320 321 public static void println( String messageIn ) 322 { 323 dialog.displayMessage( messageIn ); 324 System.out.println(messageIn); 325 } 326 327 }// Sysout class 328 329 /** 330 This is part of the standard test machinery. It provides a place for the 331 test instructions to be displayed, and a place for interactive messages 332 to the user to be displayed. 333 To have the test instructions displayed, see Sysout. 334 To have a message to the user be displayed, see Sysout. 335 Do not call anything in this dialog directly. 336 */ 337 class TestDialog extends Dialog 338 { 339 340 TextArea instructionsText; 341 TextArea messageText; 342 int maxStringLength = 80; 343 344 //DO NOT call this directly, go through Sysout 345 public TestDialog( Frame frame, String name ) 346 { 347 super( frame, name ); 348 int scrollBoth = TextArea.SCROLLBARS_BOTH; 349 instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); 350 add( "North", instructionsText ); 351 352 messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); 353 add("Center", messageText); 354 355 pack(); 356 357 setVisible(true); 358 }// TestDialog() 359 360 //DO NOT call this directly, go through Sysout 361 public void printInstructions( String[] instructions ) 362 { 363 //Clear out any current instructions 364 instructionsText.setText( "" ); 365 366 //Go down array of instruction strings 367 368 String printStr, remainingStr; 369 for( int i=0; i < instructions.length; i++ ) 370 { 371 //chop up each into pieces maxSringLength long 372 remainingStr = instructions[ i ]; 373 while( remainingStr.length() > 0 ) 374 { 375 //if longer than max then chop off first max chars to print 376 if( remainingStr.length() >= maxStringLength ) 377 { 378 //Try to chop on a word boundary 379 int posOfSpace = remainingStr. 380 lastIndexOf( ' ', maxStringLength - 1 ); 381 382 if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; 383 384 printStr = remainingStr.substring( 0, posOfSpace + 1 ); 385 remainingStr = remainingStr.substring( posOfSpace + 1 ); 386 } 387 //else just print 388 else 389 { 390 printStr = remainingStr; 391 remainingStr = ""; 392 } 393 394 instructionsText.append( printStr + "\n" ); 395 396 }// while 397 398 }// for 399 400 }//printInstructions() 401 402 //DO NOT call this directly, go through Sysout 403 public void displayMessage( String messageIn ) 404 { 405 messageText.append( messageIn + "\n" ); 406 System.out.println(messageIn); 407 } 408 409 }// TestDialog class