1 /*
   2  * Copyright (c) 2013, 2017, 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 import java.util.ArrayList;
  25 import java.util.Arrays;
  26 import java.util.ConcurrentModificationException;
  27 import java.util.HashMap;
  28 import java.util.HashSet;
  29 import java.util.LinkedHashMap;
  30 import java.util.LinkedHashSet;
  31 import java.util.LinkedList;
  32 import java.util.List;
  33 import java.util.PriorityQueue;
  34 import java.util.Spliterator;
  35 import java.util.Stack;
  36 import java.util.TreeMap;
  37 import java.util.TreeSet;
  38 import java.util.Vector;
  39 import java.util.WeakHashMap;
  40 import java.util.function.Supplier;
  41 
  42 import org.testng.Assert.ThrowingRunnable;
  43 import org.testng.annotations.DataProvider;
  44 import org.testng.annotations.Test;
  45 
  46 import static org.testng.Assert.assertThrows;
  47 
  48 /**
  49  * @test
  50  * @bug 8148748
  51  * @summary Spliterator fail-fast tests
  52  * @run testng SpliteratorFailFastTest
  53  */
  54 
  55 @Test
  56 public class SpliteratorFailFastTest extends SpliteratorLateBindingFailFastHelper {
  57 
  58     static Object[][] spliteratorDataProvider;
  59 
  60     @DataProvider(name = "Source")
  61     public static Object[][] spliteratorDataProvider() {
  62         if (spliteratorDataProvider != null) {
  63             return spliteratorDataProvider;
  64         }
  65 
  66         List<Object[]> data = new ArrayList<>();
  67         SpliteratorDataBuilder<Integer> db =
  68                 new SpliteratorDataBuilder<>(data, 5, Arrays.asList(1, 2, 3, 4));
  69 
  70         // Collections
  71 
  72         db.addList(ArrayList::new);
  73 
  74         db.addList(LinkedList::new);
  75 
  76         db.addList(Vector::new);
  77 
  78         db.addList(AbstractRandomAccessListImpl::new);
  79 
  80         db.addCollection(HashSet::new);
  81 
  82         db.addCollection(LinkedHashSet::new);
  83 
  84         db.addCollection(TreeSet::new);
  85 
  86         db.addCollection(c -> {
  87             Stack<Integer> s = new Stack<>();
  88             s.addAll(c);
  89             return s;
  90         });
  91 
  92         db.addCollection(PriorityQueue::new);
  93 
  94         // ArrayDeque fails some tests since its fail-fast support is weaker
  95         // than other collections and limited to detecting most, but not all,
  96         // removals.  It probably requires its own test since it is difficult
  97         // to abstract out the conditions under which it fails-fast.
  98 //        db.addCollection(ArrayDeque::new);
  99 
 100         // Maps
 101 
 102         db.addMap(HashMap::new);
 103 
 104         db.addMap(LinkedHashMap::new);
 105 
 106         // This fails when run through jtreg but passes when run through
 107         // ant
 108 //        db.addMap(IdentityHashMap::new);
 109 
 110         db.addMap(WeakHashMap::new);
 111 
 112         // @@@  Descending maps etc
 113         db.addMap(TreeMap::new);
 114 
 115         return spliteratorDataProvider = data.toArray(new Object[0][]);
 116     }
 117 
 118     @Test(dataProvider = "Source")
 119     public <T> void testTryAdvance(String description, Supplier<Source<T>> ss) {
 120         {
 121             Source<T> source = ss.get();
 122             Spliterator<T> s = source.spliterator();
 123 
 124             s.tryAdvance(e -> {
 125             });
 126             source.update();
 127 
 128             assertThrowsCME(() -> s.tryAdvance(e -> {
 129             }));
 130         }
 131 
 132         {
 133             Source<T> source = ss.get();
 134             Spliterator<T> s = source.spliterator();
 135 
 136             s.tryAdvance(e -> {
 137             });
 138             source.update();
 139 
 140             assertThrowsCME(() -> s.forEachRemaining(e -> {
 141             }));
 142         }
 143     }
 144 
 145     @Test(dataProvider = "Source")
 146     public <T> void testForEach(String description, Supplier<Source<T>> ss) {
 147         Source<T> source = ss.get();
 148         Spliterator<T> s = source.spliterator();
 149 
 150         assertThrowsCME(() -> s.forEachRemaining(e -> {
 151             source.update();
 152         }));
 153     }
 154 
 155     @Test(dataProvider = "Source")
 156     public <T> void testEstimateSize(String description, Supplier<Source<T>> ss) {
 157         {
 158             Source<T> source = ss.get();
 159             Spliterator<T> s = source.spliterator();
 160 
 161             s.estimateSize();
 162             source.update();
 163 
 164             assertThrowsCME(() -> s.tryAdvance(e -> {
 165             }));
 166         }
 167 
 168         {
 169             Source<T> source = ss.get();
 170             Spliterator<T> s = source.spliterator();
 171 
 172             s.estimateSize();
 173             source.update();
 174 
 175             assertThrowsCME(() -> s.forEachRemaining(e -> {
 176             }));
 177         }
 178     }
 179 
 180     private void assertThrowsCME(ThrowingRunnable r) {
 181         assertThrows(ConcurrentModificationException.class, r);
 182     }
 183 
 184 }