MixingPanelsResizing.java revision 14851:980da45565c8
1/* 2 * Copyright (c) 2014, 2016, 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 25import java.awt.*; 26import java.awt.event.InputEvent; 27import javax.swing.*; 28import java.io.*; 29import test.java.awt.regtesthelpers.Util; 30 31/** 32 * AWT/Swing overlapping test for Panel and JPanel behavior during resizing. 33 * <p>See <a href="https://bugs.openjdk.java.net/browse/JDK-6786219">JDK-6786219</a> for details 34 */ 35/* 36 * @test 37 * @key headful 38 * @bug 6786219 39 * @summary Issues when resizing the frame after mixing of heavy weight & light weight components 40 * @author sergey.grinev@oracle.com: area=awt.mixing 41 * @library ../../regtesthelpers 42 * @build Util 43 * @build FrameBorderCounter 44 * @run main MixingPanelsResizing 45 */ 46public class MixingPanelsResizing { 47 48 static volatile boolean failed = false; 49 50 private static JFrame frame; 51 private static JButton jbutton; 52 private static Button awtButton; 53 private static JButton jbutton2; 54 private static Button awtButton2; 55 private static final Color jbColor = Color.RED; 56 private static final Color awtColor = Color.ORANGE; 57 private static final Color jb2Color = Color.BLUE; 58 private static final Color awt2Color = Color.CYAN; 59 private static final int ROBOT_DELAY = 500; 60 61 private static Point lLoc; 62 private static int borderShift; 63 64 private static int frameBorderCounter() { 65 String JAVA_HOME = System.getProperty("java.home"); 66 try { 67 Process p = Runtime.getRuntime().exec(JAVA_HOME + "/bin/java FrameBorderCounter"); 68 try { 69 p.waitFor(); 70 } catch (InterruptedException e) { 71 e.printStackTrace(); 72 throw new RuntimeException(e); 73 } 74 if (p.exitValue() != 0) { 75 throw new RuntimeException("FrameBorderCounter exited with not null code!\n" + readInputStream(p.getErrorStream())); 76 } 77 return Integer.parseInt(readInputStream(p.getInputStream()).trim()); 78 } catch (IOException e) { 79 e.printStackTrace(); 80 throw new RuntimeException(e); 81 } 82 } 83 84 private static String readInputStream(InputStream is) throws IOException { 85 byte[] buffer = new byte[4096]; 86 int len = 0; 87 StringBuilder sb = new StringBuilder(); 88 try (InputStreamReader isr = new InputStreamReader(is)) { 89 while ((len = is.read(buffer)) > 0) { 90 sb.append(new String(buffer, 0, len)); 91 } 92 } 93 return sb.toString(); 94 } 95 96 private static void init() throws Exception { 97 //*** Create instructions for the user here *** 98 99 borderShift = frameBorderCounter(); 100 borderShift = Math.abs(borderShift) == 1 ? borderShift : (borderShift / 2); 101 String[] instructions = { 102 "This is an AUTOMATIC test, simply wait until it is done.", 103 "The result (passed or failed) will be shown in the", 104 "message window below." 105 }; 106 SwingUtilities.invokeAndWait(new Runnable() { 107 public void run() { 108 Sysout.createDialog(); 109 Sysout.printInstructions(instructions); 110 111 // prepare controls 112 113 frame = new JFrame(); 114 115 Panel awtPanel = new Panel(); 116 awtPanel.setBackground(Color.GREEN); 117 awtButton = new Button("AWTButton"); 118 awtPanel.add(awtButton); 119 awtButton.setForeground(awtColor); 120 awtButton.setBackground(awtColor); 121 jbutton = new JButton("SwingButton"); 122 awtPanel.add(jbutton); 123 jbutton.setForeground(jbColor); 124 jbutton.setBackground(jbColor); 125 126 JPanel jPanel = new JPanel(); 127 jbutton2 = new JButton("SwingButton2"); 128 jPanel.add(jbutton2); 129 jbutton2.setForeground(jb2Color); 130 jbutton2.setBackground(jb2Color); 131 awtButton2 = new Button("AWT Button2"); 132 jPanel.add(awtButton2); 133 awtButton2.setForeground(awt2Color); 134 awtButton2.setBackground(awt2Color); 135 jPanel.setBackground(Color.YELLOW); 136 137 frame.add(awtPanel, BorderLayout.SOUTH); 138 frame.add(jPanel, BorderLayout.NORTH); 139 140 frame.pack(); 141 frame.setVisible(true); 142 } 143 }); 144 145 ///////////////////////// 146 147 final Robot robot = Util.createRobot(); 148 robot.setAutoDelay(ROBOT_DELAY); 149 150 Util.waitForIdle(robot); 151 152 SwingUtilities.invokeAndWait(new Runnable() { 153 public void run() { 154 lLoc = frame.getLocationOnScreen(); 155 lLoc.translate(frame.getWidth() + borderShift, frame.getHeight() + borderShift); 156 } 157 }); 158 159 //grow 160 robot.mouseMove(lLoc.x, lLoc.y); 161 robot.mousePress(InputEvent.BUTTON1_MASK); 162 163 Runnable test = new Runnable() { 164 165 public void run() { 166 Point btnLoc = jbutton.getLocationOnScreen(); 167 Color c = robot.getPixelColor(btnLoc.x + 5, btnLoc.y + 5); 168 if (!c.equals(jbColor)) { 169 fail("JButton was not redrawn properly on AWT Panel during move"); 170 } 171 172 btnLoc = awtButton.getLocationOnScreen(); 173 c = robot.getPixelColor(btnLoc.x + 5, btnLoc.y + 5); 174 if (!c.equals(awtColor)) { 175 fail("AWT Button was not redrawn properly on AWT Panel during move"); 176 } 177 178 btnLoc = jbutton2.getLocationOnScreen(); 179 c = robot.getPixelColor(btnLoc.x + 5, btnLoc.y + 5); 180 if (!c.equals(jb2Color)) { 181 fail("JButton was not redrawn properly on JPanel during move"); 182 } 183 184 btnLoc = awtButton2.getLocationOnScreen(); 185 c = robot.getPixelColor(btnLoc.x + 5, btnLoc.y + 5); 186 if (!c.equals(awt2Color)) { 187 fail("ATW Button was not redrawn properly on JPanel during move"); 188 } 189 } 190 }; 191 192 for (int i = 0; i < 30; i++) { 193 test.run(); 194 robot.mouseMove(lLoc.x + 20 * i, lLoc.y + 10 * i); 195 } 196 robot.mouseRelease(InputEvent.BUTTON1_MASK); 197 198 //back 199 System.out.println("fast back"); 200 robot.mousePress(InputEvent.BUTTON1_MASK); 201 for (int i = 5; i >= 0; i--) { 202 test.run(); 203 robot.mouseMove(lLoc.x + 120 * i, lLoc.y + 60 * i); 204 } 205 robot.mouseRelease(InputEvent.BUTTON1_MASK); 206 207 pass(); 208 }//End init() 209 /***************************************************** 210 * Standard Test Machinery Section 211 * DO NOT modify anything in this section -- it's a 212 * standard chunk of code which has all of the 213 * synchronisation necessary for the test harness. 214 * By keeping it the same in all tests, it is easier 215 * to read and understand someone else's test, as 216 * well as insuring that all tests behave correctly 217 * with the test harness. 218 * There is a section following this for test- 219 * classes 220 ******************************************************/ 221 private static boolean theTestPassed = false; 222 private static boolean testGeneratedInterrupt = false; 223 private static String failureMessage = ""; 224 private static Thread mainThread = null; 225 private static int sleepTime = 300000; 226 227 // Not sure about what happens if multiple of this test are 228 // instantiated in the same VM. Being static (and using 229 // static vars), it aint gonna work. Not worrying about 230 // it for now. 231 public static void main(String args[]) throws Exception { 232 if (!Toolkit.getDefaultToolkit().isDynamicLayoutActive()) { 233 System.out.println("Dynamic layout is not active. Test passes."); 234 return; 235 } 236 mainThread = Thread.currentThread(); 237 try { 238 init(); 239 } catch (TestPassedException e) { 240 //The test passed, so just return from main and harness will 241 // interepret this return as a pass 242 return; 243 } 244 //At this point, neither test pass nor test fail has been 245 // called -- either would have thrown an exception and ended the 246 // test, so we know we have multiple threads. 247 248 //Test involves other threads, so sleep and wait for them to 249 // called pass() or fail() 250 try { 251 Thread.sleep(sleepTime); 252 //Timed out, so fail the test 253 throw new RuntimeException("Timed out after " + sleepTime / 1000 + " seconds"); 254 } catch (InterruptedException e) { 255 //The test harness may have interrupted the test. If so, rethrow the exception 256 // so that the harness gets it and deals with it. 257 if (!testGeneratedInterrupt) { 258 throw e; 259 } 260 261 //reset flag in case hit this code more than once for some reason (just safety) 262 testGeneratedInterrupt = false; 263 264 if (theTestPassed == false) { 265 throw new RuntimeException(failureMessage); 266 } 267 } 268 269 }//main 270 271 public static synchronized void setTimeoutTo(int seconds) { 272 sleepTime = seconds * 1000; 273 } 274 275 public static synchronized void pass() { 276 Sysout.println("The test passed."); 277 Sysout.println("The test is over, hit Ctl-C to stop Java VM"); 278 //first check if this is executing in main thread 279 if (mainThread == Thread.currentThread()) { 280 //Still in the main thread, so set the flag just for kicks, 281 // and throw a test passed exception which will be caught 282 // and end the test. 283 theTestPassed = true; 284 throw new TestPassedException(); 285 } 286 theTestPassed = true; 287 testGeneratedInterrupt = true; 288 mainThread.interrupt(); 289 }//pass() 290 291 public static synchronized void fail() { 292 //test writer didn't specify why test failed, so give generic 293 fail("it just plain failed! :-)"); 294 } 295 296 public static synchronized void fail(String whyFailed) { 297 Sysout.println("The test failed: " + whyFailed); 298 Sysout.println("The test is over, hit Ctl-C to stop Java VM"); 299 //check if this called from main thread 300 if (mainThread == Thread.currentThread()) { 301 //If main thread, fail now 'cause not sleeping 302 throw new RuntimeException(whyFailed); 303 } 304 theTestPassed = false; 305 testGeneratedInterrupt = true; 306 failureMessage = whyFailed; 307 mainThread.interrupt(); 308 }//fail() 309}// class JButtonInGlassPane 310class TestPassedException extends RuntimeException { 311} 312 313//*********** End Standard Test Machinery Section ********** 314//************ Begin classes defined for the test **************** 315// if want to make listeners, here is the recommended place for them, then instantiate 316// them in init() 317 318/* Example of a class which may be written as part of a test 319class NewClass implements anInterface 320{ 321static int newVar = 0; 322 323public void eventDispatched(AWTEvent e) 324{ 325//Counting events to see if we get enough 326eventCount++; 327 328if( eventCount == 20 ) 329{ 330//got enough events, so pass 331 332JButtonInGlassPane.pass(); 333} 334else if( tries == 20 ) 335{ 336//tried too many times without getting enough events so fail 337 338JButtonInGlassPane.fail(); 339} 340 341}// eventDispatched() 342 343}// NewClass class 344 345 */ 346//************** End classes defined for the test ******************* 347/**************************************************** 348Standard Test Machinery 349DO NOT modify anything below -- it's a standard 350chunk of code whose purpose is to make user 351interaction uniform, and thereby make it simpler 352to read and understand someone else's test. 353 ****************************************************/ 354/** 355This is part of the standard test machinery. 356It creates a dialog (with the instructions), and is the interface 357for sending text messages to the user. 358To print the instructions, send an array of strings to Sysout.createDialog 359WithInstructions method. Put one line of instructions per array entry. 360To display a message for the tester to see, simply call Sysout.println 361with the string to be displayed. 362This mimics System.out.println but works within the test harness as well 363as standalone. 364 */ 365class Sysout { 366 367 private static TestDialog dialog; 368 369 public static void createDialogWithInstructions(String[] instructions) { 370 dialog = new TestDialog(new Frame(), "Instructions"); 371 dialog.printInstructions(instructions); 372 //dialog.setVisible(true); 373 println("Any messages for the tester will display here."); 374 } 375 376 public static void createDialog() { 377 dialog = new TestDialog(new Frame(), "Instructions"); 378 String[] defInstr = {"Instructions will appear here. ", ""}; 379 dialog.printInstructions(defInstr); 380 //dialog.setVisible(true); 381 println("Any messages for the tester will display here."); 382 } 383 384 public static void printInstructions(String[] instructions) { 385 dialog.printInstructions(instructions); 386 } 387 388 public static void println(String messageIn) { 389 dialog.displayMessage(messageIn); 390 System.out.println(messageIn); 391 } 392}// Sysout class 393 394/** 395This is part of the standard test machinery. It provides a place for the 396test instructions to be displayed, and a place for interactive messages 397to the user to be displayed. 398To have the test instructions displayed, see Sysout. 399To have a message to the user be displayed, see Sysout. 400Do not call anything in this dialog directly. 401 */ 402class TestDialog extends Dialog { 403 404 TextArea instructionsText; 405 TextArea messageText; 406 int maxStringLength = 80; 407 408 //DO NOT call this directly, go through Sysout 409 public TestDialog(Frame frame, String name) { 410 super(frame, name); 411 int scrollBoth = TextArea.SCROLLBARS_BOTH; 412 instructionsText = new TextArea("", 15, maxStringLength, scrollBoth); 413 add("North", instructionsText); 414 415 messageText = new TextArea("", 5, maxStringLength, scrollBoth); 416 add("Center", messageText); 417 418 pack(); 419 420 //setVisible(true); 421 }// TestDialog() 422 423 //DO NOT call this directly, go through Sysout 424 public void printInstructions(String[] instructions) { 425 //Clear out any current instructions 426 instructionsText.setText(""); 427 428 //Go down array of instruction strings 429 430 String printStr, remainingStr; 431 for (int i = 0; i < instructions.length; i++) { 432 //chop up each into pieces maxSringLength long 433 remainingStr = instructions[i]; 434 while (remainingStr.length() > 0) { 435 //if longer than max then chop off first max chars to print 436 if (remainingStr.length() >= maxStringLength) { 437 //Try to chop on a word boundary 438 int posOfSpace = remainingStr.lastIndexOf(' ', maxStringLength - 1); 439 440 if (posOfSpace <= 0) { 441 posOfSpace = maxStringLength - 1; 442 } 443 444 printStr = remainingStr.substring(0, posOfSpace + 1); 445 remainingStr = remainingStr.substring(posOfSpace + 1); 446 } //else just print 447 else { 448 printStr = remainingStr; 449 remainingStr = ""; 450 } 451 452 instructionsText.append(printStr + "\n"); 453 454 }// while 455 456 }// for 457 458 }//printInstructions() 459 460 //DO NOT call this directly, go through Sysout 461 public void displayMessage(String messageIn) { 462 messageText.append(messageIn + "\n"); 463 System.out.println(messageIn); 464 } 465}// TestDialog class 466 467