Skip to content

Commit e32a4ea

Browse files
committed
8253820: Save test images and dumps with timestamps from client sanity suite
Reviewed-by: serb
1 parent dff26a4 commit e32a4ea

File tree

3 files changed

+86
-95
lines changed

3 files changed

+86
-95
lines changed

test/jdk/sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,16 @@
2222
*/
2323

2424
import com.sun.swingset3.demos.button.ButtonDemo;
25-
import org.jemmy2ext.JemmyExt;
2625
import org.jtregext.GuiTestListener;
2726
import org.netbeans.jemmy.ClassReference;
28-
import org.netbeans.jemmy.ComponentChooser;
29-
import org.netbeans.jemmy.image.StrictImageComparator;
3027
import org.netbeans.jemmy.operators.JButtonOperator;
3128
import org.netbeans.jemmy.operators.JFrameOperator;
32-
import org.testng.annotations.BeforeClass;
3329
import org.testng.annotations.Listeners;
3430
import org.testng.annotations.Test;
3531

36-
import java.awt.Component;
3732
import java.awt.Dimension;
3833
import java.awt.Point;
3934
import java.awt.Rectangle;
40-
import java.awt.Robot;
4135
import java.awt.Toolkit;
4236
import java.awt.image.BufferedImage;
4337

@@ -65,44 +59,37 @@
6559
public class ButtonDemoScreenshotTest {
6660

6761
private static final int[] BUTTONS = {0, 1, 2, 3, 4, 5}; // "open browser" buttons (6, 7) open a browser, so ignore
68-
private static StrictImageComparator sComparator = null;
69-
70-
@BeforeClass
71-
public void init() {
72-
sComparator = new StrictImageComparator();
73-
}
7462

7563
@Test(dataProvider = "availableLookAndFeels", dataProviderClass = TestHelpers.class)
7664
public void test(String lookAndFeel) throws Exception {
7765
UIManager.setLookAndFeel(lookAndFeel);
78-
Robot rob = new Robot();
7966

8067
//capture some of the background
8168
Dimension screeSize = Toolkit.getDefaultToolkit().getScreenSize();
8269
Point screenCenter = new Point(screeSize.width / 2, screeSize.height / 2);
8370
Rectangle center = new Rectangle(
8471
screenCenter.x - 50, screenCenter.y - 50,
85-
screenCenter.x + 50, screenCenter.y + 50);
86-
BufferedImage background = rob.createScreenCapture(center);
72+
100, 100);
73+
BufferedImage background = getRobot().createScreenCapture(center);
8774

8875
new ClassReference(ButtonDemo.class.getCanonicalName()).startApplication();
8976

9077
JFrameOperator mainFrame = new JFrameOperator(DEMO_TITLE);
9178
mainFrame.waitComponentShowing(true);
9279

9380
//make sure the frame is already painted
94-
waitChangedImage(rob, () -> rob.createScreenCapture(center),
95-
background, mainFrame.getTimeouts(), "background.png");
81+
waitChangedImage(() -> getRobot().createScreenCapture(center),
82+
background, mainFrame.getTimeouts(), "background");
9683
//make sure the frame is painted completely
97-
waitStillImage(rob, mainFrame, "frame.png");
84+
waitStillImage(mainFrame, "frame");
9885

9986
// Check all the buttons
10087
for (int i : BUTTONS) {
101-
checkButton(mainFrame, i, rob);
88+
checkButton(mainFrame, i);
10289
}
10390
}
10491

105-
private void checkButton(JFrameOperator jfo, int i, Robot rob) throws InterruptedException {
92+
private void checkButton(JFrameOperator jfo, int i) throws InterruptedException {
10693
JButtonOperator button = new JButtonOperator(jfo, i);
10794

10895
//additional instrumentation for JDK-8198920. To be removed after the bug is fixed
@@ -113,9 +100,7 @@ private void checkButton(JFrameOperator jfo, int i, Robot rob) throws Interrupte
113100
button.moveMouse(button.getCenterX(), button.getCenterY());
114101

115102
BufferedImage notPressed, pressed = null;
116-
notPressed = waitStillImage(rob, button, "not-pressed-" + i + ".png");
117-
118-
BufferedImage[] pressedImage = new BufferedImage[1];
103+
notPressed = waitStillImage(button, "not-pressed-" + i);
119104

120105
button.pressMouse();
121106
//additional instrumentation for JDK-8198920. To be removed after the bug is fixed
@@ -126,14 +111,14 @@ private void checkButton(JFrameOperator jfo, int i, Robot rob) throws Interrupte
126111
//additional instrumentation for JDK-8198920. To be removed after the bug is fixed
127112
button.getOutput().printTrace("JDK-8198920: Button press confirmed by " + System.currentTimeMillis());
128113
//end of instrumentation for JDK-8198920
129-
waitChangedImage(rob, () -> capture(rob, button), notPressed,
130-
button.getTimeouts(), "pressed-" + i + ".png");
131-
pressed = waitStillImage(rob, button, "pressed.png");
114+
waitChangedImage(() -> capture(button), notPressed,
115+
button.getTimeouts(), "after-press-" + i);
116+
pressed = waitStillImage(button, "pressed-" + i);
132117
} finally {
133118
button.releaseMouse();
134119
if(pressed != null) {
135-
waitChangedImage(rob, () -> capture(rob, button), pressed,
136-
button.getTimeouts(), "released-" + i + ".png");
120+
waitChangedImage(() -> capture(button), pressed,
121+
button.getTimeouts(), "released-" + i);
137122
}
138123
//additional instrumentation for JDK-8198920. To be removed after the bug is fixed
139124
button.getOutput().printTrace("JDK-8198920: Button released at " + System.currentTimeMillis());

test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ private void checkImage(JEditorPaneOperator editorPaneOperator,
149149
final int xGap = 100, yGap = 40, columns = 2, rows = 5;
150150
editorPaneOperator.waitState(comp -> {
151151
BufferedImage capturedImage = ImageTool.getImage(imageRect);
152-
save(capturedImage, "editor.png");
152+
save(capturedImage, "editor");
153153
assertFalse(isBlack(capturedImage), "image blackness");
154154
int x = 0, y = 0, i = 0, j;
155155
for (; i < columns; i++) {
@@ -159,8 +159,7 @@ private void checkImage(JEditorPaneOperator editorPaneOperator,
159159
y += yGap;
160160
if(capturedImage.getRGB(x, y) == Color.WHITE.getRGB()) {
161161
// saving image for failure case
162-
JemmyExt.save(capturedImage, "capturedimage_" + pageName + "_" +
163-
UIManager.getLookAndFeel().getClass().getSimpleName() + ".png");
162+
save(capturedImage, "capturedimage-" + pageName);
164163
return false;
165164
}
166165
}

test/jdk/sanity/client/lib/Extensions/src/org/jemmy2ext/JemmyExt.java

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@
2222
*/
2323
package org.jemmy2ext;
2424

25+
import java.awt.AWTException;
2526
import java.awt.Component;
2627
import java.awt.EventQueue;
2728
import java.awt.Frame;
2829
import java.awt.Graphics;
2930
import java.awt.Rectangle;
3031
import java.awt.Robot;
32+
import java.awt.Toolkit;
3133
import java.awt.Window;
3234
import java.awt.image.BufferedImage;
3335
import java.io.BufferedOutputStream;
@@ -36,8 +38,11 @@
3638
import java.io.FileOutputStream;
3739
import java.io.IOException;
3840
import java.lang.reflect.InvocationTargetException;
41+
import java.text.DateFormat;
42+
import java.text.SimpleDateFormat;
3943
import java.util.ArrayList;
4044
import java.util.Collections;
45+
import java.util.Date;
4146
import java.util.List;
4247
import java.util.function.Function;
4348
import java.util.function.Supplier;
@@ -83,6 +88,19 @@
8388
*/
8489
public class JemmyExt {
8590

91+
private static Robot robot = null;
92+
93+
public static Robot getRobot() {
94+
try {
95+
if(robot == null) {
96+
robot = new Robot();
97+
}
98+
return robot;
99+
} catch (AWTException e) {
100+
throw new RuntimeException(e);
101+
}
102+
}
103+
86104
/**
87105
* Statically referencing all the classes that are needed by tests so that
88106
* they're compiled by jtreg
@@ -151,78 +169,62 @@ public Boolean launch() throws Exception {
151169
});
152170
}
153171

154-
public static void assertEquals(String string, StrictImageComparator comparator, BufferedImage expected, BufferedImage actual) {
155-
try {
156-
assertTrue(string, comparator.compare(expected, actual));
157-
} catch (Error err) {
158-
save(expected, "expected.png");
159-
save(actual, "actual.png");
160-
throw err;
161-
}
172+
private static final DateFormat timestampFormat = new SimpleDateFormat("yyyyMMddHHmmss");
173+
private static String timeStamp() {
174+
return timestampFormat.format(new Date());
162175
}
163176

164-
public static void assertNotEquals(String string, StrictImageComparator comparator, BufferedImage notExpected, BufferedImage actual) {
165-
try {
166-
assertFalse(string, comparator.compare(notExpected, actual));
167-
} catch (Error err) {
168-
save(notExpected, "notExpected.png");
169-
save(actual, "actual.png");
170-
throw err;
171-
}
177+
/**
178+
* Constructs filename with a timestamp.
179+
* @param name File name or a path without the extension
180+
* @param extension File extension (without the dot). Could be null,
181+
* in which case timestamp is simply added to the filename (no trailing dot).
182+
* @return file name
183+
*/
184+
public static String timeStamp(String name, String extension) {
185+
return name + "-" + timeStamp() +
186+
((extension != null) ? ("." + extension) : "");
187+
}
188+
189+
/**
190+
* Saves an image into a file. Filename will be constructed from the given fileID and
191+
* a timestamp.
192+
* @param image
193+
* @param fileID
194+
*/
195+
public static void save(BufferedImage image, String fileID) {
196+
doSave(image, timeStamp(fileID + "-" + lafShortName(), "png"));
172197
}
173198

174-
public static void save(BufferedImage image, String filename) {
175-
String filepath = filename;
199+
//Saves an image into a file with the provided filename
200+
private static void doSave(BufferedImage image, String filename) {
176201
try {
177-
filepath = new File(filename).getCanonicalPath();
202+
String filepath = new File(filename).getCanonicalPath();
178203
System.out.println("Saving screenshot to " + filepath);
179204
BufferedOutputStream file = new BufferedOutputStream(new FileOutputStream(filepath));
180205
new PNGEncoder(file, PNGEncoder.COLOR_MODE).encode(image);
181206
} catch (IOException ioe) {
182-
throw new RuntimeException("Failed to save image to " + filepath, ioe);
207+
throw new RuntimeException("Failed to save image to " + filename, ioe);
183208
}
184209
}
185210

186-
/**
187-
* Waits for a screen area taken by a component to not be completely black rectangle.
188-
* @return last (non-black) image
189-
* @throws TimeoutExpiredException if the waiting is unsuccessful
190-
*/
191-
public static BufferedImage waitNotBlack(Robot rob, ComponentOperator operator, String imageName) {
192-
class NonBlackImageChooser implements ComponentChooser {
193-
private BufferedImage image = null;
194-
@Override
195-
public boolean checkComponent(Component comp) {
196-
image = capture(rob, operator);
197-
save(image, imageName);
198-
return !isBlack(image);
199-
}
200-
201-
@Override
202-
public String getDescription() {
203-
return "A non-black Image of " + operator;
204-
}
205-
}
206-
NonBlackImageChooser chooser = new NonBlackImageChooser();
207-
operator.waitState(chooser);
208-
return chooser.image;
209-
}
210-
211211
/**
212212
* Waits for the displayed image to be still.
213+
* @param imageID an image ID with no extension. Timestamp and LAF information is added to the ID when saving.
213214
* @return last still image
214215
* @throws TimeoutExpiredException if the waiting is unsuccessful
215216
*/
216-
public static BufferedImage waitStillImage(Robot rob, ComponentOperator operator, String imageName) {
217+
public static BufferedImage waitStillImage(ComponentOperator operator, String imageID) {
217218
operator.getTimeouts().setTimeout("Waiter.TimeDelta", 1000);
219+
String timestampName = timeStamp(imageID + "-" + lafShortName(), "png");
218220
class StillImageChooser implements ComponentChooser {
219221
private BufferedImage previousImage = null;
220222
private final StrictImageComparator sComparator = new StrictImageComparator();
221223

222224
@Override
223225
public boolean checkComponent(Component comp) {
224-
BufferedImage currentImage = capture(rob, operator);
225-
save(currentImage, imageName);
226+
BufferedImage currentImage = capture(operator);
227+
doSave(currentImage, timestampName);
226228
boolean compareResult = previousImage == null ? false : sComparator.compare(currentImage, previousImage);
227229
previousImage = currentImage;
228230
return compareResult;
@@ -241,22 +243,23 @@ public String getDescription() {
241243
/**
242244
* Waits for the displayed image to change.
243245
* @param reference image to compare to
246+
* @param imageID an image ID with no extension. Timestamp and LAF information is added to the ID when saving.
244247
* @return last (changed) image
245248
* @throws TimeoutExpiredException if the waiting is unsuccessful
246249
*/
247-
public static BufferedImage waitChangedImage(Robot rob,
248-
Supplier<BufferedImage> supplier,
250+
public static BufferedImage waitChangedImage(Supplier<BufferedImage> supplier,
249251
BufferedImage reference,
250252
Timeouts timeouts,
251-
String imageName) throws InterruptedException {
253+
String imageID) throws InterruptedException {
252254
ImageComparator comparator = new StrictImageComparator();
255+
String timestampName = timeStamp(imageID + "-" + lafShortName(), "png");
253256
class ImageWaitable implements Waitable {
254257
BufferedImage image;
255258

256259
@Override
257260
public Object actionProduced(Object obj) {
258261
image = supplier.get();
259-
save(image, imageName);
262+
doSave(image, timestampName);
260263
return comparator.compare(reference, image) ? null : image;
261264
}
262265

@@ -316,10 +319,10 @@ public String getDescription() {
316319
}
317320
}
318321

319-
public static BufferedImage capture(Robot rob, ComponentOperator operator) {
322+
public static BufferedImage capture(ComponentOperator operator) {
320323
Rectangle boundary = new Rectangle(operator.getLocationOnScreen(),
321324
operator.getSize());
322-
return rob.createScreenCapture(boundary);
325+
return getRobot().createScreenCapture(boundary);
323326
}
324327

325328
/**
@@ -400,26 +403,26 @@ public void registerRoot(Throwable t) {
400403
}
401404
}
402405

406+
private static String lafShortName() { return UIManager.getLookAndFeel().getClass().getSimpleName(); }
407+
403408
/**
404409
* Trying to capture as much information as possible. Currently it includes
405410
* full dump and a screenshot of the whole screen.
406411
*/
407412
public static void captureAll() {
408-
String lookAndFeelClassName = UIManager.getLookAndFeel().getClass().getSimpleName();
409-
PNGEncoder.captureScreen("failure_" + lookAndFeelClassName + ".png", PNGEncoder.COLOR_MODE);
413+
save(getRobot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())), "failure");
410414
try {
411-
Dumper.dumpAll("dumpAll_" + lookAndFeelClassName + ".xml");
415+
Dumper.dumpAll(timeStamp("dumpAll-" + lafShortName(), "xml"));
412416
} catch (FileNotFoundException ex) {
413417
Logger.getLogger(JemmyExt.class.getName()).log(Level.SEVERE, null, ex);
414418
}
415-
captureWindows(lookAndFeelClassName);
419+
captureWindows();
416420
}
417421

418422
/**
419423
* Captures each showing window image using Window.paint() method.
420-
* @param lookAndFeelClassName
421424
*/
422-
private static void captureWindows(String lookAndFeelClassName) {
425+
private static void captureWindows() {
423426
try {
424427
EventQueue.invokeAndWait(() -> {
425428
Window[] windows = Window.getWindows();
@@ -434,10 +437,14 @@ private static void captureWindows(String lookAndFeelClassName) {
434437
g.dispose();
435438

436439
try {
437-
ImageIO.write(img, "png", new File("window_" + lookAndFeelClassName
438-
+ "_" + index++ + ".png"));
439-
} catch (IOException e) {
440-
e.printStackTrace();
440+
save(img, "window-" + index++);
441+
} catch (RuntimeException e) {
442+
if (e.getCause() instanceof IOException) {
443+
System.err.println("Failed to save screen images");
444+
e.printStackTrace();
445+
} else {
446+
throw e;
447+
}
441448
}
442449
}
443450
});

0 commit comments

Comments
 (0)