/* * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8188083 * @summary The test checks whether applying image filters using * FilteredImageSource results in a NullPointerException. * @run main FilteredImageSourceTest */ import java.awt.Graphics; import java.awt.Image; import java.awt.image.ColorModel; import java.awt.image.FilteredImageSource; import java.awt.image.ImageConsumer; import java.awt.image.ImageFilter; import java.awt.image.ImageObserver; import java.awt.image.ImageProducer; import java.util.Hashtable; /* * An empty image consumer that will be added to the list of consumers * interested in image data for the filtered image. */ class EmptyImageConsumer implements ImageConsumer { @Override public void setDimensions(int width, int height) { } @Override public void setProperties(Hashtable props) { } @Override public void setColorModel(ColorModel colorModel) { } @Override public void setHints(int hintFlags) { } @Override public void setPixels(int x, int y, int width, int height, ColorModel colorModel, byte[] pixels, int offset, int scanSize) { } @Override public void setPixels(int x, int y, int width, int height, ColorModel colorModel, int[] pixels, int offset, int scanSize) { } @Override public void imageComplete(int i) { } } /* * An empty image producer whose sole purpose is to provide stub methods * that will be invoked while preparing filtered image. */ class EmptyImageProducer implements ImageProducer { @Override public void addConsumer(ImageConsumer imageConsumer) { } @Override public boolean isConsumer(ImageConsumer imageConsumer) { return false; } @Override public void removeConsumer(ImageConsumer imageConsumer) { } @Override public void startProduction(ImageConsumer imageConsumer) { } @Override public void requestTopDownLeftRightResend(ImageConsumer imageConsumer) { } } /* * Typically, an Image object will contain an ImageProducer that prepares * image data. FilteredImageSource will be set as image producer for images * that require image filter applied to image data. */ class EmptyFilteredImage extends Image { ImageFilter filter = null; ImageProducer producer = null; public EmptyFilteredImage(ImageProducer imgSource) { filter = new ImageFilter(); producer = new FilteredImageSource(imgSource, filter); } @Override public int getWidth(ImageObserver observer) { return 100; } @Override public int getHeight(ImageObserver observer) { return 100; } @Override public ImageProducer getSource() { return producer; } @Override public Graphics getGraphics() { throw new UnsupportedOperationException(); } @Override public Object getProperty(String name, ImageObserver observer) { return null; } } public final class FilteredImageSourceTest { // Minimum test duration in ms private static final int TEST_MIN_DURATION = 5000; /* * A throwable object that will hold any exception generated while * executing methods on FilteredImageSource. The test passes if the * methods execute without any exception */ private static volatile Throwable fail = null; public static void main(final String[] args) throws InterruptedException { final ImageConsumer ic = new EmptyImageConsumer(); final ImageProducer ip = new EmptyImageProducer(); final Image image = new EmptyFilteredImage(ip); /* * Simulate the framework's operations on FilteredImageSource by * invoking the concerned methods in multiple threads and observe * whether exceptions are generated. */ Thread t1 = new Thread(() -> { try { while (true) { image.getSource().addConsumer(ic); } } catch (Throwable t) { fail = t; } }); t1.setDaemon(true); Thread t2 = new Thread(() -> { try { while (true) { image.getSource().removeConsumer(ic); } } catch (Throwable t) { fail = t; } }); t2.setDaemon(true); Thread t3 = new Thread(() -> { try { while (true) { image.getSource().startProduction(ic); } } catch (Throwable t) { fail = t; } }); t3.setDaemon(true); // Start the threads t1.start(); t2.start(); t3.start(); // Wait on one of the threads for a specific duration. t1.join(TEST_MIN_DURATION); if (fail != null) { throw new RuntimeException("Test failed with exception: ", fail); } } }