mirror of https://github.com/rusefi/jzy3d-api.git
tester project
This commit is contained in:
parent
15c28a492c
commit
82319ab910
|
@ -0,0 +1,18 @@
|
|||
*.class
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
/target/
|
||||
|
||||
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
|
@ -0,0 +1,44 @@
|
|||
# jzy3d-tester
|
||||
|
||||
A set of tools to test charts
|
||||
|
||||
## ChartTester
|
||||
|
||||
ChartTester is A non regression test tool allowing to compare screenshots of charts.
|
||||
|
||||
Works as follow
|
||||
- Generates an image first time the test is ran. The developer should verify the image is correct.
|
||||
- Compare a chart screenshot with the reference image. Test succeed if the two images are similar. If image differ, a DIFF image is generated indicating where pixel differ.
|
||||
|
||||
```java
|
||||
Chart chart = ...;
|
||||
ChartTester.assertSimilar(chart, "path/to/reference.png");
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Mocks
|
||||
|
||||
A simple implementation of GL interface is provided to keep in memory all calls to GL primitives (glVertex3f, glColor, etc).
|
||||
|
||||
It is used to ensure Jzy3d geometries and datamodel properly lead to expected GL calls :
|
||||
|
||||
```java
|
||||
// Given
|
||||
Point p = new Point();
|
||||
p.setData(new Coord3d(3, 30, 1000));
|
||||
|
||||
// When
|
||||
GLMock glMock = new GLMock();
|
||||
p.draw(glMock, null, null);
|
||||
|
||||
// Then
|
||||
Assert.assertTrue(glMock.vertex3f_contains(3, 30, 1000));
|
||||
```
|
||||
|
||||
|
||||
## Replay
|
||||
|
||||
Replay is a tool to record a sequence of mouse actions on a chart and then replay the mouse scenario to ensure the final chart image is the same as the reference scenario.
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 211 KiB |
Binary file not shown.
After Width: | Height: | Size: 157 KiB |
|
@ -0,0 +1,64 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.jzy3d</groupId>
|
||||
<artifactId>jzy3d-tester</artifactId>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
<name>Jzy3d Tester</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.jzy3d</groupId>
|
||||
<artifactId>jzy3d-master</artifactId>
|
||||
<version>1.0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jzy3d</groupId>
|
||||
<artifactId>jzy3d-api</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.9</version>
|
||||
<type>jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<systemProperties>
|
||||
<property>
|
||||
<name>java.util.logging.config.file</name>
|
||||
<value>logging.properties</value>
|
||||
</property>
|
||||
</systemProperties>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>2.3.2</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
<!-- RELEASE PLUGIN TO HELP CREATE RELEASE BRANCHES -->
|
||||
<plugin>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,58 @@
|
|||
package org.jzy3d.junit;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.jzy3d.maths.IntegerCoord2d;
|
||||
|
||||
|
||||
public class ChartTestFailed extends Exception{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 3514756078633688965L;
|
||||
public ChartTestFailed() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ChartTestFailed(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public ChartTestFailed(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ChartTestFailed(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public ChartTestFailed(String message, BufferedImage actual, BufferedImage expected) {
|
||||
super(message);
|
||||
this.actual = actual;
|
||||
this.expected = expected;
|
||||
}
|
||||
|
||||
public BufferedImage getActualImage() {
|
||||
return actual;
|
||||
}
|
||||
|
||||
public BufferedImage getExpectedImage() {
|
||||
return expected;
|
||||
}
|
||||
|
||||
public void addDiffCoordinates(int i, int j){
|
||||
if(diffs==null)
|
||||
diffs = new ArrayList<IntegerCoord2d>();
|
||||
diffs.add(new IntegerCoord2d(i, j));
|
||||
}
|
||||
|
||||
public List<IntegerCoord2d> getDiffCoordinates(){
|
||||
return diffs;
|
||||
}
|
||||
|
||||
protected BufferedImage actual;
|
||||
protected BufferedImage expected;
|
||||
protected List<IntegerCoord2d> diffs;
|
||||
}
|
||||
|
|
@ -0,0 +1,319 @@
|
|||
package org.jzy3d.junit;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.junit.Assert;
|
||||
import org.jzy3d.chart.AWTChart;
|
||||
import org.jzy3d.chart.Chart;
|
||||
import org.jzy3d.chart.controllers.mouse.camera.AWTCameraMouseController;
|
||||
import org.jzy3d.chart.factories.AWTChartComponentFactory;
|
||||
import org.jzy3d.chart.factories.IChartComponentFactory.Toolkit;
|
||||
import org.jzy3d.maths.IntegerCoord2d;
|
||||
import org.jzy3d.plot3d.primitives.AbstractDrawable;
|
||||
import org.jzy3d.plot3d.rendering.canvas.Quality;
|
||||
import org.jzy3d.plot3d.rendering.view.AWTRenderer3d;
|
||||
|
||||
import com.jogamp.opengl.GL;
|
||||
import com.jogamp.opengl.util.texture.TextureData;
|
||||
import com.jogamp.opengl.util.texture.TextureIO;
|
||||
|
||||
/**
|
||||
* Primitives for chart tests.
|
||||
*
|
||||
* A chart having a screenshot different from the test case
|
||||
* image will generate throw a ChartTestFailed exception.
|
||||
*
|
||||
* @author martin
|
||||
*/
|
||||
public class ChartTester{
|
||||
static Logger logger = Logger.getLogger(ChartTester.class);
|
||||
|
||||
public static AWTChart offscreen(AbstractDrawable... drawables) {
|
||||
// Initialize chart
|
||||
Quality q = Quality.Intermediate;
|
||||
|
||||
AWTChartComponentFactory f = new AWTChartComponentFactory();
|
||||
AWTChart chart = (AWTChart)f.newChart(q, Toolkit.offscreen);
|
||||
AWTCameraMouseController mouse = (AWTCameraMouseController) chart.addMouseCameraController();
|
||||
|
||||
// Optimise processor
|
||||
chart.setAnimated(false);// keep animated otherwise mouse wheel not properly updating
|
||||
mouse.setUpdateViewDefault(!chart.getQuality().isAnimated());
|
||||
|
||||
for (AbstractDrawable d : drawables)
|
||||
chart.add(d);
|
||||
return chart;
|
||||
}
|
||||
|
||||
public static void assertSimilar(Chart chart, String testImage){
|
||||
try {
|
||||
new ChartTester().execute(chart, testImage);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
assertTrue(testImage, true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* In Java, a mouse click only registers if the mouse is pressed and
|
||||
* released without moving the mouse at all. This is difficult for most
|
||||
* users to accomplish, so most UI elements (like buttons) react to the
|
||||
* mouse press and release events and ignore the "click".
|
||||
*/
|
||||
|
||||
/**
|
||||
* Run a chart and verify if its screenshot is pixelwise similar to the test
|
||||
* case image.
|
||||
*
|
||||
* If test case image does not exist, build it for the first time.
|
||||
*
|
||||
* Failure to compare the chart with the test case image will create an
|
||||
* image <code>data/tests/error-[name].png</code>. This image is always
|
||||
* deleted before running a testcase.
|
||||
*
|
||||
* Calling clean() will delete the test case image.
|
||||
*
|
||||
* @param chart
|
||||
* @param testImage
|
||||
* @throws IOException
|
||||
* if a non chart related error occurs. Actual chart test errors
|
||||
* call <code>fail(...)</code>
|
||||
*/
|
||||
public void execute(Chart chart, String testImage) throws IOException {
|
||||
clean(getTestCaseFailedFileName());
|
||||
|
||||
if (!isBuilt(testImage))
|
||||
build(chart, testImage);
|
||||
test(chart, testImage);
|
||||
}
|
||||
|
||||
public void execute(Chart chart) throws IOException {
|
||||
execute(chart, getTestCaseFileName());
|
||||
}
|
||||
|
||||
/* Primitives to test images */
|
||||
|
||||
public void clean(String testImage) {
|
||||
if (!cleanFile(testImage) && isBuilt(testImage))
|
||||
logger.warn("test case file not cleaned: " + testImage);
|
||||
}
|
||||
|
||||
public boolean cleanFile(String file) {
|
||||
return new File(file).delete();
|
||||
}
|
||||
|
||||
public void build(Chart chart, String testImage) throws IOException {
|
||||
logger.warn("building the screenshot to assert later as no test image is available: " + testImage);
|
||||
screenshot(chart, testImage);
|
||||
}
|
||||
|
||||
public void build(TextureData image, String testImage) throws IOException {
|
||||
logger.warn("saving the image to assert later as no test image is available: " + testImage);
|
||||
screenshot(image, testImage);
|
||||
}
|
||||
|
||||
public boolean isBuilt(String testImage) {
|
||||
return new File(testImage).exists();
|
||||
}
|
||||
|
||||
public void test(Chart chart, String testImage) throws IOException {
|
||||
try {
|
||||
logger.info("compare chart with " + testImage);
|
||||
compare(chart, testImage);
|
||||
} catch (IOException e) {
|
||||
fail("IOException: " + e.getMessage() + " for " + testImage);
|
||||
} catch (ChartTestFailed e) {
|
||||
String errorFile = getTestCaseFailedFileName() + new File(testImage).getName().replace(".", "#ERROR#.");
|
||||
String diffFile = getTestCaseFailedFileName() + new File(testImage).getName().replace(".", "#DIFF#.");
|
||||
screenshot(chart, errorFile);
|
||||
|
||||
BufferedImage expected = e.getExpectedImage();
|
||||
|
||||
for(IntegerCoord2d diffs : e.getDiffCoordinates()){
|
||||
pixelInvert(expected, diffs);
|
||||
}
|
||||
ImageIO.write(expected, "png", new File(diffFile));
|
||||
|
||||
fail("Chart test failed: " + e.getMessage() + " see " + testImage);
|
||||
}
|
||||
}
|
||||
|
||||
private void pixelInvert(BufferedImage expected, IntegerCoord2d diffs) {
|
||||
int rgb = expected.getRGB(diffs.x, diffs.y);
|
||||
|
||||
int alpha = ((rgb >> 24) & 0xff);
|
||||
int red = ((rgb >> 16) & 0xff);
|
||||
int green = ((rgb >> 8) & 0xff);
|
||||
int blue = ((rgb ) & 0xff);
|
||||
|
||||
rgb = (alpha << 24) | (255-red << 16) | (255-green << 8) | 255-blue;
|
||||
expected.setRGB(diffs.x, diffs.y, rgb);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
/**
|
||||
* Compare the image displayed by the chart with an image given by filename
|
||||
* @param chart
|
||||
* @param filename
|
||||
* @throws IOException
|
||||
* @throws ChartTestFailed
|
||||
*/
|
||||
public void compare(Chart chart, String filename) throws IOException, ChartTestFailed {
|
||||
|
||||
// Will compare buffered image
|
||||
if(chart.getCanvas().getRenderer() instanceof AWTRenderer3d){
|
||||
chart.screenshot();
|
||||
AWTRenderer3d awtR = (AWTRenderer3d)chart.getCanvas().getRenderer();
|
||||
BufferedImage actual = awtR.getLastScreenshotImage();
|
||||
BufferedImage expected = loadBufferedImage(filename);
|
||||
|
||||
compare(actual, expected);
|
||||
}
|
||||
else {
|
||||
TextureData actual = chart.screenshot();
|
||||
TextureData expected = loadTextureData(filename, chart.getView().getCurrentGL());
|
||||
fail("CAN NOT COMPARE TEXTURE DATA FOR THE MOMENT");
|
||||
}
|
||||
}
|
||||
|
||||
public BufferedImage loadBufferedImage(String filename) throws IOException{
|
||||
return ImageIO.read(new File(filename));
|
||||
}
|
||||
|
||||
public TextureData loadTextureData(String filename, GL gl) throws IOException {
|
||||
TextureData i2 = TextureIO.newTextureData(gl.getGLProfile(), new File(filename), true, null);
|
||||
return i2;
|
||||
}
|
||||
|
||||
|
||||
public void compare(BufferedImage actual, BufferedImage expected) throws ChartTestFailed {
|
||||
// int rbg = image.getRGB((int) x, (maxRow) - ((int) y));
|
||||
|
||||
int i1W = actual.getWidth();
|
||||
int i1H = actual.getHeight();
|
||||
int i2W = expected.getWidth();
|
||||
int i2H = expected.getHeight();
|
||||
|
||||
|
||||
if (i1W == i2W && i1H == i2H) {
|
||||
ChartTestFailed potentialFailure = new ChartTestFailed("pixel diff", actual, expected);
|
||||
boolean ok = true;
|
||||
|
||||
for (int i = 0; i < i1W; i++) {
|
||||
for (int j = 0; j < i1H; j++) {
|
||||
int p1rgb = actual.getRGB(i, j);
|
||||
int p2rgb = expected.getRGB(i, j);
|
||||
|
||||
if (p1rgb != p2rgb) {
|
||||
ok = false;
|
||||
potentialFailure.addDiffCoordinates(i, j);
|
||||
//String m = "pixel diff start @(" + i + "," + j + ")";
|
||||
//throw new ChartTestFailed(m, i1, i2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!ok){
|
||||
throw potentialFailure;
|
||||
}
|
||||
|
||||
} else {
|
||||
String m = "image size differ: i1={" + i1W + "," + i1H + "} i2={" + i2W + "," + i2H + "}";
|
||||
throw new ChartTestFailed(m);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare images pixel-wise.
|
||||
*
|
||||
* @param i1
|
||||
* @param i2
|
||||
* @throws ChartTestFailed
|
||||
* as soon as a pixel difference can be found
|
||||
*/
|
||||
public void compare(TextureData i1, TextureData i2) throws ChartTestFailed {
|
||||
// int rbg = image.getRGB((int) x, (maxRow) - ((int) y));
|
||||
|
||||
int i1W = i1.getWidth();
|
||||
int i1H = i1.getHeight();
|
||||
int i2W = i2.getWidth();
|
||||
int i2H = i2.getHeight();
|
||||
|
||||
if (i1W == i2W && i1H == i2H) {
|
||||
for (int i = 0; i < i1W; i++) {
|
||||
for (int j = 0; j < i1H; j++) {
|
||||
/*int p1rgb = i1.getRGB(i, j);
|
||||
int p2rgb = i2.getRGB(i, j);
|
||||
if (p1rgb != p2rgb) {
|
||||
String m = "pixel diff @(" + i + "," + j + ")";
|
||||
throw new ChartTestFailed(m, i1, i2);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
} else {
|
||||
String m = "image size differ: i1={" + i1W + "," + i1H + "} i2={" + i2W + "," + i2H + "}";
|
||||
throw new ChartTestFailed(m);
|
||||
}
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
public void screenshot(Chart chart, String filename) throws IOException {
|
||||
screenshot(chart.screenshot(), filename);
|
||||
}
|
||||
|
||||
public void screenshot(TextureData image, String testImage) throws IOException {
|
||||
File output = new File(testImage);
|
||||
if (!output.getParentFile().exists())
|
||||
output.getParentFile().mkdirs();
|
||||
TextureIO.write(image, output);
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
public File getTestCaseFile() {
|
||||
return new File(getTestCaseFileName());
|
||||
}
|
||||
|
||||
public String getTestCaseFileName() {
|
||||
return getTestCaseFileName(getTestName());
|
||||
}
|
||||
|
||||
public String getTestCaseFileName(String testName) {
|
||||
return getTestCaseFolder() + testName + ".png";
|
||||
}
|
||||
|
||||
public String getTestCaseFailedFileName() {
|
||||
return getTestCaseFolder() + "error-";
|
||||
}
|
||||
|
||||
public String getTestCaseFolder() {
|
||||
return "data/tests/";
|
||||
}
|
||||
|
||||
public String getTestName() {
|
||||
return this.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
public String getTestCanvasType() {
|
||||
return "offscreen, " + WIDTH + ", " + HEIGHT;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
// int bufImgType = BufferedImage.TYPE_3BYTE_BGR;// );
|
||||
protected int WIDTH = 800;
|
||||
protected int HEIGHT = 600;
|
||||
}
|
||||
|
|
@ -0,0 +1,256 @@
|
|||
package org.jzy3d.junit.replay;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.event.InputEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseListener;
|
||||
import java.awt.event.MouseMotionListener;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.awt.event.MouseWheelListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jzy3d.chart.Chart;
|
||||
import org.jzy3d.junit.replay.events.ComponentEventLog;
|
||||
import org.jzy3d.junit.replay.events.IComponentEventLog.ComponentEventType;
|
||||
import org.jzy3d.junit.replay.events.IEventLog;
|
||||
import org.jzy3d.junit.replay.events.IKeyEventLog.KeyEventType;
|
||||
import org.jzy3d.junit.replay.events.IMouseEventLog.MouseEventType;
|
||||
import org.jzy3d.junit.replay.events.IWindowEventLog.WindowEventType;
|
||||
import org.jzy3d.junit.replay.events.KeyEventLog;
|
||||
import org.jzy3d.junit.replay.events.MouseEventLog;
|
||||
import org.jzy3d.junit.replay.events.WindowEventLog;
|
||||
import org.jzy3d.utils.LoggerUtils;
|
||||
|
||||
import com.jogamp.opengl.util.texture.TextureIO;
|
||||
|
||||
public class EventRecorder extends Timestamped implements MouseListener, MouseMotionListener, MouseWheelListener, KeyListener, ComponentListener, WindowListener {
|
||||
protected Component awt;
|
||||
protected Scenario scenario;
|
||||
protected Chart chart;
|
||||
protected int nScreenshot = 0;
|
||||
|
||||
public EventRecorder(String scenario, Component awt) {
|
||||
this(scenario, awt, null);
|
||||
}
|
||||
|
||||
public EventRecorder(String scenario, Component awt, Frame frame) {
|
||||
this(scenario, awt, frame, null);
|
||||
}
|
||||
|
||||
public EventRecorder(String scenario, Component awt, Frame frame, Chart chart) {
|
||||
this.chart = chart;
|
||||
this.awt = awt;
|
||||
this.scenario = new Scenario(scenario);
|
||||
addListeners(awt);
|
||||
if(frame!=null)
|
||||
addWindowListeners(frame);
|
||||
t.tic();
|
||||
LoggerUtils.minimal();
|
||||
}
|
||||
|
||||
protected void addListeners(Component awt) {
|
||||
awt.addMouseListener(this);
|
||||
awt.addMouseMotionListener(this);
|
||||
awt.addMouseWheelListener(this);
|
||||
awt.addKeyListener(this);
|
||||
awt.addComponentListener(this);
|
||||
}
|
||||
|
||||
protected void addWindowListeners(Frame frame) {
|
||||
frame.addWindowListener(this);
|
||||
}
|
||||
|
||||
protected void register(IEventLog event) {
|
||||
debugMs(event);
|
||||
scenario.register(event);
|
||||
}
|
||||
|
||||
protected void onExit() {
|
||||
try {
|
||||
scenario.save();
|
||||
} catch (Exception e) {
|
||||
logger.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Chart getChart() {
|
||||
return chart;
|
||||
}
|
||||
|
||||
public void setChart(Chart chart) {
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
protected boolean isScreenshotKey(KeyEvent e) {
|
||||
return e.getKeyChar() == 's';
|
||||
}
|
||||
|
||||
protected boolean isExit(KeyEvent e) {
|
||||
return e.getKeyChar() == 'q';
|
||||
}
|
||||
|
||||
protected String screenshotFile(int n) {
|
||||
return ScenarioFiles.SCENARIO_FOLDER + "/" + scenario.getName() + "/" + scenario.getName() + "-" + n + ".png";
|
||||
}
|
||||
|
||||
protected void screenshot(Chart chart, String filename) throws IOException {
|
||||
File output = new File(filename);
|
||||
if (!output.getParentFile().exists())
|
||||
output.mkdirs();
|
||||
TextureIO.write(chart.screenshot(), output);
|
||||
Logger.getLogger(EventRecorder.class).info("screenshot:" + filename);
|
||||
}
|
||||
|
||||
/* MOUSE */
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
register(new MouseEventLog(MouseEventType.MOUSE_WHEEL, e.getWheelRotation(), getButton(e), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
register(new MouseEventLog(MouseEventType.MOUSE_DRAGGED, e.getX(), e.getY(), getButton(e), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
register(new MouseEventLog(MouseEventType.MOUSE_MOVED, e.getX(), e.getY(), getButton(e), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
register(new MouseEventLog(MouseEventType.MOUSE_CLICKED, e.getX(), e.getY(), getButton(e), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
register(new MouseEventLog(MouseEventType.MOUSE_PRESSED, e.getX(), e.getY(), getButton(e), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
register(new MouseEventLog(MouseEventType.MOUSE_RELEASED, e.getX(), e.getY(), getButton(e), since()));
|
||||
}
|
||||
|
||||
protected int getButton(MouseEvent e) {
|
||||
int button = 0;
|
||||
if (e.getButton() == MouseEvent.BUTTON1)
|
||||
button = InputEvent.BUTTON1_MASK;
|
||||
if (e.getButton() == MouseEvent.BUTTON2)
|
||||
button = InputEvent.BUTTON2_MASK;
|
||||
if (e.getButton() == MouseEvent.BUTTON3)
|
||||
button = InputEvent.BUTTON3_MASK;
|
||||
return button;
|
||||
}
|
||||
|
||||
/* COMPONENT */
|
||||
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {
|
||||
register(new ComponentEventLog(ComponentEventType.COMPONENT_HIDDEN, since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
register(new ComponentEventLog(ComponentEventType.COMPONENT_MOVED, e.getComponent().getSize(), e.getComponent().getBounds(), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
register(new ComponentEventLog(ComponentEventType.COMPONENT_RESIZED, e.getComponent().getSize(), e.getComponent().getBounds(), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
register(new ComponentEventLog(ComponentEventType.COMPONENT_SHOWN, e.getComponent().getSize(), e.getComponent().getBounds(), since()));
|
||||
}
|
||||
|
||||
/* KEY */
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
// handle screenshot query
|
||||
if (isScreenshotKey(e)) {
|
||||
try {
|
||||
screenshot(chart, screenshotFile(nScreenshot));
|
||||
} catch (IOException e1) {
|
||||
Logger.getLogger(EventRecorder.class).error(screenshotFile(nScreenshot), e1);
|
||||
}
|
||||
nScreenshot++;
|
||||
}
|
||||
else if(isExit(e)){
|
||||
onExit();
|
||||
}
|
||||
// or register standard event
|
||||
else {
|
||||
register(new KeyEventLog(KeyEventType.KEY_TYPED, e.getKeyCode(), since()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
register(new KeyEventLog(KeyEventType.KEY_PRESS, e.getKeyCode(), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
register(new KeyEventLog(KeyEventType.KEY_RELEASE, e.getKeyCode(), since()));
|
||||
}
|
||||
|
||||
// protected String s
|
||||
|
||||
/* WINDOW */
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
register(new WindowEventLog(WindowEventType.WINDOW_CLOSING, e.getWindow().getSize(), since()));
|
||||
|
||||
onExit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
register(new WindowEventLog(WindowEventType.WINDOW_OPENED, e.getWindow().getSize(), since()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
register(new WindowEventLog(WindowEventType.WINDOW_CLOSED, since()));
|
||||
}
|
||||
|
||||
/* UNUSED */
|
||||
|
||||
@Override
|
||||
public void mouseEntered(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowActivated(WindowEvent arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeactivated(WindowEvent arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowIconified(WindowEvent arg0) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
package org.jzy3d.junit.replay;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Frame;
|
||||
import java.awt.Insets;
|
||||
import java.awt.Robot;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseMotionAdapter;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jzy3d.junit.replay.events.IComponentEventLog;
|
||||
import org.jzy3d.junit.replay.events.IComponentEventLog.ComponentEventType;
|
||||
import org.jzy3d.junit.replay.events.IEventLog;
|
||||
import org.jzy3d.junit.replay.events.IKeyEventLog;
|
||||
import org.jzy3d.junit.replay.events.IKeyEventLog.KeyEventType;
|
||||
import org.jzy3d.junit.replay.events.IMouseEventLog;
|
||||
import org.jzy3d.junit.replay.events.IMouseEventLog.MouseEventType;
|
||||
import org.jzy3d.junit.replay.events.IWindowEventLog;
|
||||
|
||||
public class EventReplay extends Timestamped{
|
||||
static Logger logger = Logger.getLogger(EventReplay.class);
|
||||
|
||||
protected Component component;
|
||||
protected Frame frame;
|
||||
protected Robot robot;
|
||||
protected Scenario currentScenario;
|
||||
protected boolean mute = false;
|
||||
protected boolean mustStop = false;
|
||||
|
||||
public EventReplay(final Component component, Frame frame){
|
||||
/*component.addMouseListener(new MouseAdapter(){
|
||||
public void mouseDragged(MouseEvent e){
|
||||
logger.info("DRAGGING");
|
||||
}
|
||||
});*/
|
||||
this.component = component;
|
||||
this.frame = frame;
|
||||
configureFocus(component, frame);
|
||||
}
|
||||
|
||||
protected void configureFocus(Component component, Frame frame) {
|
||||
component.addFocusListener(new FocusListener() {
|
||||
@Override
|
||||
public void focusLost(FocusEvent arg0) {
|
||||
mute();
|
||||
logger.info("mute event replay as component lost focus");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent arg0) {
|
||||
unmute();
|
||||
logger.info("unmute event replay as component gained focus");
|
||||
}
|
||||
});
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent arg0) {
|
||||
stop();
|
||||
logger.info("stop replay as window closes");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* REPLAY */
|
||||
|
||||
public void replay(String scenario) throws Exception {
|
||||
currentScenario = new Scenario(scenario);
|
||||
currentScenario.load();
|
||||
replay(currentScenario);
|
||||
}
|
||||
|
||||
public void replay(Scenario scenario) {
|
||||
//component.requestFocusInWindow();
|
||||
|
||||
getRobot().setAutoWaitForIdle(false);
|
||||
start();
|
||||
while(scenario.getEvents().size()>0){
|
||||
Iterator<IEventLog> events = scenario.getEvents().iterator();
|
||||
while(events.hasNext()){
|
||||
IEventLog event = events.next();
|
||||
if(elapsedMs(event)){
|
||||
if(!mute)
|
||||
replay(event);
|
||||
//debug(event);
|
||||
events.remove();
|
||||
}
|
||||
if(mustStop){
|
||||
scenario.info("done replay after " + elapsedMs()/1000 + " s");
|
||||
scenario.info("exiting before end");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
scenario.info("done replay after " + elapsedMs()/1000 + " s");
|
||||
/*for(IEventLog event: scenario.getEvents()){
|
||||
replay(event);
|
||||
}*/
|
||||
}
|
||||
|
||||
public void replay(IEventLog event) {
|
||||
if(event instanceof IMouseEventLog)
|
||||
replay((IMouseEventLog)event);
|
||||
else if(event instanceof IKeyEventLog)
|
||||
replay((IKeyEventLog)event);
|
||||
else if(event instanceof IComponentEventLog)
|
||||
replay((IComponentEventLog)event);
|
||||
else if(event instanceof IWindowEventLog)
|
||||
replay((IWindowEventLog)event);
|
||||
}
|
||||
|
||||
|
||||
public void replay(IMouseEventLog mouse) {
|
||||
Insets insets = frame.getInsets();
|
||||
|
||||
MouseEventType type = mouse.getType();
|
||||
if(type==MouseEventType.MOUSE_CLICKED)
|
||||
getRobot().mousePress(mouse.getButton());
|
||||
|
||||
else if(type==MouseEventType.MOUSE_PRESSED){
|
||||
getRobot().mousePress(mouse.getButton());
|
||||
}
|
||||
else if(type==MouseEventType.MOUSE_RELEASED){
|
||||
getRobot().mouseRelease(mouse.getButton());
|
||||
}
|
||||
else if(type==MouseEventType.MOUSE_DRAGGED){
|
||||
getRobot().mouseMove(moveX(mouse, insets), moveY(mouse, insets));
|
||||
}
|
||||
else if(type==MouseEventType.MOUSE_MOVED){
|
||||
getRobot().mouseMove(moveX(mouse, insets), moveY(mouse, insets));
|
||||
}
|
||||
else if(type==MouseEventType.MOUSE_WHEEL){
|
||||
getRobot().mouseWheel(mouse.getValue());
|
||||
}
|
||||
|
||||
//if(type!=MouseEventType.MOUSE_DRAGGED && type!=MouseEventType.MOUSE_MOVED)
|
||||
// log(mouse);
|
||||
}
|
||||
|
||||
protected int moveY(IMouseEventLog mouse, Insets insets) {
|
||||
return mouse.getCoord().y + frame.getBounds().y + insets.top;
|
||||
}
|
||||
|
||||
protected int moveX(IMouseEventLog mouse, Insets insets) {
|
||||
return mouse.getCoord().x + frame.getBounds().x + insets.left;
|
||||
}
|
||||
|
||||
public void replay(IKeyEventLog key) {
|
||||
try{
|
||||
if(key.getKeyCode()!=0){
|
||||
if(key.getType()==KeyEventType.KEY_PRESS)
|
||||
doKeyPress(key);
|
||||
else if(key.getType()==KeyEventType.KEY_RELEASE)
|
||||
doKeyRelease(key);
|
||||
else
|
||||
logger.warn("ignore key event " + key);
|
||||
}
|
||||
else
|
||||
logger.warn("ignore key event " + key + " because keycode=0");
|
||||
}
|
||||
catch(Exception e){
|
||||
log(key);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doKeyPress(IKeyEventLog key){
|
||||
getRobot().keyPress(key.getKeyCode());
|
||||
//keys[key.getKeyCode()]++;
|
||||
}
|
||||
|
||||
protected void doKeyRelease(IKeyEventLog key){
|
||||
getRobot().keyRelease(key.getKeyCode());
|
||||
//keys[key.getKeyCode()]--;
|
||||
}
|
||||
|
||||
protected void mute(){
|
||||
mute = true;
|
||||
}
|
||||
|
||||
protected void unmute() {
|
||||
mute = false;
|
||||
}
|
||||
|
||||
protected void stop() {
|
||||
mustStop = true;
|
||||
}
|
||||
|
||||
protected int[] keys = new int[256];
|
||||
|
||||
public void replay(IWindowEventLog window) {
|
||||
log(window, " not supported");
|
||||
}
|
||||
|
||||
public void replay(IComponentEventLog component) {
|
||||
if(component.getType().equals(ComponentEventType.COMPONENT_RESIZED)){
|
||||
Dimension size = component.getSize();
|
||||
frame.setSize(size);
|
||||
}
|
||||
//log(component, " not supported");
|
||||
}
|
||||
|
||||
protected void log(IEventLog event){
|
||||
logger.info("replay: " + event);
|
||||
}
|
||||
|
||||
protected void log(IEventLog event, String info){
|
||||
logger.info("replay: " + event + " " + info);
|
||||
}
|
||||
|
||||
public Robot getRobot(){
|
||||
if(robot==null)
|
||||
try {
|
||||
robot = new Robot();
|
||||
} catch (AWTException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
robot.setAutoWaitForIdle(true);
|
||||
return robot;
|
||||
}
|
||||
|
||||
/* UTILS 2 */
|
||||
|
||||
/**
|
||||
MOUSE_PRESSED, x:170, y:154, bt:0, since:925
|
||||
MOUSE_DRAGGED, x:149, y:171, bt:0, since:1428
|
||||
MOUSE_RELEASED, x:125, y:56, bt:0, since:3898
|
||||
MOUSE_MOVED, x:107, y:55, bt:0, since:3899
|
||||
|
||||
* @param mouse
|
||||
*/
|
||||
protected boolean detectDragEnd(IMouseEventLog mouse){
|
||||
MouseEventType type = mouse.getType();
|
||||
if(type==MouseEventType.MOUSE_PRESSED){
|
||||
drag = new IMouseEventLog[3];
|
||||
drag[0] = mouse;
|
||||
}
|
||||
else if(type==MouseEventType.MOUSE_DRAGGED)
|
||||
drag[1] = mouse;
|
||||
else if(type==MouseEventType.MOUSE_RELEASED){
|
||||
drag[2] = mouse;
|
||||
boolean f = full(drag);
|
||||
drag = new IMouseEventLog[3];
|
||||
if(f)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean full(IMouseEventLog[] drag){
|
||||
return drag!=null && drag[0]!=null && drag[1]!=null && drag[2]!=null;
|
||||
}
|
||||
|
||||
protected IMouseEventLog[] drag = new IMouseEventLog[3];
|
||||
|
||||
/* UTILS */
|
||||
|
||||
protected void debug(IEventLog event) {
|
||||
if(event instanceof IMouseEventLog){
|
||||
IMouseEventLog mouse = (IMouseEventLog)event;
|
||||
//if(isMouseMoveOrDrag(mouse)){
|
||||
debugMs(event);
|
||||
//}
|
||||
}
|
||||
else
|
||||
debugMs(event);
|
||||
}
|
||||
|
||||
protected boolean isMouseMoveOrDrag(IMouseEventLog mouse) {
|
||||
return mouse.getType()!=MouseEventType.MOUSE_DRAGGED && mouse.getType()!=MouseEventType.MOUSE_MOVED;
|
||||
}
|
||||
|
||||
protected void addVerifyingListeners(final Component component){
|
||||
component.addMouseMotionListener(new MouseMotionAdapter() {
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
logger.info("ASSERT DRAGGED CALLED ON COMPONENT");
|
||||
}
|
||||
});
|
||||
component.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent e) {
|
||||
logger.info("ASSERT MOVED CALLED ON COMPONENT");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void addFocusListener(final Component component, Frame frame) {
|
||||
frame.addWindowFocusListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowGainedFocus(WindowEvent e) {
|
||||
component.requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.jzy3d.junit.replay;
|
||||
|
||||
public class EventReplayDemo {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.jzy3d.junit.replay;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jzy3d.io.SimpleFile;
|
||||
import org.jzy3d.junit.replay.events.EventParser;
|
||||
import org.jzy3d.junit.replay.events.IEventLog;
|
||||
|
||||
public class Scenario {
|
||||
static Logger logger = Logger.getLogger(Scenario.class);
|
||||
|
||||
protected List<IEventLog> events;
|
||||
protected String name;
|
||||
|
||||
public Scenario(String name){
|
||||
this.name = name;
|
||||
this.events = new ArrayList<IEventLog>();
|
||||
}
|
||||
|
||||
public void register(IEventLog event){
|
||||
logger.info(event);
|
||||
events.add(event);
|
||||
}
|
||||
|
||||
public List<IEventLog> getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
public void setEvents(List<IEventLog> events) {
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
public void save() throws Exception{
|
||||
save(ScenarioFiles.SCENARIO_FOLDER + name + "/", name);
|
||||
}
|
||||
|
||||
protected void save(String folder) throws Exception{
|
||||
save(folder + "/" + name + "/", name);
|
||||
}
|
||||
|
||||
protected void save(String folder, String name) throws Exception{
|
||||
File ff = new File(folder);
|
||||
if(!ff.exists())
|
||||
ff.mkdirs();
|
||||
saveEvents(folder, name);
|
||||
}
|
||||
|
||||
protected void saveEvents(String folder, String name) throws Exception {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(IEventLog log: events)
|
||||
sb.append(log.toString() + "\n");
|
||||
String file = getEventFile(folder, name);
|
||||
SimpleFile.write(sb.toString(), file);
|
||||
info("saved " + events.size() + " events in " + file);
|
||||
}
|
||||
|
||||
public void info(String file) {
|
||||
logger.info("---------------------------------------------------");
|
||||
logger.info(file);
|
||||
logger.info("---------------------------------------------------");
|
||||
//Logger.getLogger(this.getClass()).info("saved events: " + file);
|
||||
}
|
||||
|
||||
public String getEventFile(String folder, String name) {
|
||||
return folder + name + ScenarioFiles.FILE_EVENTS;
|
||||
}
|
||||
|
||||
/* */
|
||||
|
||||
public void load() throws Exception{
|
||||
load(ScenarioFiles.SCENARIO_FOLDER, name);
|
||||
}
|
||||
|
||||
protected void load(String folder, String name) throws IOException{
|
||||
loadEvents(folder, name);
|
||||
}
|
||||
|
||||
protected void loadEvents(String folder, String name) throws IOException {
|
||||
events.clear();
|
||||
String file = getEventFile(folder, name);
|
||||
List<String> lines = SimpleFile.read(file);
|
||||
EventParser parser = new EventParser();
|
||||
|
||||
for(String s: lines){
|
||||
//logger.info("read : " + s);
|
||||
IEventLog event = parser.parse(s);
|
||||
if(event!=null){
|
||||
logger.info("parsed : " + event);
|
||||
events.add(event);
|
||||
}
|
||||
else
|
||||
logger.error("non parsable event : " + s);
|
||||
}
|
||||
|
||||
info("parsed " + events.size() + " events from " + file);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package org.jzy3d.junit.replay;
|
||||
|
||||
public class ScenarioFiles {
|
||||
public static String SCENARIO_FOLDER = "data/scenarios/";
|
||||
public static String FILE_EVENTS = "-events.txt";
|
||||
public static String FILE_SCREENSHOT = "-screenshot-";
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.jzy3d.junit.replay;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
import org.jzy3d.junit.replay.events.IEventLog;
|
||||
import org.jzy3d.maths.TicToc;
|
||||
|
||||
/** To be enhanced (wrapper tictoc)*/
|
||||
public class Timestamped {
|
||||
static Logger logger = Logger.getLogger(Timestamped.class);
|
||||
|
||||
protected TicToc t = new TicToc();
|
||||
|
||||
public Timestamped() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
t.tic();
|
||||
}
|
||||
|
||||
public long startup() {
|
||||
return t.getStart();
|
||||
}
|
||||
|
||||
public long now() {
|
||||
long now = t.rawToc();
|
||||
return now;
|
||||
}
|
||||
|
||||
public long since() {
|
||||
t.toc();
|
||||
return (long)t.elapsedMilisecond();
|
||||
}
|
||||
|
||||
public long since(long now) {
|
||||
return now - startup();
|
||||
}
|
||||
|
||||
public long elapsedMs() {
|
||||
return (now() - startup())/(1000*1000);
|
||||
}
|
||||
|
||||
public boolean elapsedMs(IEventLog event) {
|
||||
return elapsedMs(event.since());
|
||||
}
|
||||
|
||||
public boolean elapsedMs(long time) {
|
||||
return elapsedMs() > time;
|
||||
}
|
||||
|
||||
public void debugMs(IEventLog event) {
|
||||
debugMs(event.since());
|
||||
}
|
||||
|
||||
public void debugMs(long time){
|
||||
long elapsed = elapsedMs();
|
||||
logger.info("-> @[" + time/1000 + " s] (" + time + " ms): elapsed:" + elapsed);
|
||||
//logger.info("-> @[" + time/1000 + " s] (" + time + " ms): elapsed:" + elapsed + ", now:" + now + ", start:" + startup());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
public class AbstractEventLog implements IEventLog{
|
||||
|
||||
protected long since;
|
||||
|
||||
@Override
|
||||
public long since() {
|
||||
return since;
|
||||
}
|
||||
|
||||
public AbstractEventLog() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
public class ComponentEventLog extends AbstractEventLog implements IComponentEventLog {
|
||||
protected ComponentEventType type;
|
||||
protected Object value;
|
||||
protected Dimension size;
|
||||
protected Rectangle bounds;
|
||||
|
||||
public ComponentEventLog(ComponentEventType type, long since) {
|
||||
this.type = type;
|
||||
this.since = since;
|
||||
}
|
||||
|
||||
public ComponentEventLog(ComponentEventType type, Object value, long since) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.since = since;
|
||||
}
|
||||
|
||||
public ComponentEventLog(ComponentEventType type, Dimension size, Rectangle bounds, long since) {
|
||||
this.type = type;
|
||||
this.since = since;
|
||||
this.size = size;
|
||||
this.bounds = bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentEventType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (value != null)
|
||||
return type + ", value:" + value + ", since:" + since;
|
||||
else if (size != null || bounds!=null)
|
||||
return type + ", size:" + size + ", bounds:" + bounds + ", since:" + since;
|
||||
else
|
||||
return type + ", since:" + since;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.jzy3d.junit.replay.events.IComponentEventLog.ComponentEventType;
|
||||
import org.jzy3d.junit.replay.events.IKeyEventLog.KeyEventType;
|
||||
import org.jzy3d.junit.replay.events.IMouseEventLog.MouseEventType;
|
||||
import org.jzy3d.junit.replay.events.IWindowEventLog.WindowEventType;
|
||||
|
||||
public class EventParser {
|
||||
static String word = "\\w+";
|
||||
static String word_list = "[\\w|,]+";
|
||||
static String num = "\\d+";
|
||||
static String antislash = "\\\\";
|
||||
static String slash = "\\/";
|
||||
|
||||
/*
|
||||
COMPONENT_RESIZED, size:java.awt.Dimension[width=490,height=470], bounds:java.awt.Rectangle[x=5,y=25,width=490,height=470], since:524
|
||||
COMPONENT_MOVED, size:java.awt.Dimension[width=498,height=471], bounds:java.awt.Rectangle[x=1,y=28,width=498,height=471], since:785
|
||||
|
||||
WINDOW_OPENED, v:java.awt.Dimension[width=500,height=500], since:525
|
||||
WINDOW_CLOSING, v:java.awt.Dimension[width=500,height=500], since:5120
|
||||
WINDOW_CLOSED, since:5120
|
||||
|
||||
MOUSE_MOVED, x:232, y:94, bt:0, since:702
|
||||
MOUSE_PRESSED, x:244, y:245, bt:1, since:1397
|
||||
MOUSE_DRAGGED, x:241, y:239, bt:0, since:1558
|
||||
MOUSE_RELEASED, x:145, y:58, bt:1, since:16214
|
||||
MOUSE_WHEEL, v:1, bt:0, since:3205
|
||||
|
||||
KEY_PRESS, code:83, since:6750
|
||||
KEY_TYPED, code:0, since:6750
|
||||
KEY_RELEASE, code:83, since:6946
|
||||
*/
|
||||
|
||||
static Pattern mouseMovedPattern = Pattern.compile("MOUSE_MOVED, x:("+num+"), y:("+num+"), bt:("+num+"), since:("+num+")");
|
||||
static Pattern mousePressedPattern = Pattern.compile("MOUSE_PRESSED, x:("+num+"), y:("+num+"), bt:("+num+"), since:("+num+")");
|
||||
static Pattern mouseDraggedPattern = Pattern.compile("MOUSE_DRAGGED, x:("+num+"), y:("+num+"), bt:("+num+"), since:("+num+")");
|
||||
static Pattern mouseReleasePattern = Pattern.compile("MOUSE_RELEASED, x:("+num+"), y:("+num+"), bt:("+num+"), since:("+num+")");
|
||||
static Pattern mouseWheelPattern = Pattern.compile("MOUSE_WHEEL, v:("+num+"), bt:("+num+"), since:("+num+")");
|
||||
|
||||
static Pattern keyPressPattern = Pattern.compile("KEY_PRESS.*, code:("+num+"), since:("+num+")");
|
||||
static Pattern keyTypedPattern = Pattern.compile("KEY_TYPED.*, code:("+num+"), since:("+num+")");
|
||||
static Pattern keyReleasePattern = Pattern.compile("KEY_RELEASE.*, code:("+num+"), since:("+num+")");
|
||||
|
||||
static Pattern windowOpenedPattern = Pattern.compile("WINDOW_OPENED.*, since:("+num+")");
|
||||
static Pattern windowClosingPattern = Pattern.compile("WINDOW_CLOSING.*, since:("+num+")");
|
||||
static Pattern windowClosedPattern = Pattern.compile("WINDOW_CLOSED.*, since:("+num+")");
|
||||
|
||||
static Pattern componentResizedPattern = Pattern.compile("COMPONENT_RESIZED, size:java.awt.Dimension[width=("+num+"),height=("+num+")], bounds:java.awt.Rectangle[x=("+num+"),y=("+num+"),width=("+num+"),height=("+num+")] since:("+num+")");
|
||||
//static Pattern componentResizedPattern = Pattern.compile("COMPONENT_RESIZED.*, since:("+num+")");
|
||||
static Pattern componentMovedPattern = Pattern.compile("COMPONENT_MOVED.*, since:("+num+")");
|
||||
|
||||
public IEventLog parse(String event){
|
||||
// MOUSE
|
||||
Matcher mouseMovedMatcher = mouseMovedPattern.matcher(event);
|
||||
if(mouseMovedMatcher.matches())
|
||||
return parseMouseEvent(mouseMovedMatcher, MouseEventType.MOUSE_MOVED);
|
||||
|
||||
Matcher mousePressedMatcher = mousePressedPattern.matcher(event);
|
||||
if(mousePressedMatcher.matches())
|
||||
return parseMouseEvent(mousePressedMatcher, MouseEventType.MOUSE_PRESSED);
|
||||
|
||||
Matcher mouseDraggedMatcher = mouseDraggedPattern.matcher(event);
|
||||
if(mouseDraggedMatcher.matches())
|
||||
return parseMouseEvent(mouseDraggedMatcher, MouseEventType.MOUSE_DRAGGED);
|
||||
|
||||
Matcher mouseReleasedMatcher = mouseReleasePattern.matcher(event);
|
||||
if(mouseReleasedMatcher.matches())
|
||||
return parseMouseEvent(mouseReleasedMatcher, MouseEventType.MOUSE_RELEASED);
|
||||
|
||||
Matcher mouseWheelMatcher = mouseWheelPattern.matcher(event);
|
||||
if(mouseWheelMatcher.matches())
|
||||
return parseMouseWheelEvent(mouseWheelMatcher);
|
||||
|
||||
// KEYBOARD
|
||||
Matcher windowOpenMatcher = windowOpenedPattern.matcher(event);
|
||||
if(windowOpenMatcher.matches())
|
||||
return parseWindowEvent(windowOpenMatcher, WindowEventType.WINDOW_OPENED);
|
||||
|
||||
Matcher windowClosingMatcher = windowClosingPattern.matcher(event);
|
||||
if(windowClosingMatcher.matches())
|
||||
return parseWindowEvent(windowClosingMatcher, WindowEventType.WINDOW_CLOSING);
|
||||
|
||||
Matcher windowClosedMatcher = windowClosedPattern.matcher(event);
|
||||
if(windowClosedMatcher.matches())
|
||||
return parseWindowEvent(windowClosedMatcher, WindowEventType.WINDOW_CLOSED);
|
||||
|
||||
// WINDOW
|
||||
Matcher keyPressMatcher = keyPressPattern.matcher(event);
|
||||
if(keyPressMatcher.matches())
|
||||
return parseKeyEvent(keyPressMatcher, KeyEventType.KEY_PRESS);
|
||||
|
||||
Matcher keyTypedMatcher = keyTypedPattern.matcher(event);
|
||||
if(keyTypedMatcher.matches())
|
||||
return parseKeyEvent(keyTypedMatcher, KeyEventType.KEY_TYPED);
|
||||
|
||||
Matcher keyReleaseMatcher = keyReleasePattern.matcher(event);
|
||||
if(keyReleaseMatcher.matches())
|
||||
return parseKeyEvent(keyReleaseMatcher, KeyEventType.KEY_RELEASE);
|
||||
|
||||
// COMPONENT
|
||||
Matcher componentResizedMatcher = componentResizedPattern.matcher(event);
|
||||
if(componentResizedMatcher.matches())
|
||||
return parseComponentEvent(componentResizedMatcher, ComponentEventType.COMPONENT_RESIZED);
|
||||
|
||||
Matcher componentMovedMatcher = componentMovedPattern.matcher(event);
|
||||
if(componentMovedMatcher.matches())
|
||||
return parseComponentEvent(componentMovedMatcher, ComponentEventType.COMPONENT_MOVED);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected IMouseEventLog parseMouseEvent(Matcher matcher, MouseEventType type) {
|
||||
int x = Integer.parseInt(matcher.group(1));
|
||||
int y = Integer.parseInt(matcher.group(2));
|
||||
int b = Integer.parseInt(matcher.group(3));
|
||||
int s = Integer.parseInt(matcher.group(4));
|
||||
return new MouseEventLog(type, x, y, b, s);
|
||||
}
|
||||
|
||||
protected IMouseEventLog parseMouseWheelEvent(Matcher matcher) {
|
||||
int v = Integer.parseInt(matcher.group(1));
|
||||
int b = Integer.parseInt(matcher.group(2));
|
||||
int s = Integer.parseInt(matcher.group(3));
|
||||
return new MouseEventLog(MouseEventType.MOUSE_WHEEL, v, b, s);
|
||||
}
|
||||
|
||||
protected IKeyEventLog parseKeyEvent(Matcher matcher, KeyEventType type) {
|
||||
int c = Integer.parseInt(matcher.group(1));
|
||||
int s = Integer.parseInt(matcher.group(2));
|
||||
return new KeyEventLog(type, c, s);
|
||||
}
|
||||
|
||||
protected IWindowEventLog parseWindowEvent(Matcher matcher, WindowEventType type) {
|
||||
int s = Integer.parseInt(matcher.group(1));
|
||||
return new WindowEventLog(type, s);
|
||||
}
|
||||
|
||||
protected IComponentEventLog parseComponentEvent(Matcher matcher, ComponentEventType type) {
|
||||
int w = Integer.parseInt(matcher.group(1));
|
||||
int h = Integer.parseInt(matcher.group(2));
|
||||
int rx = Integer.parseInt(matcher.group(3));
|
||||
int ry = Integer.parseInt(matcher.group(4));
|
||||
int rw = Integer.parseInt(matcher.group(5));
|
||||
int rh = Integer.parseInt(matcher.group(6));
|
||||
int s = Integer.parseInt(matcher.group(7));
|
||||
|
||||
return new ComponentEventLog(type, new Dimension(w,h), new Rectangle(rx,ry,rw,rh), s);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Rectangle;
|
||||
|
||||
public interface IComponentEventLog extends IEventLog{
|
||||
public ComponentEventType getType();
|
||||
public Object getValue();
|
||||
public Dimension getSize();
|
||||
public Rectangle getBounds();
|
||||
|
||||
public enum ComponentEventType {
|
||||
COMPONENT_HIDDEN,
|
||||
COMPONENT_RESIZED,
|
||||
COMPONENT_SHOWN,
|
||||
COMPONENT_MOVED,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
public interface IEventLog {
|
||||
public long since();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
public interface IKeyEventLog extends IEventLog{
|
||||
public KeyEventType getType();
|
||||
public int getKeyCode();
|
||||
|
||||
public enum KeyEventType{
|
||||
KEY_PRESS,
|
||||
KEY_RELEASE,
|
||||
KEY_TYPED
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
import org.jzy3d.maths.IntegerCoord2d;
|
||||
|
||||
public interface IMouseEventLog extends IEventLog{
|
||||
public MouseEventType getType();
|
||||
public IntegerCoord2d getCoord();
|
||||
public int getValue();
|
||||
|
||||
public int getButton();
|
||||
public int getClicks();
|
||||
|
||||
public enum MouseEventType{
|
||||
MOUSE_CLICKED,
|
||||
MOUSE_PRESSED,
|
||||
MOUSE_RELEASED,
|
||||
MOUSE_MOVED,
|
||||
MOUSE_DRAGGED,
|
||||
MOUSE_WHEEL
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
public interface IWindowEventLog extends IEventLog{
|
||||
public WindowEventType getType();
|
||||
public Object getValue();
|
||||
|
||||
public enum WindowEventType{
|
||||
WINDOW_OPENED,
|
||||
WINDOW_CLOSING,
|
||||
WINDOW_CLOSED,
|
||||
WINDOW_MOVED,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
public class KeyEventLog extends AbstractEventLog implements IKeyEventLog{
|
||||
protected int keyCode;
|
||||
protected KeyEventType type;
|
||||
|
||||
public KeyEventLog(KeyEventType type, int keyCode, long since) {
|
||||
this.keyCode = keyCode;
|
||||
this.type = type;
|
||||
this.since = since;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeyEventType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getKeyCode() {
|
||||
return keyCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return type + ", code:" + keyCode + ", since:" + since;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
|
||||
import org.jzy3d.maths.IntegerCoord2d;
|
||||
|
||||
public class MouseEventLog extends AbstractEventLog implements IMouseEventLog{
|
||||
public MouseEventLog(MouseEventType type, int x, int y, int button, long since){
|
||||
this.type = type;
|
||||
this.button = button;
|
||||
this.since = since;
|
||||
this.coord = new IntegerCoord2d(x, y);
|
||||
}
|
||||
|
||||
public MouseEventLog(MouseEventType type, int value, int button, long since){
|
||||
this.type = type;
|
||||
this.button = button;
|
||||
this.value = value;
|
||||
this.since = since;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntegerCoord2d getCoord() {
|
||||
return coord;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getButton() {
|
||||
return button;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClicks() {
|
||||
return clicks;
|
||||
}
|
||||
@Override
|
||||
public MouseEventType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
if(coord!=null)
|
||||
return type + ", x:" + coord.x + ", y:" + coord.y + ", bt:" + button + ", since:" + since;
|
||||
else
|
||||
return type + ", v:" + value + ", bt:" + button + ", since:" + since;
|
||||
}
|
||||
|
||||
protected MouseEventType type;
|
||||
protected IntegerCoord2d coord;
|
||||
protected int value;
|
||||
|
||||
protected int button = InputEvent.BUTTON1_MASK;
|
||||
protected int clicks;
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package org.jzy3d.junit.replay.events;
|
||||
|
||||
public class WindowEventLog extends AbstractEventLog implements IWindowEventLog{
|
||||
public WindowEventLog(WindowEventType type, long since) {
|
||||
this.since = since;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public WindowEventLog(WindowEventType type, Object value, long since) {
|
||||
this.since = since;
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowEventType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
if(value!=null)
|
||||
return type + ", v:" + value + ", since:" + since;
|
||||
else
|
||||
return type + ", since:" + since;
|
||||
}
|
||||
|
||||
protected WindowEventType type;
|
||||
protected Object value;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,53 @@
|
|||
package org.jzy3d.mocks.jzy3d;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jzy3d.colors.Color;
|
||||
import org.jzy3d.maths.BoundingBox3d;
|
||||
import org.jzy3d.maths.Coord2d;
|
||||
import org.jzy3d.maths.Coord3d;
|
||||
import org.jzy3d.plot3d.rendering.view.Camera;
|
||||
import org.jzy3d.plot3d.text.align.Halign;
|
||||
import org.jzy3d.plot3d.text.align.Valign;
|
||||
import org.jzy3d.plot3d.text.renderers.TextBitmapRenderer;
|
||||
|
||||
import com.jogamp.opengl.GL;
|
||||
import com.jogamp.opengl.glu.GLU;
|
||||
|
||||
public class MockTextBitmapRenderer extends TextBitmapRenderer{
|
||||
List<Map<String,Object>> callArguments = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public BoundingBox3d drawText(GL gl, GLU glu, Camera cam, String text, Coord3d position, Halign halign, Valign valign, Color color, Coord2d screenOffset, Coord3d sceneOffset) {
|
||||
Map<String,Object> args = new HashMap<String,Object>();
|
||||
args.put("text", text);
|
||||
args.put("position", position);
|
||||
args.put("halign", halign);
|
||||
args.put("valign", valign);
|
||||
args.put("color", color);
|
||||
args.put("screenOffset", screenOffset);
|
||||
args.put("sceneOffset", sceneOffset);
|
||||
|
||||
|
||||
callArguments.add(args);
|
||||
|
||||
return new BoundingBox3d();
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getCallArguments() {
|
||||
return callArguments;
|
||||
}
|
||||
|
||||
public Map<String, Object> getCallArguments_whereTextEquals(String text) {
|
||||
for(Map<String, Object> args: callArguments){
|
||||
if(text.equals(args.get("text"))){
|
||||
return args;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package org.jzy3d.junit;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.jzy3d.junit.ChartTester;
|
||||
import org.jzy3d.junit.ChartTestFailed;
|
||||
|
||||
/**
|
||||
* Testing the test tool!
|
||||
*
|
||||
* @author martin
|
||||
*
|
||||
*/
|
||||
public class TestChartTester {
|
||||
ChartTester test;
|
||||
|
||||
@Before
|
||||
public void before(){
|
||||
test = new ChartTester();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareImageWithHerselfSucceed() throws IOException{
|
||||
BufferedImage bi = test.loadBufferedImage("data/test-test/testimage.png");
|
||||
try {
|
||||
test.compare(bi, bi);
|
||||
} catch (ChartTestFailed e) {
|
||||
Assert.fail(e.getMessage());
|
||||
}
|
||||
Assert.assertTrue(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareImageWithAnotherFails() throws IOException{
|
||||
BufferedImage bi1 = test.loadBufferedImage("data/test-test/testimage.png");
|
||||
BufferedImage bi2 = test.loadBufferedImage("data/test-test/testimage2.png");
|
||||
try {
|
||||
test.compare(bi1, bi2);
|
||||
} catch (ChartTestFailed e) {
|
||||
Assert.assertTrue(e.getMessage(), true);
|
||||
return;
|
||||
}
|
||||
Assert.fail("two different image should throw an exception");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue