1 /*
   2  * Copyright 2003 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug     4904140
  27  * @summary Unit test for EnumMap
  28  * @author  Josh Bloch
  29  * @author  Yo Yo Ma
  30  */
  31 
  32 import java.util.*;
  33 import java.io.*;
  34 
  35 public class EnumMapBash {
  36     static Random rnd = new Random();
  37 
  38     public static void main(String[] args) {
  39         bash(Silly31.class);
  40         bash(Silly32.class);
  41         bash(Silly33.class);
  42         bash(Silly63.class);
  43         bash(Silly64.class);
  44         bash(Silly65.class);
  45         bash(Silly127.class);
  46         bash(Silly128.class);
  47         bash(Silly129.class);
  48         bash(Silly500.class);
  49     }
  50 
  51     private static Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
  52 
  53     static <T extends Enum<T>> void bash(Class<T> enumClass) {
  54         Enum[] universe = enumClass.getEnumConstants();
  55 
  56         int numItr = 100;
  57 
  58         // Linked List test
  59         for (int i=0; i<numItr; i++) {
  60             int mapSize = universe.length * 7 / 8;
  61 
  62             // Build the linked list
  63             Map<T, T> m = new EnumMap<T, T>(enumClass);
  64             if (!m.isEmpty())
  65                 fail("New instance non empty.");
  66             Enum[] perm = (Enum[]) universe.clone();
  67             Collections.shuffle(Arrays.asList(perm));
  68             T head = (T) perm[0];
  69             for (int j = 0; j < mapSize; j++)
  70                 m.put((T)perm[j], (T)perm[j + 1]);
  71             T nil = (T)perm[mapSize];
  72 
  73             if (m.size() != mapSize)
  74                 fail("Size not as expected.");
  75 
  76             Map<T, T> tm = new TreeMap<T, T>(m);
  77 
  78             if (m.hashCode() != tm.hashCode())
  79                 fail("Incorrect hashCode computation.");
  80             if (!m.toString().equals(tm.toString()))
  81                 fail("Incorrect toString computation.");
  82             if (!tm.equals(m))
  83                 fail("Incorrect equals (1).");
  84             if (!m.equals(tm))
  85                 fail("Incorrect equals (2).");
  86 
  87             Map<T, T> m2 = new EnumMap<T, T>(enumClass); m2.putAll(m);
  88             m2.values().removeAll(m.keySet());
  89             if (m2.size()!= 1 || !m2.containsValue(nil))
  90                 fail("Collection views test failed.");
  91 
  92             int j=0;
  93             while (head != nil) {
  94                 if (!m.containsKey(head))
  95                     fail("Linked list doesn't contain a link.");
  96                 T newHead = m.get(head);
  97                 if (newHead == null)
  98                     fail("Could not retrieve a link.");
  99                 m.remove(head);
 100                 head = newHead;
 101                 j++;
 102             }
 103             if (!m.isEmpty())
 104                 fail("Map nonempty after removing all links.");
 105             if (j != mapSize)
 106                 fail("Linked list size not as expected.");
 107         }
 108 
 109         EnumMap<T, T> m = new EnumMap<T, T>(enumClass);
 110         int mapSize = 0;
 111         for (int i=0; i<universe.length; i += 2) {
 112             if (m.put((T)universe[i], (T)universe[i]) != null)
 113                 fail("put returns a non-null value erroenously.");
 114             mapSize++;
 115         }
 116         for (int i=0; i<universe.length; i++)
 117             if (m.containsValue(universe[i]) != (i%2==0))
 118                 fail("contains value "+i);
 119         if (m.put((T)universe[0], (T)universe[0]) == null)
 120             fail("put returns a null value erroenously.");
 121 
 122         Map<T, T>  m2 = m.clone();
 123         cloneTest(m, m2);
 124 
 125         m2 = new EnumMap<T,T>(enumClass);
 126         m2.putAll(m);
 127         cloneTest(m, m2);
 128 
 129         m2 = new EnumMap<T, T>(m);
 130         cloneTest(m, m2);
 131 
 132         m2 = new EnumMap<T, T>((Map<T, T>) m);
 133         cloneTest(m, m2);
 134         if (!m.isEmpty()) {
 135             m2 = new EnumMap<T, T>(new HashMap<T, T>(m));
 136             cloneTest(m, m2);
 137         }
 138 
 139         m2 = deepCopy(m);
 140         cloneTest(m, m2);
 141 
 142         if (!m.equals(m2))
 143             fail("Clone not equal to original. (1)");
 144         if (!m2.equals(m))
 145             fail("Clone not equal to original. (2)");
 146 
 147         Set<Map.Entry<T,T>> s = m.entrySet(), s2 = m2.entrySet();
 148 
 149         if (!s.equals(s2))
 150             fail("Clone not equal to original. (3)");
 151         if (!s2.equals(s))
 152             fail("Clone not equal to original. (4)");
 153         if (!s.containsAll(s2))
 154             fail("Original doesn't contain clone!");
 155         if (!s2.containsAll(s))
 156             fail("Clone doesn't contain original!");
 157 
 158         s2.removeAll(s);
 159         if (!m2.isEmpty()) {
 160             System.out.println(m2.size());
 161             System.out.println(m2);
 162             fail("entrySet().removeAll failed.");
 163         }
 164 
 165         m2.putAll(m);
 166         m2.clear();
 167         if (!m2.isEmpty())
 168             fail("clear failed.");
 169 
 170         Iterator i = m.entrySet().iterator();
 171         while(i.hasNext()) {
 172             i.next();
 173             i.remove();
 174         }
 175         if (!m.isEmpty())
 176             fail("Iterator.remove() failed");
 177     }
 178 
 179     // Done inefficiently so as to exercise various functions
 180     static <K, V> void cloneTest(Map<K, V> m, Map<K, V> clone) {
 181         if (!m.equals(clone))
 182             fail("Map not equal to copy.");
 183         if (!clone.equals(m))
 184             fail("Copy not equal to map.");
 185         if (!m.entrySet().containsAll(clone.entrySet()))
 186             fail("Set does not contain copy.");
 187         if (!clone.entrySet().containsAll(m.entrySet()))
 188             fail("Copy does not contain set.");
 189         if (!m.entrySet().equals(clone.entrySet()))
 190             fail("Set not equal clone set");
 191         if (!clone.entrySet().equals(m.entrySet()))
 192             fail("Clone set not equal set");
 193     }
 194 
 195     // Utility method to do a deep copy of an object *very slowly* using
 196     // serialization/deserialization
 197     static <T> T deepCopy(T oldObj) {
 198         try {
 199             ByteArrayOutputStream bos = new ByteArrayOutputStream();
 200             ObjectOutputStream oos = new ObjectOutputStream(bos);
 201             oos.writeObject(oldObj);
 202             oos.flush();
 203             ByteArrayInputStream bin = new ByteArrayInputStream(
 204                 bos.toByteArray());
 205             ObjectInputStream ois = new ObjectInputStream(bin);
 206             return (T) ois.readObject();
 207         } catch(Exception e) {
 208             throw new IllegalArgumentException(e.toString());
 209         }
 210     }
 211 
 212     static void fail(String s) {
 213         throw new RuntimeException(s);
 214     }
 215 
 216     public enum Silly31 {
 217         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 218         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30
 219     }
 220 
 221     public enum Silly32 {
 222         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 223         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31
 224     }
 225 
 226     public enum Silly33 {
 227         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 228         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
 229         e32
 230     }
 231 
 232     public enum Silly63 {
 233         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 234         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
 235         e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
 236         e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
 237         e62
 238     }
 239 
 240     public enum Silly64 {
 241         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 242         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
 243         e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
 244         e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
 245         e62, e63
 246     }
 247 
 248     public enum Silly65 {
 249         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 250         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
 251         e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
 252         e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
 253         e62, e63, e64
 254     }
 255 
 256     public enum Silly127 {
 257         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 258         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
 259         e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
 260         e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
 261         e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
 262         e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
 263         e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
 264         e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
 265         e118, e119, e120, e121, e122, e123, e124, e125, e126
 266     }
 267 
 268     public enum Silly128 {
 269         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 270         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
 271         e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
 272         e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
 273         e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
 274         e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
 275         e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
 276         e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
 277         e118, e119, e120, e121, e122, e123, e124, e125, e126, e127
 278     }
 279 
 280     public enum Silly129 {
 281         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 282         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
 283         e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
 284         e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
 285         e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
 286         e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
 287         e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
 288         e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
 289         e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128
 290     }
 291 
 292     public enum Silly500 {
 293         e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12, e13, e14, e15, e16,
 294         e17, e18, e19, e20, e21, e22, e23, e24, e25, e26, e27, e28, e29, e30, e31,
 295         e32, e33, e34, e35, e36, e37, e38, e39, e40, e41, e42, e43, e44, e45, e46,
 296         e47, e48, e49, e50, e51, e52, e53, e54, e55, e56, e57, e58, e59, e60, e61,
 297         e62, e63, e64, e65, e66, e67, e68, e69, e70, e71, e72, e73, e74, e75, e76,
 298         e77, e78, e79, e80, e81, e82, e83, e84, e85, e86, e87, e88, e89, e90, e91,
 299         e92, e93, e94, e95, e96, e97, e98, e99, e100, e101, e102, e103, e104, e105,
 300         e106, e107, e108, e109, e110, e111, e112, e113, e114, e115, e116, e117,
 301         e118, e119, e120, e121, e122, e123, e124, e125, e126, e127, e128, e129,
 302         e130, e131, e132, e133, e134, e135, e136, e137, e138, e139, e140, e141,
 303         e142, e143, e144, e145, e146, e147, e148, e149, e150, e151, e152, e153,
 304         e154, e155, e156, e157, e158, e159, e160, e161, e162, e163, e164, e165,
 305         e166, e167, e168, e169, e170, e171, e172, e173, e174, e175, e176, e177,
 306         e178, e179, e180, e181, e182, e183, e184, e185, e186, e187, e188, e189,
 307         e190, e191, e192, e193, e194, e195, e196, e197, e198, e199, e200, e201,
 308         e202, e203, e204, e205, e206, e207, e208, e209, e210, e211, e212, e213,
 309         e214, e215, e216, e217, e218, e219, e220, e221, e222, e223, e224, e225,
 310         e226, e227, e228, e229, e230, e231, e232, e233, e234, e235, e236, e237,
 311         e238, e239, e240, e241, e242, e243, e244, e245, e246, e247, e248, e249,
 312         e250, e251, e252, e253, e254, e255, e256, e257, e258, e259, e260, e261,
 313         e262, e263, e264, e265, e266, e267, e268, e269, e270, e271, e272, e273,
 314         e274, e275, e276, e277, e278, e279, e280, e281, e282, e283, e284, e285,
 315         e286, e287, e288, e289, e290, e291, e292, e293, e294, e295, e296, e297,
 316         e298, e299, e300, e301, e302, e303, e304, e305, e306, e307, e308, e309,
 317         e310, e311, e312, e313, e314, e315, e316, e317, e318, e319, e320, e321,
 318         e322, e323, e324, e325, e326, e327, e328, e329, e330, e331, e332, e333,
 319         e334, e335, e336, e337, e338, e339, e340, e341, e342, e343, e344, e345,
 320         e346, e347, e348, e349, e350, e351, e352, e353, e354, e355, e356, e357,
 321         e358, e359, e360, e361, e362, e363, e364, e365, e366, e367, e368, e369,
 322         e370, e371, e372, e373, e374, e375, e376, e377, e378, e379, e380, e381,
 323         e382, e383, e384, e385, e386, e387, e388, e389, e390, e391, e392, e393,
 324         e394, e395, e396, e397, e398, e399, e400, e401, e402, e403, e404, e405,
 325         e406, e407, e408, e409, e410, e411, e412, e413, e414, e415, e416, e417,
 326         e418, e419, e420, e421, e422, e423, e424, e425, e426, e427, e428, e429,
 327         e430, e431, e432, e433, e434, e435, e436, e437, e438, e439, e440, e441,
 328         e442, e443, e444, e445, e446, e447, e448, e449, e450, e451, e452, e453,
 329         e454, e455, e456, e457, e458, e459, e460, e461, e462, e463, e464, e465,
 330         e466, e467, e468, e469, e470, e471, e472, e473, e474, e475, e476, e477,
 331         e478, e479, e480, e481, e482, e483, e484, e485, e486, e487, e488, e489,
 332         e490, e491, e492, e493, e494, e495, e496, e497, e498, e499
 333     }
 334 
 335 }