ConstraintsTest.java revision 7dd252788645e940eada959bdde927426e2531c9
1/* 2 * Copyright (C) 2007 The Guava Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.google.common.collect; 18 19import static java.util.Arrays.asList; 20 21import com.google.common.annotations.GwtCompatible; 22import com.google.common.annotations.GwtIncompatible; 23import com.google.common.testing.FluentAsserts; 24import com.google.common.testing.SerializableTester; 25 26import java.util.AbstractCollection; 27import java.util.Collection; 28import java.util.Collections; 29import java.util.Iterator; 30import java.util.List; 31import java.util.ListIterator; 32import java.util.RandomAccess; 33import java.util.Set; 34import java.util.SortedSet; 35 36import junit.framework.TestCase; 37 38/** 39 * Tests for {@code Constraints}. 40 * 41 * @author Mike Bostock 42 * @author Jared Levy 43 */ 44@GwtCompatible(emulated = true) 45public class ConstraintsTest extends TestCase { 46 47 private static final String TEST_ELEMENT = "test"; 48 49 private static final class TestElementException 50 extends IllegalArgumentException { 51 private static final long serialVersionUID = 0; 52 } 53 54 private static final Constraint<String> TEST_CONSTRAINT 55 = new Constraint<String>() { 56 @Override 57 public String checkElement(String element) { 58 if (TEST_ELEMENT.equals(element)) { 59 throw new TestElementException(); 60 } 61 return element; 62 } 63 }; 64 65 public void testNotNull() { 66 Constraint<? super String> constraint = Constraints.notNull(); 67 assertSame(TEST_ELEMENT, constraint.checkElement(TEST_ELEMENT)); 68 try { 69 constraint.checkElement(null); 70 fail("NullPointerException expected"); 71 } catch (NullPointerException expected) {} 72 assertEquals("Not null", constraint.toString()); 73 } 74 75 public void testConstrainedCollectionLegal() { 76 Collection<String> collection = Lists.newArrayList("foo", "bar"); 77 Collection<String> constrained = Constraints.constrainedCollection( 78 collection, TEST_CONSTRAINT); 79 collection.add(TEST_ELEMENT); 80 constrained.add("qux"); 81 constrained.addAll(asList("cat", "dog")); 82 /* equals and hashCode aren't defined for Collection */ 83 FluentAsserts.assertThat(collection).has().allOf("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder(); 84 FluentAsserts.assertThat(constrained).has() 85 .allOf("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder(); 86 } 87 88 public void testConstrainedCollectionIllegal() { 89 Collection<String> collection = Lists.newArrayList("foo", "bar"); 90 Collection<String> constrained = Constraints.constrainedCollection( 91 collection, TEST_CONSTRAINT); 92 try { 93 constrained.add(TEST_ELEMENT); 94 fail("TestElementException expected"); 95 } catch (TestElementException expected) {} 96 try { 97 constrained.addAll(asList("baz", TEST_ELEMENT)); 98 fail("TestElementException expected"); 99 } catch (TestElementException expected) {} 100 FluentAsserts.assertThat(constrained).has().allOf("foo", "bar").inOrder(); 101 FluentAsserts.assertThat(collection).has().allOf("foo", "bar").inOrder(); 102 } 103 104 public void testConstrainedSetLegal() { 105 Set<String> set = Sets.newLinkedHashSet(asList("foo", "bar")); 106 Set<String> constrained = Constraints.constrainedSet(set, TEST_CONSTRAINT); 107 set.add(TEST_ELEMENT); 108 constrained.add("qux"); 109 constrained.addAll(asList("cat", "dog")); 110 assertTrue(set.equals(constrained)); 111 assertTrue(constrained.equals(set)); 112 assertEquals(set.toString(), constrained.toString()); 113 assertEquals(set.hashCode(), constrained.hashCode()); 114 FluentAsserts.assertThat(set).has().allOf("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder(); 115 FluentAsserts.assertThat(constrained).has() 116 .allOf("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog").inOrder(); 117 } 118 119 public void testConstrainedSetIllegal() { 120 Set<String> set = Sets.newLinkedHashSet(asList("foo", "bar")); 121 Set<String> constrained = Constraints.constrainedSet(set, TEST_CONSTRAINT); 122 try { 123 constrained.add(TEST_ELEMENT); 124 fail("TestElementException expected"); 125 } catch (TestElementException expected) {} 126 try { 127 constrained.addAll(asList("baz", TEST_ELEMENT)); 128 fail("TestElementException expected"); 129 } catch (TestElementException expected) {} 130 FluentAsserts.assertThat(constrained).has().allOf("foo", "bar").inOrder(); 131 FluentAsserts.assertThat(set).has().allOf("foo", "bar").inOrder(); 132 } 133 134 public void testConstrainedSortedSetLegal() { 135 SortedSet<String> sortedSet = Sets.newTreeSet(asList("foo", "bar")); 136 SortedSet<String> constrained = Constraints.constrainedSortedSet( 137 sortedSet, TEST_CONSTRAINT); 138 sortedSet.add(TEST_ELEMENT); 139 constrained.add("qux"); 140 constrained.addAll(asList("cat", "dog")); 141 assertTrue(sortedSet.equals(constrained)); 142 assertTrue(constrained.equals(sortedSet)); 143 assertEquals(sortedSet.toString(), constrained.toString()); 144 assertEquals(sortedSet.hashCode(), constrained.hashCode()); 145 FluentAsserts.assertThat(sortedSet).has().allOf("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder(); 146 FluentAsserts.assertThat(constrained).has() 147 .allOf("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT).inOrder(); 148 assertNull(constrained.comparator()); 149 assertEquals("bar", constrained.first()); 150 assertEquals(TEST_ELEMENT, constrained.last()); 151 } 152 153 public void testConstrainedSortedSetIllegal() { 154 SortedSet<String> sortedSet = Sets.newTreeSet(asList("foo", "bar")); 155 SortedSet<String> constrained = Constraints.constrainedSortedSet( 156 sortedSet, TEST_CONSTRAINT); 157 try { 158 constrained.add(TEST_ELEMENT); 159 fail("TestElementException expected"); 160 } catch (TestElementException expected) {} 161 try { 162 constrained.subSet("bar", "foo").add(TEST_ELEMENT); 163 fail("TestElementException expected"); 164 } catch (TestElementException expected) {} 165 try { 166 constrained.headSet("bar").add(TEST_ELEMENT); 167 fail("TestElementException expected"); 168 } catch (TestElementException expected) {} 169 try { 170 constrained.tailSet("foo").add(TEST_ELEMENT); 171 fail("TestElementException expected"); 172 } catch (TestElementException expected) {} 173 try { 174 constrained.addAll(asList("baz", TEST_ELEMENT)); 175 fail("TestElementException expected"); 176 } catch (TestElementException expected) {} 177 FluentAsserts.assertThat(constrained).has().allOf("bar", "foo").inOrder(); 178 FluentAsserts.assertThat(sortedSet).has().allOf("bar", "foo").inOrder(); 179 } 180 181 public void testConstrainedListLegal() { 182 List<String> list = Lists.newArrayList("foo", "bar"); 183 List<String> constrained = Constraints.constrainedList( 184 list, TEST_CONSTRAINT); 185 list.add(TEST_ELEMENT); 186 constrained.add("qux"); 187 constrained.addAll(asList("cat", "dog")); 188 constrained.add(1, "cow"); 189 constrained.addAll(4, asList("box", "fan")); 190 constrained.set(2, "baz"); 191 assertTrue(list.equals(constrained)); 192 assertTrue(constrained.equals(list)); 193 assertEquals(list.toString(), constrained.toString()); 194 assertEquals(list.hashCode(), constrained.hashCode()); 195 FluentAsserts.assertThat(list).has().allOf( 196 "foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder(); 197 FluentAsserts.assertThat(constrained).has().allOf( 198 "foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder(); 199 ListIterator<String> iterator = constrained.listIterator(); 200 iterator.next(); 201 iterator.set("sun"); 202 constrained.listIterator(2).add("sky"); 203 FluentAsserts.assertThat(list).has().allOf( 204 "sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder(); 205 FluentAsserts.assertThat(constrained).has().allOf( 206 "sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog").inOrder(); 207 assertTrue(constrained instanceof RandomAccess); 208 } 209 210 public void testConstrainedListRandomAccessFalse() { 211 List<String> list = Lists.newLinkedList(asList("foo", "bar")); 212 List<String> constrained = Constraints.constrainedList( 213 list, TEST_CONSTRAINT); 214 list.add(TEST_ELEMENT); 215 constrained.add("qux"); 216 assertFalse(constrained instanceof RandomAccess); 217 } 218 219 public void testConstrainedListIllegal() { 220 List<String> list = Lists.newArrayList("foo", "bar"); 221 List<String> constrained = Constraints.constrainedList( 222 list, TEST_CONSTRAINT); 223 try { 224 constrained.add(TEST_ELEMENT); 225 fail("TestElementException expected"); 226 } catch (TestElementException expected) {} 227 try { 228 constrained.listIterator().add(TEST_ELEMENT); 229 fail("TestElementException expected"); 230 } catch (TestElementException expected) {} 231 try { 232 constrained.listIterator(1).add(TEST_ELEMENT); 233 fail("TestElementException expected"); 234 } catch (TestElementException expected) {} 235 try { 236 constrained.listIterator().set(TEST_ELEMENT); 237 fail("TestElementException expected"); 238 } catch (TestElementException expected) {} 239 try { 240 constrained.listIterator(1).set(TEST_ELEMENT); 241 fail("TestElementException expected"); 242 } catch (TestElementException expected) {} 243 try { 244 constrained.subList(0, 1).add(TEST_ELEMENT); 245 fail("TestElementException expected"); 246 } catch (TestElementException expected) {} 247 try { 248 constrained.add(1, TEST_ELEMENT); 249 fail("TestElementException expected"); 250 } catch (TestElementException expected) {} 251 try { 252 constrained.set(1, TEST_ELEMENT); 253 fail("TestElementException expected"); 254 } catch (TestElementException expected) {} 255 try { 256 constrained.addAll(asList("baz", TEST_ELEMENT)); 257 fail("TestElementException expected"); 258 } catch (TestElementException expected) {} 259 try { 260 constrained.addAll(1, asList("baz", TEST_ELEMENT)); 261 fail("TestElementException expected"); 262 } catch (TestElementException expected) {} 263 FluentAsserts.assertThat(constrained).has().allOf("foo", "bar").inOrder(); 264 FluentAsserts.assertThat(list).has().allOf("foo", "bar").inOrder(); 265 } 266 267 public void testConstrainedMultisetLegal() { 268 Multiset<String> multiset = HashMultiset.create(asList("foo", "bar")); 269 Multiset<String> constrained = Constraints.constrainedMultiset( 270 multiset, TEST_CONSTRAINT); 271 multiset.add(TEST_ELEMENT); 272 constrained.add("qux"); 273 constrained.addAll(asList("cat", "dog")); 274 constrained.add("cow", 2); 275 assertTrue(multiset.equals(constrained)); 276 assertTrue(constrained.equals(multiset)); 277 assertEquals(multiset.toString(), constrained.toString()); 278 assertEquals(multiset.hashCode(), constrained.hashCode()); 279 FluentAsserts.assertThat(multiset).has().allOf( 280 "foo", "bar", TEST_ELEMENT, "qux", "cat", "dog", "cow", "cow"); 281 FluentAsserts.assertThat(constrained).has().allOf( 282 "foo", "bar", TEST_ELEMENT, "qux", "cat", "dog", "cow", "cow"); 283 assertEquals(1, constrained.count("foo")); 284 assertEquals(1, constrained.remove("foo", 3)); 285 assertEquals(2, constrained.setCount("cow", 0)); 286 FluentAsserts.assertThat(multiset).has().allOf("bar", TEST_ELEMENT, "qux", "cat", "dog"); 287 FluentAsserts.assertThat(constrained).has().allOf("bar", TEST_ELEMENT, "qux", "cat", "dog"); 288 } 289 290 public void testConstrainedMultisetIllegal() { 291 Multiset<String> multiset = HashMultiset.create(asList("foo", "bar")); 292 Multiset<String> constrained = Constraints.constrainedMultiset( 293 multiset, TEST_CONSTRAINT); 294 try { 295 constrained.add(TEST_ELEMENT); 296 fail("TestElementException expected"); 297 } catch (TestElementException expected) {} 298 try { 299 constrained.add(TEST_ELEMENT, 2); 300 fail("TestElementException expected"); 301 } catch (TestElementException expected) {} 302 try { 303 constrained.addAll(asList("baz", TEST_ELEMENT)); 304 fail("TestElementException expected"); 305 } catch (TestElementException expected) {} 306 FluentAsserts.assertThat(constrained).has().allOf("foo", "bar"); 307 FluentAsserts.assertThat(multiset).has().allOf("foo", "bar"); 308 } 309 310 public void testNefariousAddAll() { 311 List<String> list = Lists.newArrayList("foo", "bar"); 312 List<String> constrained = Constraints.constrainedList( 313 list, TEST_CONSTRAINT); 314 Collection<String> onceIterable = onceIterableCollection("baz"); 315 constrained.addAll(onceIterable); 316 FluentAsserts.assertThat(constrained).has().allOf("foo", "bar", "baz").inOrder(); 317 FluentAsserts.assertThat(list).has().allOf("foo", "bar", "baz").inOrder(); 318 } 319 320 /** 321 * Returns a "nefarious" collection, which permits only one call to 322 * iterator(). This verifies that the constrained collection uses a defensive 323 * copy instead of potentially checking the elements in one snapshot and 324 * adding the elements from another. 325 * 326 * @param element the element to be contained in the collection 327 */ 328 static <E> Collection<E> onceIterableCollection(final E element) { 329 return new AbstractCollection<E>() { 330 boolean iteratorCalled; 331 @Override public int size() { 332 /* 333 * We could make the collection empty, but that seems more likely to 334 * trigger special cases (so maybe we should test both empty and 335 * nonempty...). 336 */ 337 return 1; 338 } 339 @Override public Iterator<E> iterator() { 340 assertFalse("Expected only one call to iterator()", iteratorCalled); 341 iteratorCalled = true; 342 return Collections.singleton(element).iterator(); 343 } 344 }; 345 } 346 347 @GwtIncompatible("SerializableTester") 348 public void testSerialization() { 349 // TODO: Test serialization of constrained collections. 350 assertSame(Constraints.notNull(), 351 SerializableTester.reserialize(Constraints.notNull())); 352 } 353} 354