/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2011, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.swing;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.awt.Color;
import java.awt.image.WritableRaster;
import java.util.concurrent.CancellationException;
import org.geotools.map.MapContent;
import org.geotools.swing.testutils.MockRenderer;
import org.geotools.swing.testutils.WaitingRenderingExecutorListener;
import org.junit.Before;
import org.junit.Test;
/**
* Tests for SingleTaskRenderingExecutor.
*
* @author Michael Bedward
* @since 8.0
*
* @source $URL$
* @version $Id$
*/
public class DefaultRenderingExecutorTest extends RenderingExecutorTestBase {
@Before
public void localSetup() {
super.setup();
}
@Test
public void shutdownExecutor() {
assertFalse(executor.isShutdown());
executor.shutdown();
assertTrue(executor.isShutdown());
}
@Test(expected=IllegalStateException.class)
public void submitAfterShutdown() {
executor.shutdown();
createSubmitObjects();
executor.submit(mapContent, renderer, graphics, listener);
}
@Test
public void setAndGetPollingInterval() {
long poll = executor.getPollingInterval();
executor.setPollingInterval(poll * 2);
assertEquals(poll * 2, executor.getPollingInterval());
}
@Test
public void invalidPollingInterval() {
long poll = executor.getPollingInterval();
// should be ignored
executor.setPollingInterval(-1);
assertEquals(poll, executor.getPollingInterval());
}
/**
* GEOT-5563
*
* Tests that the renderer continue to work on subsequent submits after a single
* submit has failed due to a layer failure.
*
*/
@Test
public void testContinuedOperationAfterLayerFail() {
createSubmitObjects();
//Test requires that a map is _actually_ drawn, so cannot use the MockRenderer - replace it here
class FailableMockRenderer extends MockRenderer {
boolean mockFail;
public FailableMockRenderer(MapContent map) {
super(map);
}
public void setFail(boolean fail) {
this.mockFail = fail;
}
//Just fill the graphics with red ... our test will be looking for this
@Override
protected void pretendToPaint() {
graphics.setColor(Color.red);
graphics.fill(PANE);
//Do the locking/waiting bit
super.pretendToPaint();
//And now fail if we're told to. Note that this fail is _after_ the render
//which simulate the actual behaviour if the map has multiple layers, only
//one of which fails.
if (mockFail) {
listeners.forEach(listener->listener.errorOccurred(new RuntimeException("Simulated layer rendering failure")));
}
}
};
FailableMockRenderer failableRenderer = new FailableMockRenderer(mapContent);
this.renderer = failableRenderer;
renderer.setPaintTime(10);
//Execute with no problems
clearGraphics();
listener.setExpected(WaitingRenderingExecutorListener.Type.STARTED);
listener.setExpected(WaitingRenderingExecutorListener.Type.COMPLETED);
executor.submit(mapContent, renderer, graphics, listener);
int timeoutMillis = 1000;
listener.await(WaitingRenderingExecutorListener.Type.STARTED, timeoutMillis);
listener.await(WaitingRenderingExecutorListener.Type.COMPLETED, timeoutMillis);
assertTrue(listener.eventReceived(WaitingRenderingExecutorListener.Type.STARTED));
assertTrue(listener.eventReceived(WaitingRenderingExecutorListener.Type.COMPLETED));
checkGraphicsWasPainted();
//Now deliberately fail the render
clearGraphics();
listener.setExpected(WaitingRenderingExecutorListener.Type.STARTED);
listener.setExpected(WaitingRenderingExecutorListener.Type.FAILED);
failableRenderer.setFail(true);
executor.submit(mapContent, renderer, graphics, listener);
listener.await(WaitingRenderingExecutorListener.Type.STARTED, timeoutMillis);
listener.await(WaitingRenderingExecutorListener.Type.FAILED, timeoutMillis);
assertTrue(listener.eventReceived(WaitingRenderingExecutorListener.Type.STARTED));
assertTrue(listener.eventReceived(WaitingRenderingExecutorListener.Type.FAILED));
//Actual failed submission still paints as expected
checkGraphicsWasPainted();
//Now remove the failure and submit again
clearGraphics();
listener.setExpected(WaitingRenderingExecutorListener.Type.STARTED);
listener.setExpected(WaitingRenderingExecutorListener.Type.COMPLETED);
failableRenderer.setFail(false);
executor.submit(mapContent, renderer, graphics, listener);
listener.await(WaitingRenderingExecutorListener.Type.STARTED, timeoutMillis);
listener.await(WaitingRenderingExecutorListener.Type.COMPLETED, timeoutMillis);
assertTrue(listener.eventReceived(WaitingRenderingExecutorListener.Type.STARTED));
assertTrue(listener.eventReceived(WaitingRenderingExecutorListener.Type.COMPLETED));
checkGraphicsWasPainted(); //Prior to fix, nothing is drawn
}
private void checkGraphicsWasPainted() {
WritableRaster raster = image.getRaster();
int[] pixel = new int[4];
raster.getPixel(1, 1, pixel);
assertEquals("Pixel at (1,1) was not renderered", 255, pixel[0]);
assertEquals("Pixel at (1,1) was not renderered", 0, pixel[1]);
assertEquals("Pixel at (1,1) was not renderered", 0, pixel[2]);
}
private void clearGraphics() {
graphics.setColor(Color.white);
graphics.fill(PANE);
}
}