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