Coverage Summary for Class: RelationshipTester (com.google.common.testing)

Class Method, % Line, %
RelationshipTester 100% (7/7) 100% (48/48)
RelationshipTester$Item 100% (2/2) 100% (6/6)
RelationshipTester$ItemReporter 100% (2/2) 100% (2/2)
Total 100% (11/11) 100% (56/56)


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.base.Equivalence; 23 import com.google.common.collect.ImmutableList; 24 import com.google.common.collect.Lists; 25 import java.util.List; 26 import junit.framework.AssertionFailedError; 27  28 /** 29  * Implementation helper for {@link EqualsTester} and {@link EquivalenceTester} that tests for 30  * equivalence classes. 31  * 32  * @author Gregory Kick 33  */ 34 @GwtCompatible 35 final class RelationshipTester<T> { 36  37  static class ItemReporter { 38  String reportItem(Item<?> item) { 39  return item.toString(); 40  } 41  } 42  43  /** 44  * A word about using {@link Equivalence}, which automatically checks for {@code null} and 45  * identical inputs: This sounds like it ought to be a problem here, since the goals of this class 46  * include testing that {@code equals()} is reflexive and is tolerant of {@code null}. However, 47  * there's no problem. The reason: {@link EqualsTester} tests {@code null} and identical inputs 48  * directly against {@code equals()} rather than through the {@code Equivalence}. 49  */ 50  private final Equivalence<? super T> equivalence; 51  52  private final String relationshipName; 53  private final String hashName; 54  private final ItemReporter itemReporter; 55  private final List<ImmutableList<T>> groups = Lists.newArrayList(); 56  57  RelationshipTester( 58  Equivalence<? super T> equivalence, 59  String relationshipName, 60  String hashName, 61  ItemReporter itemReporter) { 62  this.equivalence = checkNotNull(equivalence); 63  this.relationshipName = checkNotNull(relationshipName); 64  this.hashName = checkNotNull(hashName); 65  this.itemReporter = checkNotNull(itemReporter); 66  } 67  68  // TODO(cpovirk): should we reject null items, since the tests already check null automatically? 69  public RelationshipTester<T> addRelatedGroup(Iterable<? extends T> group) { 70  groups.add(ImmutableList.copyOf(group)); 71  return this; 72  } 73  74  public void test() { 75  for (int groupNumber = 0; groupNumber < groups.size(); groupNumber++) { 76  ImmutableList<T> group = groups.get(groupNumber); 77  for (int itemNumber = 0; itemNumber < group.size(); itemNumber++) { 78  // check related items in same group 79  for (int relatedItemNumber = 0; relatedItemNumber < group.size(); relatedItemNumber++) { 80  if (itemNumber != relatedItemNumber) { 81  assertRelated(groupNumber, itemNumber, relatedItemNumber); 82  } 83  } 84  // check unrelated items in all other groups 85  for (int unrelatedGroupNumber = 0; 86  unrelatedGroupNumber < groups.size(); 87  unrelatedGroupNumber++) { 88  if (groupNumber != unrelatedGroupNumber) { 89  ImmutableList<T> unrelatedGroup = groups.get(unrelatedGroupNumber); 90  for (int unrelatedItemNumber = 0; 91  unrelatedItemNumber < unrelatedGroup.size(); 92  unrelatedItemNumber++) { 93  assertUnrelated(groupNumber, itemNumber, unrelatedGroupNumber, unrelatedItemNumber); 94  } 95  } 96  } 97  } 98  } 99  } 100  101  private void assertRelated(int groupNumber, int itemNumber, int relatedItemNumber) { 102  Item<T> itemInfo = getItem(groupNumber, itemNumber); 103  Item<T> relatedInfo = getItem(groupNumber, relatedItemNumber); 104  105  T item = itemInfo.value; 106  T related = relatedInfo.value; 107  assertWithTemplate( 108  "$ITEM must be $RELATIONSHIP to $OTHER", 109  itemInfo, 110  relatedInfo, 111  equivalence.equivalent(item, related)); 112  113  int itemHash = equivalence.hash(item); 114  int relatedHash = equivalence.hash(related); 115  assertWithTemplate( 116  "the $HASH (" 117  + itemHash 118  + ") of $ITEM must be equal to the $HASH (" 119  + relatedHash 120  + ") of $OTHER", 121  itemInfo, 122  relatedInfo, 123  itemHash == relatedHash); 124  } 125  126  private void assertUnrelated( 127  int groupNumber, int itemNumber, int unrelatedGroupNumber, int unrelatedItemNumber) { 128  Item<T> itemInfo = getItem(groupNumber, itemNumber); 129  Item<T> unrelatedInfo = getItem(unrelatedGroupNumber, unrelatedItemNumber); 130  131  assertWithTemplate( 132  "$ITEM must not be $RELATIONSHIP to $OTHER", 133  itemInfo, 134  unrelatedInfo, 135  !equivalence.equivalent(itemInfo.value, unrelatedInfo.value)); 136  } 137  138  private void assertWithTemplate(String template, Item<T> item, Item<T> other, boolean condition) { 139  if (!condition) { 140  throw new AssertionFailedError( 141  template 142  .replace("$RELATIONSHIP", relationshipName) 143  .replace("$HASH", hashName) 144  .replace("$ITEM", itemReporter.reportItem(item)) 145  .replace("$OTHER", itemReporter.reportItem(other))); 146  } 147  } 148  149  private Item<T> getItem(int groupNumber, int itemNumber) { 150  return new Item<T>(groups.get(groupNumber).get(itemNumber), groupNumber, itemNumber); 151  } 152  153  static final class Item<T> { 154  final T value; 155  final int groupNumber; 156  final int itemNumber; 157  158  Item(T value, int groupNumber, int itemNumber) { 159  this.value = value; 160  this.groupNumber = groupNumber; 161  this.itemNumber = itemNumber; 162  } 163  164  @Override 165  public String toString() { 166  return value + " [group " + (groupNumber + 1) + ", item " + (itemNumber + 1) + ']'; 167  } 168  } 169 }