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 24 import javax.swing.*; 25 import java.awt.*; 26 import java.awt.event.*; 27 import java.awt.image.BufferedImage; 28 import java.util.ArrayList; 29 import java.util.LinkedList; 30 import java.util.List; 31 import 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 43 public class Util { 44 /** 45 * Convert a rectangle from coordinate system of Component c to 46 * screen coordinate system. 47 * 48 * @param r a non-null Rectangle 49 * @param c a Component whose coordinate system is used for conversion 50 */ convertRectToScreen(Rectangle r, Component c)51 public static void convertRectToScreen(Rectangle r, Component c) { 52 Point p = new Point(r.x, r.y); 53 SwingUtilities.convertPointToScreen(p, c); 54 r.x = p.x; 55 r.y = p.y; 56 } 57 58 /** 59 * Compares two bufferedImages pixel-by-pixel. 60 * return true if all pixels in the two areas are identical 61 */ compareBufferedImages(BufferedImage bufferedImage0, BufferedImage bufferedImage1)62 public static boolean compareBufferedImages(BufferedImage bufferedImage0, BufferedImage bufferedImage1) { 63 int width = bufferedImage0.getWidth(); 64 int height = bufferedImage0.getHeight(); 65 66 if (width != bufferedImage1.getWidth() || height != bufferedImage1.getHeight()) { 67 return false; 68 } 69 70 for (int y = 0; y < height; y++) { 71 for (int x = 0; x < width; x++) { 72 if (bufferedImage0.getRGB(x, y) != bufferedImage1.getRGB(x, y)) { 73 return false; 74 } 75 } 76 } 77 78 return true; 79 } 80 81 /** 82 * Fills the heap until OutOfMemoryError occurs. This method is useful for 83 * WeakReferences removing. 84 */ generateOOME()85 public static void generateOOME() { 86 List<Object> bigLeak = new LinkedList<Object>(); 87 88 boolean oome = false; 89 90 System.out.print("Filling the heap"); 91 92 try { 93 for(int i = 0; true ; i++) { 94 // Now, use up all RAM 95 bigLeak.add(new byte[1024 * 1024]); 96 97 System.out.print("."); 98 99 // Give the GC a change at that weakref 100 if (i % 10 == 0) { 101 System.gc(); 102 try { 103 Thread.sleep(100); 104 } catch (InterruptedException e) { 105 e.printStackTrace(); 106 } 107 } 108 } 109 } catch (OutOfMemoryError e) { 110 bigLeak = null; 111 oome = true; 112 } 113 114 System.out.println(""); 115 116 if (!oome) { 117 throw new RuntimeException("Problem with test case - never got OOME"); 118 } 119 120 System.out.println("Got OOME"); 121 } 122 123 /** 124 * Find a sub component by class name. 125 * Always run this method on the EDT thread 126 */ findSubComponent(Component parent, String className)127 public static Component findSubComponent(Component parent, String className) { 128 String parentClassName = parent.getClass().getName(); 129 130 if (parentClassName.contains(className)) { 131 return parent; 132 } 133 134 if (parent instanceof Container) { 135 for (Component child : ((Container) parent).getComponents()) { 136 Component subComponent = findSubComponent(child, className); 137 138 if (subComponent != null) { 139 return subComponent; 140 } 141 } 142 } 143 144 return null; 145 } 146 147 /** 148 * Hits mnemonics by robot. 149 */ hitMnemonics(Robot robot, int... keys)150 public static void hitMnemonics(Robot robot, int... keys) { 151 152 ArrayList<Integer> mnemonicKeyCodes = getSystemMnemonicKeyCodes(); 153 for (Integer mnemonic : mnemonicKeyCodes) { 154 robot.keyPress(mnemonic); 155 } 156 157 hitKeys(robot, keys); 158 159 for (Integer mnemonic : mnemonicKeyCodes) { 160 robot.keyRelease(mnemonic); 161 } 162 } 163 164 /** 165 * Hits keys by robot. 166 */ hitKeys(Robot robot, int... keys)167 public static void hitKeys(Robot robot, int... keys) { 168 for (int i = 0; i < keys.length; i++) { 169 robot.keyPress(keys[i]); 170 } 171 172 for (int i = keys.length - 1; i >= 0; i--) { 173 robot.keyRelease(keys[i]); 174 } 175 } 176 177 /** 178 * Moves mouse smoothly from (x0, y0) to (x1, y1). 179 */ glide(Robot robot, int x0, int y0, int x1, int y1)180 public static void glide(Robot robot, int x0, int y0, int x1, int y1) throws AWTException { 181 float dmax = (float) Math.max(Math.abs(x1 - x0), Math.abs(y1 - y0)); 182 float dx = (x1 - x0) / dmax; 183 float dy = (y1 - y0) / dmax; 184 185 for (int i = 0; i <= dmax; i += 10) { 186 robot.mouseMove((int) (x0 + dx * i), (int) (y0 + dy * i)); 187 } 188 } 189 190 /** 191 * Gets component center point 192 * 193 * @return center point of the <code>component</code> 194 */ getCenterPoint(final Component component)195 public static Point getCenterPoint(final Component component) throws Exception { 196 return Util.invokeOnEDT(new Callable<Point>() { 197 198 @Override 199 public Point call() throws Exception { 200 Point p = component.getLocationOnScreen(); 201 Dimension size = component.getSize(); 202 return new Point(p.x + size.width / 2, p.y + size.height / 2); 203 } 204 }); 205 } 206 207 /** 208 * Invokes the <code>task</code> on the EDT thread. 209 * 210 * @return result of the <code>task</code> 211 */ 212 public static <T> T invokeOnEDT(final Callable<T> task) throws Exception { 213 final List<T> result = new ArrayList<>(1); 214 final Exception[] exception = new Exception[1]; 215 216 SwingUtilities.invokeAndWait(new Runnable() { 217 @Override 218 public void run() { 219 try { 220 result.add(task.call()); 221 } catch (Exception e) { 222 exception[0] = e; 223 } 224 } 225 }); 226 227 if (exception[0] != null) { 228 throw exception[0]; 229 } 230 231 return result.get(0); 232 } 233 234 /** 235 * Gets the key codes list from modifiers 236 * @param modifiers an integer combination of the modifier constants 237 * @return key codes list 238 */ 239 public static ArrayList<Integer> getKeyCodesFromKeyMask(int modifiers) { 240 ArrayList<Integer> result = new ArrayList<>(); 241 if ((modifiers & InputEvent.CTRL_MASK) != 0) { 242 result.add(KeyEvent.VK_CONTROL); 243 } 244 if ((modifiers & InputEvent.ALT_MASK) != 0) { 245 result.add(KeyEvent.VK_ALT); 246 } 247 if ((modifiers & InputEvent.SHIFT_MASK) != 0) { 248 result.add(KeyEvent.VK_SHIFT); 249 } 250 if ((modifiers & InputEvent.META_MASK) != 0) { 251 result.add(KeyEvent.VK_META); 252 } 253 return result; 254 } 255 256 /** 257 * Gets key codes from system mnemonic key mask 258 * @return key codes list 259 */ 260 public static ArrayList<Integer> getSystemMnemonicKeyCodes() { 261 String osName = System.getProperty("os.name"); 262 ArrayList<Integer> result = new ArrayList<>(); 263 if (osName.contains("OS X")) { 264 result.add(KeyEvent.VK_CONTROL); 265 } 266 result.add(KeyEvent.VK_ALT); 267 return result; 268 } 269 } 270