/**
  * Test that point features are rendered at the expected image coordinates when the map is
  * rotated. StreamingRenderer
  *
  * @throws Exception
  */
 @Test
 public void testRotatedTransform() throws Exception {
   // If we rotate the world rectangle + 90 degrees around (0,0), we get the screen rectangle
   final Rectangle screen = new Rectangle(0, 0, 100, 50);
   final Envelope world = new Envelope(0, 50, 0, -100);
   final AffineTransform worldToScreen =
       AffineTransform.getRotateInstance(Math.toRadians(90), 0, 0);
   DefaultFeatureCollection fc = new DefaultFeatureCollection();
   fc.add(createPoint(0, 0));
   fc.add(createPoint(world.getMaxX(), world.getMinY()));
   MapContext mapContext = new DefaultMapContext(DefaultGeographicCRS.WGS84);
   mapContext.addLayer((FeatureCollection) fc, createPointStyle());
   BufferedImage image =
       new BufferedImage(screen.width, screen.height, BufferedImage.TYPE_4BYTE_ABGR);
   final StreamingRenderer sr = new StreamingRenderer();
   sr.setContext(mapContext);
   sr.paint(image.createGraphics(), screen, worldToScreen);
   assertTrue("Pixel should be drawn at 0,0 ", image.getRGB(0, 0) != 0);
   assertTrue(
       "Pixel should not be drawn in image centre ",
       image.getRGB(screen.width / 2, screen.height / 2) == 0);
   assertTrue(
       "Pixel should be drawn at image max corner ",
       image.getRGB(screen.width - 1, screen.height - 1) != 0);
 }
  @Test
  public void testRenderStuff() throws Exception {
    // build map context
    MapContext mapContext = new DefaultMapContext(DefaultGeographicCRS.WGS84);
    mapContext.addLayer(createLineCollection(), createLineStyle());

    // build projected envelope to work with (small one around the area of
    // validity of utm zone 1, which being a Gauss projection is a vertical
    // slice parallel to the central meridian, -177°)
    ReferencedEnvelope reWgs =
        new ReferencedEnvelope(new Envelope(-180, -170, 20, 40), DefaultGeographicCRS.WGS84);
    CoordinateReferenceSystem utm1N = CRS.decode("EPSG:32601");
    System.out.println(CRS.getGeographicBoundingBox(utm1N));
    ReferencedEnvelope reUtm = reWgs.transform(utm1N, true);

    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR);

    // setup the renderer and listen for errors
    StreamingRenderer sr = new StreamingRenderer();
    sr.setContext(mapContext);
    sr.addRenderListener(
        new RenderListener() {
          public void featureRenderer(SimpleFeature feature) {
            features++;
          }

          public void errorOccurred(Exception e) {
            errors++;
          }
        });
    errors = 0;
    features = 0;
    sr.paint((Graphics2D) image.getGraphics(), new Rectangle(200, 200), reUtm);

    // we should get two errors since there are two features that cannot be
    // projected but the renderer itself should not throw exceptions
    assertTrue(features > 0);
  }
  @Test
  public void testInfiniteLoopAvoidance() throws Exception {
    final Exception sentinel =
        new RuntimeException("This is the one that should be thrown in hasNext()");

    // setup the mock necessary to have the renderer hit into the exception in hasNext()
    SimpleFeatureIterator it2 = createNiceMock(SimpleFeatureIterator.class);
    expect(it2.hasNext()).andThrow(sentinel).anyTimes();
    replay(it2);

    SimpleFeatureCollection fc = createNiceMock(SimpleFeatureCollection.class);
    expect(fc.features()).andReturn(it2);
    expect(fc.size()).andReturn(200);
    expect(fc.getSchema()).andReturn(testFeatureType).anyTimes();
    replay(fc);

    SimpleFeatureSource fs = createNiceMock(SimpleFeatureSource.class);
    expect(fs.getFeatures((Query) anyObject())).andReturn(fc);
    expect(fs.getSchema()).andReturn(testFeatureType).anyTimes();
    expect(fs.getSupportedHints()).andReturn(new HashSet()).anyTimes();
    replay(fs);

    // build map context
    MapContext mapContext = new DefaultMapContext(DefaultGeographicCRS.WGS84);
    mapContext.addLayer(fs, createLineStyle());

    // setup the renderer and listen for errors
    final StreamingRenderer sr = new StreamingRenderer();
    sr.setContext(mapContext);
    sr.addRenderListener(
        new RenderListener() {
          public void featureRenderer(SimpleFeature feature) {
            features++;
          }

          public void errorOccurred(Exception e) {
            errors++;

            if (errors > 2) {
              // we dont' want to block the loop in case of regression on this bug
              sr.stopRendering();
            }

            // but we want to make sure we're getting
            Throwable t = e;
            while (t != sentinel && t.getCause() != null) t = t.getCause();
            assertSame(sentinel, t);
          }
        });
    errors = 0;
    features = 0;
    BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_4BYTE_ABGR);
    ReferencedEnvelope reWgs =
        new ReferencedEnvelope(new Envelope(-180, -170, 20, 40), DefaultGeographicCRS.WGS84);
    sr.paint((Graphics2D) image.getGraphics(), new Rectangle(200, 200), reWgs);

    // we should get two errors since there are two features that cannot be
    // projected but the renderer itself should not throw exceptions
    assertEquals(0, features);
    assertEquals(1, errors);
  }