SNAP Temporal Percentile Operator test case failed

Unit test org.esa.snap.statistics.percentile.interpolated.MeanOpImageTest. testThatOperatorExceptionOccursWhenNoFloatingPointImagesAreProvided failed with the following stacktrace:

Expected: an instance of org.esa.snap.core.gpf.OperatorException
     but: <java.lang.NullPointerException> is a java.lang.NullPointerException
Stacktrace was: java.lang.NullPointerException
	at javax.media.jai.PlanarImage.copyData(PlanarImage.java:2344)
	at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2525)
	at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2546)
	at org.esa.snap.statistics.percentile.interpolated.MeanOpImageTest.testThatOperatorExceptionOccursWhenNoFloatingPointImagesAreProvided(MeanOpImageTest.java:131)
...

It appears that OperatorException was thrown because in surefire report <system-err> shows:

org.geotools.util.logging.LoggingImagingListener: Problem occurs when computing a tile by the owner.
org.esa.snap.core.gpf.OperatorException: Unable to compute raster for non floating number data type
	at org.esa.snap.statistics.percentile.interpolated.MeanOpImage.computeRect(MeanOpImage.java:37)
	at javax.media.jai.PointOpImage.computeTile(PointOpImage.java:914)
	at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
	at javax.media.jai.OpImage.getTile(OpImage.java:1129)
	at javax.media.jai.PlanarImage.copyData(PlanarImage.java:2343)
	at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2525)
	at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2546)
	at org.esa.snap.statistics.percentile.interpolated.MeanOpImageTest.testThatOperatorExceptionOccursWhenNoFloatingPointImagesAreProvided(MeanOpImageTest.java:131)
...

Any ideas NullPointerException was caught instead of OperatorException for exception.expect(OperatorException.class)?

The OperatorException is thrown here:

For me on Windows the test works also on our build platform (Linux) it works. Maybe Mac is again a bit different here. I’ll test it in the coming days on Mac

Actually throwing OperatorException is not correct in the MeanOpImage. Because it is not a GPF operator. It would be better to throw UnsupportedOperationException similar. I’ll check if I can change this easily.

I also had to add the following dependency in snap-desktop/snap-ui/pom.xml in order to successfully complete the snap-desktop build:

<dependency>
    <groupId>org.esa.snap</groupId>
    <artifactId>snap-gpf</artifactId>
</dependency>

Without that dependency, maven gives the following error:

Project uses classes from transitive module org.esa.snap:snap-gpf:jar:7.0.0-SNAPSHOT which will not be accessible at runtime.

I just tried out your new code which is throwing UnsupportedOperationException. The exception is indeed thrown as can be seen in the surefire-report:

INFO: org.geotools.util.logging.LoggingImagingListener: Problem occurs when computing a tile by the owner.
java.lang.UnsupportedOperationException: Unable to compute raster for non floating number data type
	at org.esa.snap.statistics.percentile.interpolated.MeanOpImage.computeRect(MeanOpImage.java:35)
	at javax.media.jai.PointOpImage.computeTile(PointOpImage.java:914)
	at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
	at javax.media.jai.OpImage.getTile(OpImage.java:1129)
	at javax.media.jai.PlanarImage.copyData(PlanarImage.java:2343)
	at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2525)
	at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2546)
	at org.esa.snap.statistics.percentile.interpolated.MeanOpImageTest.testThatOperatorExceptionOccursWhenNoFloatingPointImagesAreProvided(MeanOpImageTest.java:131)
    ...

However, what is caught in the test case is still NullPointerException as seen here:

Expected: an instance of java.lang.UnsupportedOperationException
     but: <java.lang.NullPointerException> is a java.lang.NullPointerException
Stacktrace was: java.lang.NullPointerException
	at javax.media.jai.PlanarImage.copyData(PlanarImage.java:2344)
	at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2525)
	at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2546)
	at org.esa.snap.statistics.percentile.interpolated.MeanOpImageTest.testThatOperatorExceptionOccursWhenNoFloatingPointImagesAreProvided(MeanOpImageTest.java:131)
    ...

INFO: org.geotools.util.logging.LoggingImagingListener: Problem occurs when computing a tile by the owner.
java.lang.UnsupportedOperationException: Unable to compute raster for non floating number data type
    at org.esa.snap.statistics.percentile.interpolated.MeanOpImage.computeRect(MeanOpImage.java:35)
    at javax.media.jai.PointOpImage.computeTile(PointOpImage.java:914)
    at com.sun.media.jai.util.SunTileScheduler.scheduleTile(SunTileScheduler.java:904)
    at javax.media.jai.OpImage.getTile(OpImage.java:1129)
    at javax.media.jai.PlanarImage.copyData(PlanarImage.java:2343)
    at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2525)

Expected: an instance of java.lang.UnsupportedOperationException
but: <java.lang.NullPointerException> is a java.lang.NullPointerException
Stacktrace was: java.lang.NullPointerException
    at javax.media.jai.PlanarImage.copyData(PlanarImage.java:2344)
    at javax.media.jai.PlanarImage.getAsBufferedImage(PlanarImage.java:2525)

From the above 2 stack traces, it appears that UnsupportedOperationException was indeed thrown within getTile(tx, ty) method.

But for some reason, the code still continued with tile still null.

If I run the unit test on eclipse, it will pass with UnsupportedOperationException but fail if NullPointerException is used.

However, if I run maven clean test from command line, it will fail with UnsupportedOperationException but pass if NullPointerException is used.

This has been resolved by

Just found out that the above behaviour is due to the different ImagingListener used when in eclipse and maven.

When running the test case in eclipse, the ImagingListener class is

com.sun.media.jai.util.ImagingListenerImpl

but in maven command line, the ImagingListener class is

org.geotools.util.logging.LoggingImagingListener

I managed to trace the test case code flow as below:

  1. Raster tile = getTile(tx, ty) at line 2343 above will call tile = scheduler.scheduleTile(this, tileX, tileY) at line 1129 below:
  1. … which will reach line 904 below…
  1. … which will reach line 914 below …
  1. … then reaching line 35 of MeanOpImage which throws UnsupportedOperationException.
  1. The UnsupportedOperationException thrown is handled between 916 and 931 below:
  1. Since UnsupportedOperationException is an instance of RuntimeException, line 921 above handles it through the method sendExceptionToListener below:
  1. As mentioned earlier, the ImagingListener gotten from ImageUtil in line 1644 is different when I ran the test from eclipse and maven.

  2. Tracing the code further to org.geotools.util.logging.Logging, I can see that geotools will replace ImagingListener with LoggingImagingListener in line 119 if the class name contains ImagingListenerImpl. I think this happened when I ran the test case in maven command line which made the test case logged UnsupportedOperationException instead of throwing the exception for the test case to catch.

Any way to set the ImageListener to com.sun.media.jai.util.ImagingListenerImpl when running the case from maven command line so that the test case can pass?

Based on my above finding, I modified testThatOperatorExceptionOccursWhenNoFloatingPointImagesAreProvided method as below in order to pass the test from maven command line:

@Test
public void testThatOperatorExceptionOccursWhenNoFloatingPointImagesAreProvided() {
	// get the ImagingListener currently in use
	ImagingListener originalImagingListener = JAI.getDefaultInstance().getImagingListener();
	// set the ImagingListener to com.sun.media.jai.util.ImagingListenerImpl
	JAI.getDefaultInstance().setImagingListener(ImagingListenerImpl.getInstance());

    final Vector<RenderedImage> sources = new Vector<>();
    sources.add(ConstantDescriptor.create(2f, 2f, new Integer[]{3}, null));
    sources.add(ConstantDescriptor.create(2f, 2f, new Integer[]{2}, null));

    //execution
    final MeanOpImage meanOpImage = new MeanOpImage(sources);
    exception.expect(UnsupportedOperationException.class);
    meanOpImage.getAsBufferedImage();

	// revert the ImagingListener to the one in use
	JAI.getDefaultInstance().setImagingListener(originalImagingListener);
    fail("Should not reach this line");
}

Do you know of a better way?

Also found out that org.geotools.util.logging.LoggingImagingListener logger is set only when org.esa.snap.statistics.percentile.interpolated.UtilsTest_GroupProductsDaily test is run.

This could be the reason why the test passed in eclipse because I only ran the MeanOpImageTest whereas from maven command line I ran all tests.

Thanks for this.
It should be solved now.

The problem is that GeoTools changes the behavior. As soon as it is used or at least its logging the ImagingListener is changed, as you already noticed.

I’ve written a bit more in the MeanOpImageTest: