001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package framework;
042:
043: import org.netbeans.api.visual.widget.Scene;
044: import org.netbeans.junit.NbTestCase;
045:
046: import javax.imageio.ImageIO;
047: import javax.swing.*;
048: import java.awt.*;
049: import java.awt.image.BufferedImage;
050: import java.io.File;
051: import java.io.IOException;
052:
053: /**
054: * Visual test case allows to create visual test - usually by creating a snapshot of a scene rendered into an image.
055: * Then the image can been "cleaned" by a specific colors at particular regions.
056: * Then the image can be tested if colors that remains there.
057: *
058: * @author David Kaspar
059: */
060: public class VisualTestCase extends NbTestCase {
061:
062: /**
063: * Creates a new visual test case.
064: * @param testName the test name
065: */
066: public VisualTestCase(String testName) {
067: super (testName);
068: }
069:
070: /**
071: * Shows a frame for a scene and wait until it shown on a screen. View size is [400,300].
072: * @param scene the scene
073: * @return the frame; null if the frame is not shown in 10 seconds
074: */
075: public JFrame showFrame(Scene scene) {
076: return showFrame(scene, 400, 300);
077: }
078:
079: /**
080: * Shows a frame of for a scene and wait until it shown on a screen.
081: * @param scene the scene
082: * @param width the view width
083: * @param height the view height
084: * @return the frame; null if the frame is not shown in 10 seconds
085: */
086: public JFrame showFrame(Scene scene, int width, int height) {
087: assert scene != null;
088:
089: JFrame frame = new JFrame();
090: frame.getContentPane().setLayout(new BorderLayout());
091: JComponent view = scene.createView();
092: view.setPreferredSize(new Dimension(width, height));
093: frame.getContentPane().add(view, BorderLayout.CENTER);
094: frame.pack();
095: frame.setVisible(true);
096: int countdown = 10;
097: for (;;) {
098: if (frame.isShowing() && scene.isValidated())
099: break;
100: if (--countdown < 0) {
101: frame.setVisible(false);
102: frame.dispose();
103: return null;
104: }
105: try {
106: Thread.sleep(1000);
107: } catch (InterruptedException e) {
108: e.printStackTrace();
109: }
110: }
111: return frame;
112: }
113:
114: /**
115: * Takes a snapshot of a scene. This method assumes that the scene view is already shown on the screen
116: * and therefore the scene is initialized correctly.
117: * @param scene the scene
118: * @return the snapshot
119: */
120: public BufferedImage takeSnapshot(Scene scene) {
121: assert scene != null;
122: Dimension viewSize = scene.getView().getSize();
123: assert viewSize.width >= 0 && viewSize.height >= 0;
124: return takeSnapshot(scene, viewSize.width, viewSize.height);
125: }
126:
127: /**
128: * Takes a snapshot of a scene. This method assumes that the scene view is already shown on the screen
129: * and therefore the scene is initialized correctly.
130: * @param scene the scene
131: * @param width the snapshot width
132: * @param height the snapshot height
133: * @return the snapshot
134: */
135: public BufferedImage takeSnapshot(Scene scene, int width, int height) {
136: assert scene != null;
137: BufferedImage snapshot = new BufferedImage(width, height,
138: BufferedImage.TYPE_INT_RGB);
139: Graphics2D snapshotGraphics = snapshot.createGraphics();
140: scene.paint(snapshotGraphics);
141: snapshotGraphics.dispose();
142: return snapshot;
143: }
144:
145: /**
146: * Takes a one-time snapshot. Similar to takeSnapshot method but it automatically creates and disposes a frame for it.
147: * @param scene the scene
148: * @return the snapshot
149: */
150: public BufferedImage takeOneTimeSnapshot(Scene scene) {
151: JFrame frame = showFrame(scene);
152: BufferedImage snapshot = takeSnapshot(scene);
153: assert scene != null;
154: frame.setVisible(false);
155: frame.dispose();
156: return snapshot;
157: }
158:
159: /**
160: * Takes a one-time snapshot. Similar to takeSnapshot method but it automatically creates and disposes a frame for it.
161: * @param scene the scene
162: * @param width the scene width
163: * @param height the scene height
164: * @return the snapshot
165: */
166: public BufferedImage takeOneTimeSnapshot(Scene scene, int width,
167: int height) {
168: JFrame frame = showFrame(scene, width, height);
169: BufferedImage snapshot = takeSnapshot(scene, width, height);
170: assert scene != null;
171: frame.setVisible(false);
172: frame.dispose();
173: return snapshot;
174: }
175:
176: /**
177: * Creates a new image which is a copy of a specified image and contains "clean" regions.
178: * @param image the image to be copied
179: * @param clearColor the color by which the regions are cleaned.
180: * @param clearShapes the clean regions
181: * @return the clean image
182: */
183: public BufferedImage clearRegions(BufferedImage image,
184: Color clearColor, Shape... clearShapes) {
185: BufferedImage clean = new BufferedImage(image.getWidth(), image
186: .getHeight(), BufferedImage.TYPE_INT_RGB);
187: Graphics2D cleanGraphics = clean.createGraphics();
188: cleanGraphics.drawImage(image, 0, 0, null);
189: cleanGraphics.setColor(clearColor);
190: for (Shape shape : clearShapes)
191: cleanGraphics.fill(shape);
192: cleanGraphics.dispose();
193: return clean;
194: }
195:
196: /**
197: * Checks whether an image contains only specified colors.
198: * @param image the image
199: * @param colors the colors
200: * @return true if the image contains specified colors only; false otherwise
201: */
202: public boolean testCleaness(BufferedImage image, Color... colors) {
203: int[] rgbs = new int[colors.length];
204: for (int a = 0; a < colors.length; a++)
205: rgbs[a] = colors[a].getRGB();
206: int height = image.getHeight();
207: int width = image.getWidth();
208: for (int y = 0; y < height; y++)
209: for (int x = 0; x < width; x++) {
210: boolean isClean = false;
211: for (int rgb : rgbs)
212: if (image.getRGB(x, y) == rgb) {
213: isClean = true;
214: break;
215: }
216: if (!isClean)
217: return false;
218: }
219: return true;
220: }
221:
222: /**
223: * Saves an image into the working directory of the test.
224: * @param image the image to save
225: * @param imageID the image id used as an image file name
226: */
227: public void saveImage(BufferedImage image, String imageID) {
228: if (image == null)
229: return;
230: try {
231: ImageIO.write(image, "png", new File(getWorkDir(), imageID
232: + ".png")); // NOI18N
233: } catch (IOException e) {
234: e.printStackTrace();
235: }
236: }
237:
238: /**
239: * Asserts cleaness and optionally saves snapshots.
240: * @param isClean if true, nothing happens; if false, the assertion fails
241: * @param snapshot the snapshot image
242: * @param clean the clean snapshot image
243: */
244: public void assertCleaness(boolean isClean, BufferedImage snapshot,
245: BufferedImage clean) {
246: if (!isClean) {
247: saveImage(snapshot, "snapshot");
248: saveImage(clean, "clean-snapshot");
249: assertTrue("The scene snapshot is not clean.", isClean);
250: }
251: }
252:
253: /**
254: * Asserts a scene by taking its snapshots, cleaning specified regions with clear color and asserting that the clear color remains in the snapshot.
255: * @param scene the scene
256: * @param clearColor the clear color
257: * @param clearShapes the clear regions
258: */
259: public void assertScene(Scene scene, Color clearColor,
260: Shape... clearShapes) {
261: BufferedImage snapshot = takeOneTimeSnapshot(scene);
262: BufferedImage clean = clearRegions(snapshot, clearColor,
263: clearShapes);
264: assertCleaness(testCleaness(clean, clearColor), snapshot, clean);
265: }
266:
267: }
|