• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2011 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 
17 package com.google.common.testing;
18 
19 import static com.google.common.base.Preconditions.checkNotNull;
20 
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.collect.ImmutableList;
23 import com.google.common.collect.Lists;
24 
25 import junit.framework.AssertionFailedError;
26 
27 import java.util.List;
28 
29 /**
30  * Tests a collection of objects according to the rules specified in a
31  * {@link RelationshipAssertion}.
32  *
33  * @author Gregory Kick
34  */
35 @GwtCompatible
36 final class RelationshipTester<T> {
37   private final List<ImmutableList<T>> groups = Lists.newArrayList();
38   private final RelationshipAssertion<T> assertion;
39 
RelationshipTester(RelationshipAssertion<T> assertion)40   RelationshipTester(RelationshipAssertion<T> assertion) {
41     this.assertion = checkNotNull(assertion);
42   }
43 
addRelatedGroup(Iterable<? extends T> group)44   public RelationshipTester<T> addRelatedGroup(Iterable<? extends T> group) {
45     groups.add(ImmutableList.copyOf(group));
46     return this;
47   }
48 
test()49   public void test() {
50     for (int groupNumber = 0; groupNumber < groups.size(); groupNumber++) {
51       ImmutableList<T> group = groups.get(groupNumber);
52       for (int itemNumber = 0; itemNumber < group.size(); itemNumber++) {
53         // check related items in same group
54         for (int relatedItemNumber = 0; relatedItemNumber < group.size(); relatedItemNumber++) {
55           if (itemNumber != relatedItemNumber) {
56             assertRelated(groupNumber, itemNumber, relatedItemNumber);
57           }
58         }
59         // check unrelated items in all other groups
60         for (int unrelatedGroupNumber = 0; unrelatedGroupNumber < groups.size();
61             unrelatedGroupNumber++) {
62           if (groupNumber != unrelatedGroupNumber) {
63             ImmutableList<T> unrelatedGroup = groups.get(unrelatedGroupNumber);
64             for (int unrelatedItemNumber = 0; unrelatedItemNumber < unrelatedGroup.size();
65                 unrelatedItemNumber++) {
66               assertUnrelated(groupNumber, itemNumber, unrelatedGroupNumber, unrelatedItemNumber);
67             }
68           }
69         }
70       }
71     }
72   }
73 
assertRelated(int groupNumber, int itemNumber, int relatedItemNumber)74   private void assertRelated(int groupNumber, int itemNumber, int relatedItemNumber) {
75     ImmutableList<T> group = groups.get(groupNumber);
76     T item = group.get(itemNumber);
77     T related = group.get(relatedItemNumber);
78     try {
79       assertion.assertRelated(item, related);
80     } catch (AssertionFailedError e) {
81       // TODO(gak): special handling for ComparisonFailure?
82       throw new AssertionFailedError(e.getMessage()
83           .replace("$ITEM", itemString(item, groupNumber, itemNumber))
84           .replace("$RELATED", itemString(related, groupNumber, relatedItemNumber)));
85     }
86   }
87 
assertUnrelated(int groupNumber, int itemNumber, int unrelatedGroupNumber, int unrelatedItemNumber)88   private void assertUnrelated(int groupNumber, int itemNumber, int unrelatedGroupNumber,
89       int unrelatedItemNumber) {
90     T item = groups.get(groupNumber).get(itemNumber);
91     T unrelated = groups.get(unrelatedGroupNumber).get(unrelatedItemNumber);
92     try {
93       assertion.assertUnrelated(item, unrelated);
94     } catch (AssertionFailedError e) {
95       // TODO(gak): special handling for ComparisonFailure?
96       throw new AssertionFailedError(e.getMessage()
97           .replace("$ITEM", itemString(item, groupNumber, itemNumber))
98           .replace("$UNRELATED", itemString(unrelated, unrelatedGroupNumber, unrelatedItemNumber)));
99     }
100   }
101 
itemString(Object item, int groupNumber, int itemNumber)102   private static String itemString(Object item, int groupNumber, int itemNumber) {
103     return new StringBuilder()
104         .append(item)
105         .append(" [group ")
106         .append(groupNumber + 1)
107         .append(", item ")
108         .append(itemNumber + 1)
109         .append(']')
110         .toString();
111   }
112 
113   /**
114    * A strategy for testing the relationship between objects.  Methods are expected to throw
115    * {@link AssertionFailedError} whenever the relationship is violated.
116    *
117    * <p>As a convenience, any occurrence of {@code $ITEM}, {@code $RELATED} or {@code $UNRELATED} in
118    * the error message will be replaced with a string that combines the {@link Object#toString()},
119    * item number and group number of the respective item.
120    *
121    */
122   interface RelationshipAssertion<T> {
assertRelated(T item, T related)123     void assertRelated(T item, T related);
124 
assertUnrelated(T item, T unrelated)125     void assertUnrelated(T item, T unrelated);
126   }
127 }
128