ChorusLine.java revision 12745:f068a4ffddd2
1/* 2 * Copyright (c) 2005, 2010, 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 6324846 27 * @summary Deque implementations must behave isomorphically 28 * @author Martin Buchholz 29 */ 30 31import java.util.*; 32import java.util.concurrent.*; 33 34public class ChorusLine { 35 private interface Tweaker { 36 void run(Deque<Integer> deq); 37 } 38 39 private static final Tweaker[] tweakers = { 40 new Tweaker() { public void run(Deque<Integer> deq) { 41 for (int i = 0; i < 7; i++) 42 deq.addLast(i); 43 deq.removeFirst(); 44 deq.removeFirst(); 45 deq.addLast(7); 46 deq.addLast(8); 47 Iterator<Integer> it = deq.descendingIterator(); 48 equal(it.next(), 8); 49 it.remove(); 50 51 try {it.remove();} 52 catch (IllegalStateException e) {pass();} 53 catch (Throwable t) {unexpected(t);} 54 55 deq.addLast(9); 56 it = deq.descendingIterator(); 57 equal(it.next(), 9); 58 equal(it.next(), 7); 59 it.remove(); 60 61 try {it.remove();} 62 catch (IllegalStateException e) {pass();} 63 catch (Throwable t) {unexpected(t);} 64 65 equal(it.next(), 6); 66 67 System.out.println(deq); 68 }}, 69 new Tweaker() { public void run(Deque<Integer> deq) { 70 deq.clear(); 71 check(deq.isEmpty()); 72 check(deq.size() == 0); 73 check(! deq.iterator().hasNext()); 74 check(! deq.descendingIterator().hasNext()); 75 76 try {deq.iterator().next(); fail();} 77 catch (NoSuchElementException e) {pass();} 78 catch (Throwable t) {unexpected(t);} 79 80 try {deq.descendingIterator().next(); fail();} 81 catch (NoSuchElementException e) {pass();} 82 catch (Throwable t) {unexpected(t);} 83 }}, 84 new Tweaker() { public void run(Deque<Integer> deq) { 85 for (int i = 0; i < 11; i++) 86 deq.add(i); 87 Iterator<Integer> it = deq.iterator(); 88 equal(it.next(), 0); 89 equal(it.next(), 1); 90 it.remove(); 91 deq.addFirst(-1); 92 deq.addFirst(-2); 93 it = deq.iterator(); 94 equal(it.next(), -2); 95 equal(it.next(), -1); 96 equal(it.next(), 0); 97 it.remove(); 98 99 it = deq.descendingIterator(); 100 101 try {it.remove(); fail();} 102 catch (IllegalStateException e) {pass();} 103 catch (Throwable t) {unexpected(t);} 104 105 equal(it.next(), 10); 106 it.remove(); 107 108 try {it.remove(); fail();} 109 catch (IllegalStateException e) {pass();} 110 catch (Throwable t) {unexpected(t);} 111 112 equal(it.next(), 9); 113 equal(it.next(), 8); 114 it.remove(); 115 System.out.println(deq); 116 }}, 117 new Tweaker() { public void run(Deque<Integer> deq) { 118 while (deq.size() > 1) { 119 Iterator<Integer> it = deq.iterator(); 120 it.next(); it.remove(); 121 it = deq.descendingIterator(); 122 it.next(); it.remove(); 123 } 124 System.out.println(deq); 125 }}}; 126 127 private static void realMain(String[] args) throws Throwable { 128 Collection<Deque<Integer>> deqs = new ArrayDeque<Deque<Integer>>(3); 129 deqs.add(new ArrayDeque<Integer>()); 130 deqs.add(new LinkedList<Integer>()); 131 deqs.add(new LinkedBlockingDeque<Integer>()); 132 deqs.add(new ConcurrentLinkedDeque<Integer>()); 133 134 equal(deqs); 135 136 for (Tweaker tweaker : tweakers) { 137 for (Deque<Integer> deq : deqs) 138 tweaker.run(deq); 139 equal(deqs); 140 } 141 } 142 143 private static void equal(Iterable<Deque<Integer>> deqs) { 144 Deque<Integer> prev = null; 145 for (Deque<Integer> deq : deqs) { 146 if (prev != null) { 147 equal(prev.isEmpty(), deq.isEmpty()); 148 equal(prev.size(), deq.size()); 149 equal(prev.toString(), deq.toString()); 150 } 151 prev = deq; 152 } 153 154 Deque<Iterator<Integer>> its = new ArrayDeque<Iterator<Integer>>(); 155 for (Deque<Integer> deq : deqs) 156 its.addLast(deq.iterator()); 157 equal(its); 158 159 Deque<Iterator<Integer>> dits = new ArrayDeque<Iterator<Integer>>(); 160 for (Deque<Integer> deq : deqs) 161 dits.addLast(deq.descendingIterator()); 162 equal(dits); 163 } 164 165 private static void equal(Deque<Iterator<Integer>> its) { 166 Iterator<Integer> it0 = its.remove(); 167 while (it0.hasNext()) { 168 Integer i = it0.next(); 169 for (Iterator<Integer> it : its) 170 equal(it.next(), i); 171 } 172 for (Iterator<Integer> it : its) { 173 check(! it.hasNext()); 174 175 try {it.next(); fail();} 176 catch (NoSuchElementException e) {pass();} 177 catch (Throwable t) {unexpected(t);} 178 } 179 } 180 181 //--------------------- Infrastructure --------------------------- 182 static volatile int passed = 0, failed = 0; 183 static void pass() {passed++;} 184 static void fail() {failed++; Thread.dumpStack();} 185 static void fail(String msg) {System.out.println(msg); fail();} 186 static void unexpected(Throwable t) {failed++; t.printStackTrace();} 187 static void check(boolean cond) {if (cond) pass(); else fail();} 188 static void equal(Object x, Object y) { 189 if (x == null ? y == null : x.equals(y)) pass(); 190 else fail(x + " not equal to " + y);} 191 public static void main(String[] args) throws Throwable { 192 try {realMain(args);} catch (Throwable t) {unexpected(t);} 193 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 194 if (failed > 0) throw new AssertionError("Some tests failed");} 195} 196