Util.java revision 12770:7b9d345fc7ba
1/* 2 * Copyright (c) 2011, 2015, 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 24import javax.swing.*; 25import java.awt.*; 26import java.awt.event.*; 27import java.awt.image.BufferedImage; 28import java.util.ArrayList; 29import java.util.LinkedList; 30import java.util.List; 31import java.util.concurrent.Callable; 32 33/** 34 * <p>This class contains utilities useful for regression testing. 35 * <p>When using jtreg you would include this class via something like: 36 * <pre> 37 * 38 * @library ../../regtesthelpers 39 * @build Util 40 * </pre> 41 */ 42 43public class Util { 44 45 /** 46 * Convert a rectangle from coordinate system of Component c to 47 * screen coordinate system. 48 * 49 * @param r a non-null Rectangle 50 * @param c a Component whose coordinate system is used for conversion 51 */ 52 public static void convertRectToScreen(Rectangle r, Component c) { 53 Point p = new Point(r.x, r.y); 54 SwingUtilities.convertPointToScreen(p, c); 55 r.x = p.x; 56 r.y = p.y; 57 } 58 59 /** 60 * Compares two bufferedImages pixel-by-pixel. 61 * return true if all pixels in the two areas are identical 62 */ 63 public static boolean compareBufferedImages(BufferedImage bufferedImage0, BufferedImage bufferedImage1) { 64 int width = bufferedImage0.getWidth(); 65 int height = bufferedImage0.getHeight(); 66 67 if (width != bufferedImage1.getWidth() || height != bufferedImage1.getHeight()) { 68 return false; 69 } 70 71 for (int y = 0; y < height; y++) { 72 for (int x = 0; x < width; x++) { 73 if (bufferedImage0.getRGB(x, y) != bufferedImage1.getRGB(x, y)) { 74 return false; 75 } 76 } 77 } 78 79 return true; 80 } 81 82 /** 83 * Fills the heap until OutOfMemoryError occurs. This method is useful for 84 * WeakReferences removing. 85 */ 86 public static void generateOOME() { 87 List<Object> bigLeak = new LinkedList<Object>(); 88 89 boolean oome = false; 90 91 System.out.print("Filling the heap"); 92 93 try { 94 for(int i = 0; true ; i++) { 95 // Now, use up all RAM 96 bigLeak.add(new byte[1024 * 1024]); 97 98 System.out.print("."); 99 100 // Give the GC a change at that weakref 101 if (i % 10 == 0) { 102 System.gc(); 103 try { 104 Thread.sleep(100); 105 } catch (InterruptedException e) { 106 e.printStackTrace(); 107 } 108 } 109 } 110 } catch (OutOfMemoryError e) { 111 bigLeak = null; 112 oome = true; 113 } 114 115 System.out.println(""); 116 117 if (!oome) { 118 throw new RuntimeException("Problem with test case - never got OOME"); 119 } 120 121 System.out.println("Got OOME"); 122 } 123 124 /** 125 * Find a sub component by class name. 126 * Always run this method on the EDT thread 127 */ 128 public static Component findSubComponent(Component parent, String className) { 129 String parentClassName = parent.getClass().getName(); 130 131 if (parentClassName.contains(className)) { 132 return parent; 133 } 134 135 if (parent instanceof Container) { 136 for (Component child : ((Container) parent).getComponents()) { 137 Component subComponent = findSubComponent(child, className); 138 139 if (subComponent != null) { 140 return subComponent; 141 } 142 } 143 } 144 145 return null; 146 } 147 148 /** 149 * Hits mnemonics by robot. 150 */ 151 public static void hitMnemonics(Robot robot, int... keys) { 152 153 ArrayList<Integer> mnemonicKeyCodes = getSystemMnemonicKeyCodes(); 154 for (Integer mnemonic : mnemonicKeyCodes) { 155 robot.keyPress(mnemonic); 156 } 157 158 hitKeys(robot, keys); 159 160 for (Integer mnemonic : mnemonicKeyCodes) { 161 robot.keyRelease(mnemonic); 162 } 163 } 164 165 /** 166 * Hits keys by robot. 167 */ 168 public static void hitKeys(Robot robot, int... keys) { 169 for (int i = 0; i < keys.length; i++) { 170 robot.keyPress(keys[i]); 171 } 172 173 for (int i = keys.length - 1; i >= 0; i--) { 174 robot.keyRelease(keys[i]); 175 } 176 } 177 178 /** 179 * Moves mouse smoothly from (x0, y0) to (x1, y1). 180 */ 181 public static void glide(Robot robot, int x0, int y0, int x1, int y1) throws AWTException { 182 float dmax = (float) Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0)); 183 float dx = (x1 - x0) / dmax; 184 float dy = (y1 - y0) / dmax; 185 186 for (int i = 0; i <= dmax; i += 10) { 187 robot.mouseMove((int) (x0 + dx * i), (int) (y0 + dy * i)); 188 } 189 } 190 191 /** 192 * Gets component center point 193 * 194 * @return center point of the <code>component</code> 195 */ 196 public static Point getCenterPoint(final Component component) throws Exception { 197 return Util.invokeOnEDT(new Callable<Point>() { 198 199 @Override 200 public Point call() throws Exception { 201 Point p = component.getLocationOnScreen(); 202 Dimension size = component.getSize(); 203 return new Point(p.x + size.width / 2, p.y + size.height / 2); 204 } 205 }); 206 } 207 208 /** 209 * Invokes the <code>task</code> on the EDT thread. 210 * 211 * @return result of the <code>task</code> 212 */ 213 public static <T> T invokeOnEDT(final Callable<T> task) throws Exception { 214 final List<T> result = new ArrayList<>(1); 215 final Exception[] exception = new Exception[1]; 216 217 SwingUtilities.invokeAndWait(new Runnable() { 218 @Override 219 public void run() { 220 try { 221 result.add(task.call()); 222 } catch (Exception e) { 223 exception[0] = e; 224 } 225 } 226 }); 227 228 if (exception[0] != null) { 229 throw exception[0]; 230 } 231 232 return result.get(0); 233 } 234 235 /** 236 * Gets the key codes list from modifiers 237 * @param modifiers an integer combination of the modifier constants 238 * @return key codes list 239 */ 240 public static ArrayList<Integer> getKeyCodesFromKeyMask(int modifiers) { 241 ArrayList<Integer> result = new ArrayList<>(); 242 if ((modifiers & InputEvent.CTRL_MASK) != 0) { 243 result.add(KeyEvent.VK_CONTROL); 244 } 245 if ((modifiers & InputEvent.ALT_MASK) != 0) { 246 result.add(KeyEvent.VK_ALT); 247 } 248 if ((modifiers & InputEvent.SHIFT_MASK) != 0) { 249 result.add(KeyEvent.VK_SHIFT); 250 } 251 if ((modifiers & InputEvent.META_MASK) != 0) { 252 result.add(KeyEvent.VK_META); 253 } 254 return result; 255 } 256 257 /** 258 * Gets key codes from system mnemonic key mask 259 * @return key codes list 260 */ 261 public static ArrayList<Integer> getSystemMnemonicKeyCodes() { 262 String osName = System.getProperty("os.name"); 263 ArrayList<Integer> result = new ArrayList<>(); 264 if (osName.contains("OS X")) { 265 result.add(KeyEvent.VK_CONTROL); 266 } 267 result.add(KeyEvent.VK_ALT); 268 return result; 269 } 270 271 /** 272 * Creates and returns a JDialog with two button, one that says pass, 273 * another that says fail. The fail button is wired to call 274 * <code>uiTestFailed</code> with <code>failString</code> and the pass 275 * button is wired to invoked <code>uiTestPassed</code>. 276 * <p>The content pane of the JDialog uses a BorderLayout with the 277 * buttons inside a horizontal box with filler between them and the 278 * pass button on the left. 279 * <p>The returned Dialog has not been packed, or made visible, it is 280 * up to the caller to do that (after putting in some useful components). 281 */ 282 public static JDialog createModalDialogWithPassFailButtons(final String failString) { 283 JDialog retDialog = new JDialog(); 284 Box buttonBox = Box.createHorizontalBox(); 285 JButton passButton = new JButton("Pass"); 286 JButton failButton = new JButton("Fail"); 287 288 passButton.addActionListener(new ActionListener() { 289 public void actionPerformed(ActionEvent ae) { 290 retDialog.dispose(); 291 } 292 }); 293 failButton.addActionListener(new ActionListener() { 294 public void actionPerformed(ActionEvent ae) { 295 retDialog.dispose(); 296 throw new RuntimeException("Test failed. " + failString); 297 } 298 }); 299 retDialog.setTitle("Test"); 300 retDialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL); 301 buttonBox.add(passButton); 302 buttonBox.add(Box.createGlue()); 303 buttonBox.add(failButton); 304 retDialog.getContentPane().add(buttonBox, BorderLayout.SOUTH); 305 retDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); 306 return retDialog; 307 } 308} 309