1 /*
   2  * Copyright (c) 2016, 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 package java.lang.reflect;
  25 
  26 import java.lang.ref.Reference;
  27 import java.util.Objects;
  28 
  29 /**
  30  * Functional test for WeakPairMap
  31  *
  32  * @author Peter Levart
  33  */
  34 public class WeakPairMapTest {
  35     public static void main(String[] args) {
  36         WeakPairMap<Object, Object, String> pm = new WeakPairMap<>();
  37         Object key1 = new Object();
  38         Object key2 = new Object();
  39 
  40         // check for emptiness
  41         assertEquals(pm.constainsKeyPair(key1, key2), false);
  42         assertEquals(pm.get(key1, key2), null);
  43 
  44         // check for NPE(s)
  45         for (Object k1 : new Object[]{null, key1}) {
  46             for (Object k2 : new Object[]{null, key2}) {
  47                 for (String v : new String[]{null, "abc"}) {
  48 
  49                     if (k1 != null && k2 != null && v != null) {
  50                         // skip non-null args
  51                         continue;
  52                     }
  53 
  54                     try {
  55                         pm.put(k1, k2, v);
  56                         throw new AssertionError("Unexpected code path, k1=" +
  57                                                  k1 + ", k2=" + k2 + ", v=" + v);
  58                     } catch (NullPointerException e) {
  59                         // expected
  60                     }
  61 
  62                     try {
  63                         pm.putIfAbsent(k1, k2, v);
  64                         throw new AssertionError("Unexpected code path, k1=" +
  65                                                  k1 + ", k2=" + k2 + ", v=" + v);
  66                     } catch (NullPointerException e) {
  67                         // expected
  68                     }
  69 
  70                     if (k1 != null && k2 != null) {
  71                         // skip non-null args
  72                         continue;
  73                     }
  74 
  75                     try {
  76                         pm.computeIfAbsent(k1, k2, (_k1, _k2) -> v);
  77                         throw new AssertionError("Unexpected code path, k1=" +
  78                                                  k1 + ", k2=" + k2 + ", v=" + v);
  79                     } catch (NullPointerException e) {
  80                         // expected
  81                     }
  82 
  83                     try {
  84                         pm.constainsKeyPair(k1, k2);
  85                         throw new AssertionError("Unexpected code path, k1=" +
  86                                                  k1 + ", k2=" + k2);
  87                     } catch (NullPointerException e) {
  88                         // expected
  89                     }
  90 
  91                     try {
  92                         pm.get(k1, k2);
  93                         throw new AssertionError("Unexpected code path, k1=" +
  94                                                  k1 + ", k2=" + k2);
  95                     } catch (NullPointerException e) {
  96                         // expected
  97                     }
  98                 }
  99             }
 100         }
 101 
 102         // check insertion
 103         assertEquals(pm.putIfAbsent(key1, key2, "abc"), null);
 104         assertEquals(pm.get(key1, key2), "abc");
 105 
 106         // check retention while both keys are still reachable
 107         gc();
 108         assertEquals(pm.values().contains("abc"), true);
 109         assertEquals(pm.get(key1, key2), "abc");
 110 
 111         // check cleanup when both keys are unreachable
 112         key1 = null;
 113         key2 = null;
 114         gc();
 115         assertEquals(pm.values().contains("abc"), false);
 116 
 117         // new insertion
 118         key1 = new Object();
 119         key2 = new Object();
 120         assertEquals(pm.putIfAbsent(key1, key2, "abc"), null);
 121         assertEquals(pm.get(key1, key2), "abc");
 122 
 123         // check retention while both keys are still reachable
 124         gc();
 125         assertEquals(pm.values().contains("abc"), true);
 126         assertEquals(pm.get(key1, key2), "abc");
 127 
 128         // check cleanup when 1st key is unreachable
 129         key1 = null;
 130         gc();
 131         assertEquals(pm.values().contains("abc"), false);
 132         Reference.reachabilityFence(key2);
 133 
 134         // new insertion
 135         key1 = new Object();
 136         key2 = new Object();
 137         assertEquals(pm.putIfAbsent(key1, key2, "abc"), null);
 138         assertEquals(pm.get(key1, key2), "abc");
 139 
 140         // check retention while both keys are still reachable
 141         gc();
 142         assertEquals(pm.values().contains("abc"), true);
 143         assertEquals(pm.get(key1, key2), "abc");
 144 
 145         // check cleanup when 2nd key is unreachable
 146         key2 = null;
 147         gc();
 148         assertEquals(pm.values().contains("abc"), false);
 149         Reference.reachabilityFence(key1);
 150     }
 151 
 152     static void gc() {
 153         System.gc();
 154         try {
 155             Thread.sleep(500L);
 156         } catch (InterruptedException e) {
 157             throw new AssertionError("Interrupted");
 158         }
 159     }
 160 
 161     static void assertEquals(Object actual, Object expected) {
 162         if (!Objects.equals(actual, expected)) {
 163             throw new AssertionError("Expected: " + expected + ", actual: " + actual);
 164         }
 165     }
 166 }