11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.collect;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static java.util.Arrays.asList;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport static org.junit.contrib.truth.Truth.ASSERT;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtCompatible;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.GwtIncompatible;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.testing.SerializableTester;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport junit.framework.TestCase;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.AbstractCollection;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collections;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Iterator;
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.ListIterator;
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.RandomAccess;
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set;
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.SortedSet;
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Tests for {@code Constraints}.
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Mike Bostock
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Jared Levy
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@GwtCompatible(emulated = true)
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class ConstraintsTest extends TestCase {
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final String TEST_ELEMENT = "test";
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final class TestElementException
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      extends IllegalArgumentException {
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    private static final long serialVersionUID = 0;
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private static final Constraint<String> TEST_CONSTRAINT
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      = new Constraint<String>() {
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          @Override
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          public String checkElement(String element) {
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            if (TEST_ELEMENT.equals(element)) {
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              throw new TestElementException();
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            return element;
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          }
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        };
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testNotNull() {
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Constraint<? super String> constraint = Constraints.notNull();
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertSame(TEST_ELEMENT, constraint.checkElement(TEST_ELEMENT));
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constraint.checkElement(null);
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("NullPointerException expected");
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (NullPointerException expected) {}
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals("Not null", constraint.toString());
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedCollectionLegal() {
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Collection<String> collection = Lists.newArrayList("foo", "bar");
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Collection<String> constrained = Constraints.constrainedCollection(
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        collection, TEST_CONSTRAINT);
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    collection.add(TEST_ELEMENT);
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.add("qux");
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.addAll(asList("cat", "dog"));
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    /* equals and hashCode aren't defined for Collection */
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(collection).hasContentsInOrder("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog");
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog");
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedCollectionIllegal() {
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Collection<String> collection = Lists.newArrayList("foo", "bar");
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Collection<String> constrained = Constraints.constrainedCollection(
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        collection, TEST_CONSTRAINT);
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.add(TEST_ELEMENT);
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.addAll(asList("baz", TEST_ELEMENT));
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder("foo", "bar");
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(collection).hasContentsInOrder("foo", "bar");
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedSetLegal() {
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<String> set = Sets.newLinkedHashSet(asList("foo", "bar"));
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<String> constrained = Constraints.constrainedSet(set, TEST_CONSTRAINT);
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    set.add(TEST_ELEMENT);
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.add("qux");
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.addAll(asList("cat", "dog"));
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(set.equals(constrained));
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(constrained.equals(set));
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(set.toString(), constrained.toString());
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(set.hashCode(), constrained.hashCode());
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(set).hasContentsInOrder("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog");
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder("foo", "bar", TEST_ELEMENT, "qux", "cat", "dog");
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedSetIllegal() {
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<String> set = Sets.newLinkedHashSet(asList("foo", "bar"));
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<String> constrained = Constraints.constrainedSet(set, TEST_CONSTRAINT);
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.add(TEST_ELEMENT);
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.addAll(asList("baz", TEST_ELEMENT));
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder("foo", "bar");
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(set).hasContentsInOrder("foo", "bar");
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedSortedSetLegal() {
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SortedSet<String> sortedSet = Sets.newTreeSet(asList("foo", "bar"));
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SortedSet<String> constrained = Constraints.constrainedSortedSet(
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        sortedSet, TEST_CONSTRAINT);
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    sortedSet.add(TEST_ELEMENT);
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.add("qux");
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.addAll(asList("cat", "dog"));
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(sortedSet.equals(constrained));
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(constrained.equals(sortedSet));
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(sortedSet.toString(), constrained.toString());
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(sortedSet.hashCode(), constrained.hashCode());
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(sortedSet).hasContentsInOrder("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT);
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder("bar", "cat", "dog", "foo", "qux", TEST_ELEMENT);
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertNull(constrained.comparator());
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals("bar", constrained.first());
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(TEST_ELEMENT, constrained.last());
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedSortedSetIllegal() {
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SortedSet<String> sortedSet = Sets.newTreeSet(asList("foo", "bar"));
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    SortedSet<String> constrained = Constraints.constrainedSortedSet(
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        sortedSet, TEST_CONSTRAINT);
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.add(TEST_ELEMENT);
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.subSet("bar", "foo").add(TEST_ELEMENT);
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.headSet("bar").add(TEST_ELEMENT);
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.tailSet("foo").add(TEST_ELEMENT);
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.addAll(asList("baz", TEST_ELEMENT));
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder("bar", "foo");
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(sortedSet).hasContentsInOrder("bar", "foo");
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedListLegal() {
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<String> list = Lists.newArrayList("foo", "bar");
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<String> constrained = Constraints.constrainedList(
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        list, TEST_CONSTRAINT);
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    list.add(TEST_ELEMENT);
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.add("qux");
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.addAll(asList("cat", "dog"));
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.add(1, "cow");
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.addAll(4, asList("box", "fan"));
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.set(2, "baz");
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(list.equals(constrained));
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(constrained.equals(list));
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(list.toString(), constrained.toString());
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(list.hashCode(), constrained.hashCode());
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(list).hasContentsInOrder(
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog");
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder(
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "foo", "cow", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog");
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ListIterator<String> iterator = constrained.listIterator();
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    iterator.next();
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    iterator.set("sun");
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.listIterator(2).add("sky");
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(list).hasContentsInOrder(
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog");
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder(
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "sun", "cow", "sky", "baz", TEST_ELEMENT, "box", "fan", "qux", "cat", "dog");
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(constrained instanceof RandomAccess);
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedListRandomAccessFalse() {
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<String> list = Lists.newLinkedList(asList("foo", "bar"));
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<String> constrained = Constraints.constrainedList(
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        list, TEST_CONSTRAINT);
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    list.add(TEST_ELEMENT);
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.add("qux");
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertFalse(constrained instanceof RandomAccess);
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedListIllegal() {
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<String> list = Lists.newArrayList("foo", "bar");
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<String> constrained = Constraints.constrainedList(
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        list, TEST_CONSTRAINT);
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.add(TEST_ELEMENT);
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.listIterator().add(TEST_ELEMENT);
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.listIterator(1).add(TEST_ELEMENT);
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.listIterator().set(TEST_ELEMENT);
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.listIterator(1).set(TEST_ELEMENT);
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.subList(0, 1).add(TEST_ELEMENT);
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.add(1, TEST_ELEMENT);
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.set(1, TEST_ELEMENT);
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.addAll(asList("baz", TEST_ELEMENT));
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.addAll(1, asList("baz", TEST_ELEMENT));
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder("foo", "bar");
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(list).hasContentsInOrder("foo", "bar");
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedMultisetLegal() {
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Multiset<String> multiset = HashMultiset.create(asList("foo", "bar"));
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Multiset<String> constrained = Constraints.constrainedMultiset(
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        multiset, TEST_CONSTRAINT);
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    multiset.add(TEST_ELEMENT);
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.add("qux");
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.addAll(asList("cat", "dog"));
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.add("cow", 2);
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(multiset.equals(constrained));
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertTrue(constrained.equals(multiset));
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(multiset.toString(), constrained.toString());
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(multiset.hashCode(), constrained.hashCode());
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(multiset).hasContentsAnyOrder(
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "foo", "bar", TEST_ELEMENT, "qux", "cat", "dog", "cow", "cow");
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsAnyOrder(
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        "foo", "bar", TEST_ELEMENT, "qux", "cat", "dog", "cow", "cow");
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, constrained.count("foo"));
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(1, constrained.remove("foo", 3));
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertEquals(2, constrained.setCount("cow", 0));
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(multiset).hasContentsAnyOrder("bar", TEST_ELEMENT, "qux", "cat", "dog");
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsAnyOrder("bar", TEST_ELEMENT, "qux", "cat", "dog");
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testConstrainedMultisetIllegal() {
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Multiset<String> multiset = HashMultiset.create(asList("foo", "bar"));
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Multiset<String> constrained = Constraints.constrainedMultiset(
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        multiset, TEST_CONSTRAINT);
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.add(TEST_ELEMENT);
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.add(TEST_ELEMENT, 2);
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      constrained.addAll(asList("baz", TEST_ELEMENT));
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      fail("TestElementException expected");
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (TestElementException expected) {}
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsAnyOrder("foo", "bar");
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(multiset).hasContentsAnyOrder("foo", "bar");
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testNefariousAddAll() {
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<String> list = Lists.newArrayList("foo", "bar");
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    List<String> constrained = Constraints.constrainedList(
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        list, TEST_CONSTRAINT);
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Collection<String> onceIterable = onceIterableCollection("baz");
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    constrained.addAll(onceIterable);
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(constrained).hasContentsInOrder("foo", "bar", "baz");
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    ASSERT.that(list).hasContentsInOrder("foo", "bar", "baz");
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Returns a "nefarious" collection, which permits only one call to
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * iterator(). This verifies that the constrained collection uses a defensive
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * copy instead of potentially checking the elements in one snapshot and
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * adding the elements from another.
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param element the element to be contained in the collection
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static <E> Collection<E> onceIterableCollection(final E element) {
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new AbstractCollection<E>() {
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      boolean iteratorCalled;
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public int size() {
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        /*
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert         * We could make the collection empty, but that seems more likely to
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert         * trigger special cases (so maybe we should test both empty and
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert         * nonempty...).
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert         */
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return 1;
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      @Override public Iterator<E> iterator() {
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        assertFalse("Expected only one call to iterator()", iteratorCalled);
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        iteratorCalled = true;
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        return Collections.singleton(element).iterator();
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    };
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @GwtIncompatible("SerializableTester")
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void testSerialization() {
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // TODO: Test serialization of constrained collections.
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    assertSame(Constraints.notNull(),
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        SerializableTester.reserialize(Constraints.notNull()));
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
351