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