7107905: ColorModel subclasses are missing hashCode() or equals() or both methods
authorjdv
Mon, 13 Feb 2017 12:13:20 +0530
changeset 43827 a02bc4e52007
parent 43826 ff4d8d468f68
child 43828 0573d83832f2
7107905: ColorModel subclasses are missing hashCode() or equals() or both methods Reviewed-by: prr, flar Contributed-by: jayathirth.d.v@oracle.com
jdk/src/java.desktop/share/classes/java/awt/image/ColorModel.java
jdk/src/java.desktop/share/classes/java/awt/image/ComponentColorModel.java
jdk/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java
jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java
jdk/test/java/awt/image/ColorModel/EqualsTest.java
jdk/test/java/awt/image/ComponentColorModel/ComponentColorModelEqualsTest.java
jdk/test/java/awt/image/IndexColorModel/IndexColorModelEqualsTest.java
jdk/test/java/awt/image/PackedColorModel/PackedColorModelEqualsTest.java
--- a/jdk/src/java.desktop/share/classes/java/awt/image/ColorModel.java	Fri Feb 10 10:20:22 2017 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/ColorModel.java	Mon Feb 13 12:13:20 2017 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, 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
@@ -31,10 +31,10 @@
 import sun.java2d.cmm.CMSManager;
 import sun.java2d.cmm.ColorTransform;
 import sun.java2d.cmm.PCMM;
-import java.awt.Toolkit;
 import java.util.Collections;
 import java.util.Map;
 import java.util.WeakHashMap;
+import java.util.Arrays;
 
 /**
  * The {@code ColorModel} abstract class encapsulates the
@@ -362,7 +362,14 @@
             this.transparency         = transparency;
         }
 
-        nBits = bits.clone();
+        /*
+         * We need significant bits value only for the length
+         * of number of components, so we truncate remaining part.
+         * It also helps in hashCode calculation since bits[] can contain
+         * different values after the length of number of components between
+         * two ColorModels.
+         */
+        nBits = Arrays.copyOf(bits, numComponents);
         this.pixel_bits = pixel_bits;
         if (pixel_bits <= 0) {
             throw new IllegalArgumentException("Number of pixel bits must "+
@@ -1441,69 +1448,53 @@
     }
 
     /**
-     * Tests if the specified {@code Object} is an instance of
-     * {@code ColorModel} and if it equals this
-     * {@code ColorModel}.
-     * @param obj the {@code Object} to test for equality
-     * @return {@code true} if the specified {@code Object}
-     * is an instance of {@code ColorModel} and equals this
-     * {@code ColorModel}; {@code false} otherwise.
+     * This method simply delegates to the default implementation in {@code Object}
+     * which is identical to an {@code ==} test since this class cannot enforce the
+     * issues of a proper equality test among multiple independent subclass
+     * branches.
+     * Subclasses are encouraged to override this method and provide equality
+     * testing for their own properties in addition to equality tests for the
+     * following common base properties of {@code ColorModel}:
+     * <ul>
+     * <li>Support for alpha component.</li>
+     * <li>Is alpha premultiplied.</li>
+     * <li>Number of bits per pixel.</li>
+     * <li>Type of transparency like Opaque, Bitmask or Translucent.</li>
+     * <li>Number of components in a pixel.</li>
+     * <li>{@code ColorSpace} type.</li>
+     * <li>Type of the array used to represent pixel values.</li>
+     * <li>Number of significant bits per color and alpha component.</li>
+     * </ul>
+     * @param obj the reference object with which to compare.
+     * @return {@code true} if this object is the same as the obj
+     *         argument; {@code false} otherwise.
      */
+    @Override
     public boolean equals(Object obj) {
-        if (!(obj instanceof ColorModel)) {
-            return false;
-        }
-        ColorModel cm = (ColorModel) obj;
-
-        if (this == cm) {
-            return true;
-        }
-        if (supportsAlpha != cm.hasAlpha() ||
-            isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
-            pixel_bits != cm.getPixelSize() ||
-            transparency != cm.getTransparency() ||
-            numComponents != cm.getNumComponents())
-        {
-            return false;
-        }
-
-        int[] nb = cm.getComponentSize();
-
-        if ((nBits != null) && (nb != null)) {
-            for (int i = 0; i < numComponents; i++) {
-                if (nBits[i] != nb[i]) {
-                    return false;
-                }
-            }
-        } else {
-            return ((nBits == null) && (nb == null));
-        }
-
-        return true;
+        return super.equals(obj);
     }
 
     /**
-     * Returns the hash code for this ColorModel.
-     *
-     * @return    a hash code for this ColorModel.
+     * This method simply delegates to the default implementation in {@code Object}
+     * which returns the system ID for the class.
+     * Subclasses are encouraged to override this method and provide a hash
+     * for their own properties in addition to hashing the values of the
+     * following common base properties of {@code ColorModel}:
+     * <ul>
+     * <li>Support for alpha component.</li>
+     * <li>Is alpha premultiplied.</li>
+     * <li>Number of bits per pixel.</li>
+     * <li>Type of transparency like Opaque, Bitmask or Translucent.</li>
+     * <li>Number of components in a pixel.</li>
+     * <li>{@code ColorSpace} type.</li>
+     * <li>Type of the array used to represent pixel values.</li>
+     * <li>Number of significant bits per color and alpha component.</li>
+     * </ul>
+     * @return a hash code value for this object.
      */
+    @Override
     public int hashCode() {
-
-        int result = 0;
-
-        result = (supportsAlpha ? 2 : 3) +
-                 (isAlphaPremultiplied ? 4 : 5) +
-                 pixel_bits * 6 +
-                 transparency * 7 +
-                 numComponents * 8;
-
-        if (nBits != null) {
-            for (int i = 0; i < numComponents; i++) {
-                result = result + nBits[i] * (i + 9);
-            }
-        }
-
-        return result;
+        return super.hashCode();
     }
 
     /**
@@ -1961,4 +1952,4 @@
         return lg16Toog16LUT;
     }
 
-}
+}
\ No newline at end of file
--- a/jdk/src/java.desktop/share/classes/java/awt/image/ComponentColorModel.java	Fri Feb 10 10:20:22 2017 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/ComponentColorModel.java	Mon Feb 13 12:13:20 2017 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -27,6 +27,7 @@
 
 import java.awt.color.ColorSpace;
 import java.awt.color.ICC_ColorSpace;
+import java.util.Arrays;
 
 /**
  * A {@code ColorModel} class that works with pixel values that
@@ -200,6 +201,7 @@
     private float[] diffMinMax;
     private float[] compOffset;
     private float[] compScale;
+    private volatile int hashCode;
 
     /**
      * Constructs a {@code ComponentColorModel} from the specified
@@ -2927,22 +2929,59 @@
     }
 
     /**
-     * Compares this color model with another for equality.
-     *
-     * @param obj The object to compare with this color model.
-     * @return {@code true} if the color model objects are equal,
-     * {@code false} if they are not.
+     * Tests if the specified {@code Object} is an instance
+     * of {@code ComponentColorModel} and equals this
+     * {@code ComponentColorModel}.
+     * @param obj the {@code Object} to test for equality
+     * @return {@code true} if the specified {@code Object}
+     * is an instance of {@code ComponentColorModel} and equals this
+     * {@code ComponentColorModel}; {@code false} otherwise.
      */
+    @Override
     public boolean equals(Object obj) {
-        if (!super.equals(obj)) {
+        if (!(obj instanceof ComponentColorModel)) {
             return false;
         }
 
-        if (obj.getClass() !=  getClass()) {
+        ComponentColorModel cm = (ComponentColorModel) obj;
+        if (supportsAlpha != cm.hasAlpha() ||
+            isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
+            pixel_bits != cm.getPixelSize() ||
+            transparency != cm.getTransparency() ||
+            numComponents != cm.getNumComponents() ||
+            (!(colorSpace.equals(cm.colorSpace))) ||
+            transferType != cm.transferType)
+        {
+            return false;
+        }
+
+        if (!(Arrays.equals(nBits, cm.getComponentSize()))) {
             return false;
         }
 
         return true;
     }
 
-}
+    /**
+     * Returns the hash code for this ComponentColorModel.
+     *
+     * @return    a hash code for this ComponentColorModel.
+     */
+    @Override
+    public int hashCode() {
+        int result = hashCode;
+        if (result == 0) {
+            result = 7;
+            result = 89 * result + this.pixel_bits;
+            result = 89 * result + Arrays.hashCode(this.nBits);
+            result = 89 * result + this.transparency;
+            result = 89 * result + (this.supportsAlpha ? 1 : 0);
+            result = 89 * result + (this.isAlphaPremultiplied ? 1 : 0);
+            result = 89 * result + this.numComponents;
+            result = 89 * result + this.colorSpace.hashCode();
+            result = 89 * result + this.transferType;
+            hashCode = result;
+        }
+        return result;
+    }
+}
\ No newline at end of file
--- a/jdk/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java	Fri Feb 10 10:20:22 2017 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/IndexColorModel.java	Mon Feb 13 12:13:20 2017 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2017, 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
@@ -28,6 +28,7 @@
 import java.awt.Transparency;
 import java.awt.color.ColorSpace;
 import java.math.BigInteger;
+import java.util.Arrays;
 
 /**
  * The {@code IndexColorModel} class is a {@code ColorModel}
@@ -129,6 +130,7 @@
     private int transparent_index = -1;
     private boolean allgrayopaque;
     private BigInteger validBits;
+    private volatile int hashCode;
 
     private sun.awt.image.BufImgSurfaceData.ICMColorData colorData = null;
 
@@ -1532,4 +1534,100 @@
                          + " isAlphaPre = "+isAlphaPremultiplied
                          );
     }
-}
+
+    /**
+     * Tests if the specified {@code Object} is an
+     * instance of {@code IndexColorModel}
+     * and if it equals this {@code IndexColorModel}
+     * @param obj the {@code Object} to test for equality
+     * @return {@code true} if the specified {@code Object}
+     * equals this {@code IndexColorModel}; {@code false} otherwise.
+     */
+    @Override
+    public boolean equals(Object obj) {
+
+        if (!(obj instanceof IndexColorModel)) {
+            return false;
+        }
+
+        IndexColorModel cm = (IndexColorModel) obj;
+        if (supportsAlpha != cm.hasAlpha() ||
+            isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
+            pixel_bits != cm.getPixelSize() ||
+            transparency != cm.getTransparency() ||
+            numComponents != cm.getNumComponents() ||
+            (!(colorSpace.equals(cm.colorSpace))) ||
+            transferType != cm.transferType ||
+            map_size != cm.map_size ||
+            transparent_index != cm.transparent_index)
+        {
+            return false;
+        }
+
+        if (!(Arrays.equals(nBits, cm.getComponentSize()))) {
+            return false;
+        }
+
+        // verify whether we have to check equality of all bits in validBits
+        boolean testValidBits;
+        if (validBits == cm.validBits) {
+            testValidBits = false;
+        } else if (validBits == null || cm.validBits == null) {
+            return false;
+        } else if (validBits.equals(cm.validBits)) {
+            testValidBits = false;
+        } else {
+            testValidBits = true;
+        }
+
+        if (testValidBits) {
+            for (int i = 0; i < map_size; i++) {
+                if (rgb[i] != cm.rgb[i] ||
+                    validBits.testBit(i) != cm.validBits.testBit(i))
+                {
+                    return false;
+                }
+            }
+        } else {
+            for (int i = 0; i < map_size; i++) {
+                if (rgb[i] != cm.rgb[i]) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Returns the hash code for IndexColorModel.
+     *
+     * @return    a hash code for IndexColorModel
+     */
+    @Override
+    public int hashCode() {
+        int result = hashCode;
+        if (result == 0) {
+            /*
+             * We are intentionally not calculating hashCode for validBits,
+             * because it is only used for 8-bit indexed screens and they
+             * are very rare. It is very unlikely for 2 IndexColorModels
+             * to have different valiBits and have same value for all
+             * other properties.
+             */
+            result = 7;
+            result = 89 * result + this.pixel_bits;
+            result = 89 * result + Arrays.hashCode(this.nBits);
+            result = 89 * result + this.transparency;
+            result = 89 * result + (this.supportsAlpha ? 1 : 0);
+            result = 89 * result + (this.isAlphaPremultiplied ? 1 : 0);
+            result = 89 * result + this.numComponents;
+            result = 89 * result + this.colorSpace.hashCode();
+            result = 89 * result + this.transferType;
+            result = 89 * result + Arrays.hashCode(this.rgb);
+            result = 89 * result + this.map_size;
+            result = 89 * result + this.transparent_index;
+            hashCode = result;
+        }
+        return result;
+    }
+}
\ No newline at end of file
--- a/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java	Fri Feb 10 10:20:22 2017 -0800
+++ b/jdk/src/java.desktop/share/classes/java/awt/image/PackedColorModel.java	Mon Feb 13 12:13:20 2017 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, 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
@@ -27,6 +27,7 @@
 
 import java.awt.Transparency;
 import java.awt.color.ColorSpace;
+import java.util.Arrays;
 
 /**
  * The {@code PackedColorModel} class is an abstract
@@ -88,6 +89,7 @@
     int[] maskArray;
     int[] maskOffsets;
     float[] scaleFactors;
+    private volatile int hashCode;
 
     /**
      * Constructs a {@code PackedColorModel} from a color mask array,
@@ -393,25 +395,63 @@
      * is an instance of {@code PackedColorModel} and equals this
      * {@code PackedColorModel}; {@code false} otherwise.
      */
+    @Override
     public boolean equals(Object obj) {
         if (!(obj instanceof PackedColorModel)) {
             return false;
         }
 
-        if (!super.equals(obj)) {
+        PackedColorModel cm = (PackedColorModel) obj;
+
+        if (supportsAlpha != cm.hasAlpha() ||
+            isAlphaPremultiplied != cm.isAlphaPremultiplied() ||
+            pixel_bits != cm.getPixelSize() ||
+            transparency != cm.getTransparency() ||
+            numComponents != cm.getNumComponents() ||
+            (!(colorSpace.equals(cm.colorSpace))) ||
+            transferType != cm.transferType)
+        {
             return false;
         }
 
-        PackedColorModel cm = (PackedColorModel) obj;
         int numC = cm.getNumComponents();
         for(int i=0; i < numC; i++) {
             if (maskArray[i] != cm.getMask(i)) {
                 return false;
             }
         }
+
+        if (!(Arrays.equals(nBits, cm.getComponentSize()))) {
+            return false;
+        }
+
         return true;
     }
 
+    /**
+     * Returns the hash code for this PackedColorModel.
+     *
+     * @return    a hash code for this PackedColorModel.
+     */
+    @Override
+    public int hashCode() {
+        int result = hashCode;
+        if (result == 0) {
+            result = 7;
+            result = 89 * result + this.pixel_bits;
+            result = 89 * result + Arrays.hashCode(this.nBits);
+            result = 89 * result + this.transparency;
+            result = 89 * result + (this.supportsAlpha ? 1 : 0);
+            result = 89 * result + (this.isAlphaPremultiplied ? 1 : 0);
+            result = 89 * result + this.numComponents;
+            result = 89 * result + this.colorSpace.hashCode();
+            result = 89 * result + this.transferType;
+            result = 89 * result + Arrays.hashCode(this.maskArray);
+            hashCode = result;
+        }
+        return result;
+    }
+
     private static final int[] createBitsArray(int[]colorMaskArray,
                                                int alphaMask) {
         int numColors = colorMaskArray.length;
@@ -480,4 +520,4 @@
         return count;
     }
 
-}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/ColorModel/EqualsTest.java	Mon Feb 13 12:13:20 2017 +0530
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2017, 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 4524500 7107905
+ * @run main EqualsTest
+ * @summary Tests whether ColorModel.equals() succeeds using a
+ * user-implemented subclass of ColorModel which calls the ColorModel(int bits)
+ * constructor. The test fails if an exception is thrown when equals()
+ * is called or if equals() returns an incorrect value.
+ */
+
+import java.awt.image.ColorModel;
+
+public class EqualsTest {
+
+    public static void main(String[] args) {
+        SimpleColorModel scm1 = new SimpleColorModel(3);
+        SimpleColorModel scm2 = new SimpleColorModel(3);
+        SimpleColorModel scm3 = new SimpleColorModel(8);
+        ColorModel rgbcm = ColorModel.getRGBdefault();
+
+        try {
+            if (scm1.equals(scm2)) {
+                throw new RuntimeException("Test 1 failed: " +
+                                           "scm1 should not equal scm2");
+            }
+
+            if (scm1.equals(scm3)) {
+                throw new RuntimeException("Test 2 failed: " +
+                                           "scm1 should not equal scm3");
+            }
+
+            if (scm1.equals(rgbcm) || rgbcm.equals(scm1)) {
+                throw new RuntimeException("Test 3 failed: " +
+                                           "scm1 should not equal rgbcm");
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Test failed: " + e);
+        }
+    }
+
+    private static class SimpleColorModel extends ColorModel {
+
+        public SimpleColorModel(int bits) {
+            super(bits);
+        }
+
+        public int getRed(int pixel) {
+            return 0;
+        }
+
+        public int getGreen(int pixel) {
+            return 0;
+        }
+
+        public int getBlue(int pixel) {
+            return 0;
+        }
+
+        public int getAlpha(int pixel) {
+            return 0;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/ComponentColorModel/ComponentColorModelEqualsTest.java	Mon Feb 13 12:13:20 2017 +0530
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017, 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     7107905
+ * @summary Test verifies whether equals() and hashCode() methods in
+ *          ComponentColorModel works properly.
+ * @run     main ComponentColorModelEqualsTest
+ */
+
+import java.awt.Transparency;
+import java.awt.color.ColorSpace;
+import java.awt.image.ComponentColorModel;
+import java.awt.image.DataBuffer;
+
+public class ComponentColorModelEqualsTest {
+
+    private static void verifyEquals(ComponentColorModel m1,
+                                     ComponentColorModel m2) {
+        if (m1.equals(null)) {
+            throw new RuntimeException("equals(null) returns true");
+        }
+        if (!(m1.equals(m2))) {
+            throw new RuntimeException("equals() method is not working"
+                    + " properly");
+        }
+        if (!(m2.equals(m1))) {
+            throw new RuntimeException("equals() method is not working"
+                    + " properly");
+        }
+        if (m1.hashCode() != m2.hashCode()) {
+            throw new RuntimeException("HashCode is not same for same"
+                    + " ComponentColorModels");
+        }
+    }
+
+    private static void testConstructor1() {
+        /*
+         * verify equality with constructor
+         * ComponentColorModel(ColorSpace colorSpace,
+         *                  int[] bits,
+         *                  boolean hasAlpha,
+         *                  boolean isAlphaPremultiplied,
+         *                  int transparency,
+         *                  int transferType)
+         */
+        ComponentColorModel model1 =
+            new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                                    new int[] {8, 8, 8},
+                                    false,
+                                    false,
+                                    Transparency.OPAQUE,
+                                    DataBuffer.TYPE_BYTE);
+        ComponentColorModel model2 =
+            new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                                    new int[] {8, 8, 8},
+                                    false,
+                                    false,
+                                    Transparency.OPAQUE,
+                                    DataBuffer.TYPE_BYTE);
+        verifyEquals(model1, model2);
+    }
+
+    private static void testConstructor2() {
+        /*
+         * verify equality with constructor
+         * ComponentColorModel(ColorSpace colorSpace,
+         *                  boolean hasAlpha,
+         *                  boolean isAlphaPremultiplied,
+         *                  int transparency,
+         *                  int transferType)
+         */
+        ComponentColorModel model1 =
+            new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                                    false,
+                                    false,
+                                    Transparency.OPAQUE,
+                                    DataBuffer.TYPE_BYTE);
+        ComponentColorModel model2 =
+            new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                                    false,
+                                    false,
+                                    Transparency.OPAQUE,
+                                    DataBuffer.TYPE_BYTE);
+        verifyEquals(model1, model2);
+    }
+
+    private static void testSameComponentColorModel() {
+        testConstructor1();
+        testConstructor2();
+    }
+    public static void main(String[] args) {
+        // verify ComponentColorModel equality using different constructors.
+        testSameComponentColorModel();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/IndexColorModel/IndexColorModelEqualsTest.java	Mon Feb 13 12:13:20 2017 +0530
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2017, 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     7107905
+ * @summary Test verifies whether equals() and hashCode() methods in
+ *          IndexColorModel works properly for IndexColorModel unique
+ *          properties.
+ * @run     main IndexColorModelEqualsTest
+ */
+
+import java.awt.image.DataBuffer;
+import java.awt.image.IndexColorModel;
+import java.math.BigInteger;
+
+public class IndexColorModelEqualsTest {
+
+    private static void verifyEquals(IndexColorModel m1,
+                                     IndexColorModel m2) {
+        if (m1.equals(null)) {
+            throw new RuntimeException("equals(null) returns true");
+        }
+        if (!(m1.equals(m2))) {
+            throw new RuntimeException("equals() method is not working"
+                    + " properly");
+        }
+        if (!(m2.equals(m1))) {
+            throw new RuntimeException("equals() method is not working"
+                    + " properly");
+        }
+        if (m1.hashCode() != m2.hashCode()) {
+            throw new RuntimeException("HashCode is not same for same"
+                    + " IndexColorModels");
+        }
+    }
+
+    private static void testColorMapEquality() {
+        // test with different cmap values.
+        IndexColorModel model1 = new IndexColorModel(8, 3, new int[] {1, 2, 3},
+                0, true, -1, DataBuffer.TYPE_BYTE);
+        IndexColorModel model2 = new IndexColorModel(8, 3, new int[] {4, 5, 6},
+                0, true, -1, DataBuffer.TYPE_BYTE);
+        if (model1.equals(model2)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " ColorMap equality improperly");
+        }
+        if (model2.equals(model1)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " ColorMap equality improperly");
+        }
+    }
+
+    private static void testSizeEquality() {
+        // test with different size for cmap.
+        IndexColorModel model1 = new IndexColorModel(8, 4,
+                new int[] {1, 2, 3, 4},
+                0, true, -1, DataBuffer.TYPE_BYTE);
+        IndexColorModel model2 = new IndexColorModel(8, 3,
+                new int[] {1, 2, 3},
+                0, true, -1, DataBuffer.TYPE_BYTE);
+        if (model1.equals(model2)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " Map size equality improperly");
+        }
+        if (model2.equals(model1)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " Map size equality improperly");
+        }
+    }
+
+    private static void testTransparentIndexEquality() {
+        // test with different values for transparent_index.
+        IndexColorModel model1 = new IndexColorModel(8, 3, new int[] {1, 2, 3},
+                0, true, 1, DataBuffer.TYPE_BYTE);
+        IndexColorModel model2 = new IndexColorModel(8, 3, new int[] {1, 2, 3},
+                0, true, 2, DataBuffer.TYPE_BYTE);
+        if (model1.equals(model2)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " TransparentIndex equality improperly");
+        }
+        if (model2.equals(model1)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " TransparentIndex equality improperly");
+        }
+    }
+
+    private static void testValidPixelsEquality() {
+        // test with different valid pixels.
+        /*
+         * In setRGBs() function of IndexColorModel we override
+         * transparent_index value to map to pixel value if alpha is 0x00
+         * so we should have atleast minimum alpha value to verify
+         * equality of validBits thats why we have color value as
+         * 16777216(2 ^ 24).
+         */
+        int color = 16777216;
+        IndexColorModel model1 = new IndexColorModel(8, 3, new int[] {color,
+                color, color}, 0, DataBuffer.TYPE_BYTE, new BigInteger("1"));
+        IndexColorModel model2 = new IndexColorModel(8, 3, new int[] {color,
+                color, color}, 0, DataBuffer.TYPE_BYTE, new BigInteger("2"));
+        if (model1.equals(model2)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " Valid pixels equality improperly");
+        }
+        if (model2.equals(model1)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " Valid pixels equality improperly");
+        }
+    }
+
+    private static void testConstructor1() {
+        /*
+         * verify equality with constructor
+         * IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b)
+         */
+        IndexColorModel model1 = new IndexColorModel(8, 2,
+                new byte[] {1, 2}, new byte[] {1, 2}, new byte[] {1, 2});
+        IndexColorModel model2 = new IndexColorModel(8, 2,
+                new byte[] {1, 2}, new byte[] {1, 2}, new byte[] {1, 2});
+        verifyEquals(model1, model2);
+    }
+
+    private static void testConstructor2() {
+        /*
+         * verify equality with constructor
+         * IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b,
+         * byte[] a)
+         */
+        IndexColorModel model1 = new IndexColorModel(8, 2, new byte[] {1, 2},
+                new byte[] {1, 2}, new byte[] {1, 2}, new byte[] {1, 2});
+        IndexColorModel model2 = new IndexColorModel(8, 2, new byte[] {1, 2},
+                new byte[] {1, 2}, new byte[] {1, 2}, new byte[] {1, 2});
+        verifyEquals(model1, model2);
+    }
+
+    private static void testConstructor3() {
+        /*
+         * verify equality with constructor
+         * IndexColorModel(int bits, int size, byte[] r, byte[] g, byte[] b,
+         * int trans)
+         */
+        IndexColorModel model1 = new IndexColorModel(8, 2, new byte[] {1, 2},
+                new byte[] {1, 2}, new byte[] {1, 2}, 1);
+        IndexColorModel model2 = new IndexColorModel(8, 2, new byte[] {1, 2},
+                new byte[] {1, 2}, new byte[] {1, 2}, 1);
+        verifyEquals(model1, model2);
+    }
+
+    private static void testConstructor4() {
+        /*
+         * verify equality with constructor
+         * IndexColorModel(int bits, int size, byte[] cmap, int start,
+         * boolean hasalpha)
+         */
+        IndexColorModel model1 = new IndexColorModel(8, 1,
+                new byte[] {1, 2, 3, 4}, 0, true);
+        IndexColorModel model2 = new IndexColorModel(8, 1,
+                new byte[] {1, 2, 3, 4}, 0, true);
+        verifyEquals(model1, model2);
+    }
+
+    private static void testConstructor5() {
+        /*
+         * verify equality with constructor
+         * IndexColorModel(int bits, int size, byte[] cmap, int start,
+         * boolean hasalpha, int trans)
+         */
+        IndexColorModel model1 = new IndexColorModel(8, 1,
+                new byte[] {1, 2, 3, 4}, 0, true, 0);
+        IndexColorModel model2 = new IndexColorModel(8, 1,
+                new byte[] {1, 2, 3, 4}, 0, true, 0);
+        verifyEquals(model1, model2);
+    }
+
+    private static void testConstructor6() {
+        /*
+         * verify equality with constructor
+         * IndexColorModel(int bits, int size, int[] cmap, int start,
+         * boolean hasalpha, int trans, int transferType)
+         */
+        IndexColorModel model1 = new IndexColorModel(8, 3, new int[] {1, 2, 3},
+                0, true, -1, DataBuffer.TYPE_BYTE);
+        IndexColorModel model2 = new IndexColorModel(8, 3, new int[] {1, 2, 3},
+                0, true, -1, DataBuffer.TYPE_BYTE);
+        verifyEquals(model1, model2);
+    }
+
+    private static void testConstructor7() {
+        /*
+         * verify equality with constructor
+         * IndexColorModel(int bits, int size, int[] cmap, int start,
+         * int transferType, BigInteger validBits)
+         */
+        /*
+         * In setRGBs() function of IndexColorModel we override
+         * transparent_index value to map to pixel value if alpha is 0x00
+         * so we should have atleast minimum alpha value to keep
+         * both model1 and model2 same.
+         */
+        int color = 16777216;
+        IndexColorModel model1 = new IndexColorModel(8, 3, new int[] {color,
+                color, color}, 0, DataBuffer.TYPE_BYTE, new BigInteger("1"));
+        IndexColorModel model2 = new IndexColorModel(8, 3, new int[] {color,
+                color, color}, 0, DataBuffer.TYPE_BYTE, new BigInteger("1"));
+        verifyEquals(model1, model2);
+    }
+
+    private static void testSameIndexColorModel() {
+        testConstructor1();
+        testConstructor2();
+        testConstructor3();
+        testConstructor4();
+        testConstructor5();
+        testConstructor6();
+        testConstructor7();
+    }
+    public static void main(String[] args) {
+        /* test whether equals() method works properly for parameters
+         * unique to IndexColorModel.
+         */
+        testColorMapEquality();
+        testSizeEquality();
+        testTransparentIndexEquality();
+        testValidPixelsEquality();
+        // verify same IndexColorModel equality using different constructors.
+        testSameIndexColorModel();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/image/PackedColorModel/PackedColorModelEqualsTest.java	Mon Feb 13 12:13:20 2017 +0530
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, 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     7107905
+ * @summary Test verifies whether equals() and hashCode() methods in
+ *          PackedColorModel works properly.
+ * @run     main PackedColorModelEqualsTest
+ */
+
+import java.awt.color.ColorSpace;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
+
+public class PackedColorModelEqualsTest {
+
+    private static void verifyEquals(DirectColorModel m1,
+                                     DirectColorModel m2) {
+        if (m1.equals(null)) {
+            throw new RuntimeException("equals(null) returns true");
+        }
+        if (!(m1.equals(m2))) {
+            throw new RuntimeException("equals() method is not working"
+                    + " properly");
+        }
+        if (!(m2.equals(m1))) {
+            throw new RuntimeException("equals() method is not working"
+                    + " properly");
+        }
+        if (m1.hashCode() != m2.hashCode()) {
+            throw new RuntimeException("HashCode is not same for same"
+                    + " PackedColorModels");
+        }
+    }
+
+    private static void testMaskArrayEquality() {
+        /*
+         * Test with different maskArray values, since PackedColorModel
+         * is abstract we use subclass DirectColorModel.
+         */
+        DirectColorModel model1 =
+            new DirectColorModel(24, 0x00FF0000, 0x0000FF00, 0x000000FF);
+        DirectColorModel model2 =
+            new DirectColorModel(24, 0x000000FF, 0x0000FF00, 0x00FF0000);
+        if (model1.equals(model2)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " ColorMap equality improperly");
+        }
+        if (model2.equals(model1)) {
+            throw new RuntimeException("equals() method is determining"
+                    + " ColorMap equality improperly");
+        }
+    }
+
+    private static void testConstructor1() {
+        /*
+         * verify equality with constructor
+         * DirectColorModel(int bits, int rmask, int gmask, int bmask,
+         *    int amask)
+         */
+        DirectColorModel model1 =
+            new DirectColorModel(32, 0xFF000000, 0x00FF0000,
+                    0x0000FF00, 0x000000FF);
+        DirectColorModel model2 =
+            new DirectColorModel(32, 0xFF000000, 0x00FF0000,
+                    0x0000FF00, 0x000000FF);
+        verifyEquals(model1, model2);
+    }
+
+    private static void testConstructor2() {
+        /*
+         * verify equality with constructor
+         * DirectColorModel(ColorSpace space, int bits, int rmask, int gmask,
+         * int bmask, int amask, boolean isAlphaPremultiplied, int transferType)
+         */
+        DirectColorModel model1 =
+            new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF,
+                    false, DataBuffer.TYPE_BYTE);
+        DirectColorModel model2 =
+            new DirectColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
+                    32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF,
+                    false, DataBuffer.TYPE_BYTE);
+        verifyEquals(model1, model2);
+    }
+
+    private static void testSamePackedColorModel() {
+        testConstructor1();
+        testConstructor2();
+    }
+    public static void main(String[] args) {
+        // test with different mask array.
+        testMaskArrayEquality();
+        // verify PackedColorModel equality using different constructors.
+        testSamePackedColorModel();
+    }
+}
+