1 /*
  2  * Copyright (c) 2005, 2024, 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 6306829 8336669
 27  * @summary Verify assertions in get() javadocs
 28  * @author Martin Buchholz
 29  */
 30 
 31 import java.util.HashMap;
 32 import java.util.Hashtable;
 33 import java.util.IdentityHashMap;
 34 import java.util.LinkedHashMap;
 35 import java.util.Map;
 36 import java.util.Objects;
 37 import java.util.SortedMap;
 38 import java.util.TreeMap;
 39 import java.util.WeakHashMap;
 40 import java.util.concurrent.ConcurrentHashMap;
 41 import java.util.concurrent.ConcurrentMap;
 42 import java.util.concurrent.ConcurrentSkipListMap;
 43 
 44 public class Get {
 45 
 46     // An identity class holding an char (like non-Preview Character)
 47     record Char(char c) implements Comparable<Char> {
 48         @Override
 49         public int compareTo(Char ch) {
 50             return Character.compare(c, ch.c);
 51         }
 52     }
 53 
 54     private static void realMain(String[] args) throws Throwable {
 55         testMap(new Hashtable<Char,Boolean>());
 56         testMap(new HashMap<Char,Boolean>());
 57         testMap(new IdentityHashMap<Char,Boolean>());
 58         testMap(new LinkedHashMap<Char,Boolean>());
 59         testMap(new ConcurrentHashMap<Char,Boolean>());
 60         testMap(new WeakHashMap<Char,Boolean>());
 61         testMap(new TreeMap<Char,Boolean>());
 62         testMap(new ConcurrentSkipListMap<Char,Boolean>());
 63     }
 64 
 65     private static void put(Map<Char,Boolean> m,
 66                             Char key, Boolean value,
 67                             Boolean oldValue) {
 68         if (oldValue != null) {
 69             check("containsValue(oldValue)", m.containsValue(oldValue));
 70             check("values.contains(oldValue)", m.values().contains(oldValue));
 71         }
 72         equal(m.put(key, value), oldValue);
 73         equal(m.get(key), value);
 74         check("containsKey", m.containsKey(key));
 75         check("keySet.contains", m.keySet().contains(key));
 76         check("containsValue", m.containsValue(value));
 77         check("values.contains",  m.values().contains(value));
 78         check("!isEmpty", ! m.isEmpty());
 79     }
 80 
 81     private static void testMap(Map<Char,Boolean> m) {
 82         // We verify following assertions in get(Object) method javadocs
 83         boolean permitsNullKeys = (! (m instanceof ConcurrentMap ||
 84                                       m instanceof Hashtable     ||
 85                                       m instanceof SortedMap));
 86         boolean permitsNullValues = (! (m instanceof ConcurrentMap ||
 87                                         m instanceof Hashtable));
 88         boolean usesIdentity = m instanceof IdentityHashMap;
 89 
 90         System.err.println(m.getClass());
 91         Char aCh = new Char('A');
 92         put(m, aCh, true,  null);
 93         put(m, aCh, false, true);
 94         put(m, new Char('B'), true,  null);
 95         put(m, new Char('A'), false, usesIdentity ? null : false);
 96         if (permitsNullKeys) {
 97             try {
 98                 put(m, null, true,  null);
 99                 put(m, null, false, true);
100             }
101             catch (Throwable t) { unexpected(m.getClass().getName(), t); }
102         } else {
103             try { m.get(null); fail(m.getClass().getName() + " did not reject null key"); }
104             catch (NullPointerException e) {}
105             catch (Throwable t) { unexpected(m.getClass().getName(), t); }
106 
107             try { m.put(null, true); fail(m.getClass().getName() + " did not reject null key"); }
108             catch (NullPointerException e) {}
109             catch (Throwable t) { unexpected(m.getClass().getName(), t); }
110         }
111         if (permitsNullValues) {
112             try {
113                 Char cCh = new Char('C');
114                 put(m, cCh, null, null);
115                 put(m, cCh, true, null);
116                 put(m, cCh, null, true);
117             }
118             catch (Throwable t) { unexpected(m.getClass().getName(), t); }
119         } else {
120             try { m.put(new Char('A'), null); fail(m.getClass().getName() + " did not reject null key"); }
121             catch (NullPointerException e) {}
122             catch (Throwable t) { unexpected(m.getClass().getName(), t); }
123 
124             try { m.put(new Char('C'), null); fail(m.getClass().getName() + " did not reject null key"); }
125             catch (NullPointerException e) {}
126             catch (Throwable t) { unexpected(m.getClass().getName(), t); }
127         }
128     }
129 
130     //--------------------- Infrastructure ---------------------------
131     static volatile int passed = 0, failed = 0;
132     static void pass() { passed++; }
133     static void fail() { failed++; new Error("Failure").printStackTrace(System.err); }
134     static void fail(String msg) { failed++; new Error("Failure: " + msg).printStackTrace(System.err); }
135     static void unexpected(String msg, Throwable t) { System.err.println("Unexpected: " + msg); unexpected(t); }
136     static void unexpected(Throwable t) { failed++; t.printStackTrace(System.err); }
137     static void check(boolean cond) { if (cond) pass(); else fail(); }
138     static void check(String desc, boolean cond) { if (cond) pass(); else fail(desc); }
139     static void equal(Object x, Object y) {
140         if (Objects.equals(x,y)) pass(); else fail(x + " not equal to " + y);
141     }
142 
143     public static void main(String[] args) throws Throwable {
144         try { realMain(args); } catch (Throwable t) { unexpected(t); }
145 
146         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
147         if (failed > 0) throw new Error("Some tests failed");
148     }
149 }