/
githubmirror
/
guava
Обзор
Документация
Войти
/
githubmirror
/
guava
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
android/guava-testlib/src/com/google/common/testing/RelationshipTester.java
170 строк
6 KB
cpovirk
Make nested package-private classes `final`.
09 авг 2025, 04:14
09 авг 2025, 04:14
ab2f614
Код
Авторство
О чём код?
/* * Copyright (C) 2011 The Guava Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.google.common.testing; import static com.google.common.base.Preconditions.checkNotNull; import com.google.common.annotations.GwtCompatible; import com.google.common.base.Equivalence; import com.google.common.collect.ImmutableList; import com.google.errorprone.annotations.CanIgnoreReturnValue; import java.util.ArrayList; import java.util.List; import junit.framework.AssertionFailedError; import org.jspecify.annotations.NullMarked; /** * Implementation helper for {@link EqualsTester} and {@link EquivalenceTester} that tests for * equivalence classes. * * @author Gregory Kick */ @GwtCompatible @NullMarked final class RelationshipTester<T> { interface ItemReporter { String reportItem(Item<?> item); } /** * A word about using {@link Equivalence}, which automatically checks for {@code null} and * identical inputs: This sounds like it ought to be a problem here, since the goals of this class * include testing that {@code equals()} is reflexive and is tolerant of {@code null}. However, * there's no problem. The reason: {@link EqualsTester} tests {@code null} and identical inputs * directly against {@code equals()} rather than through the {@code Equivalence}. */ private final Equivalence<? super T> equivalence; private final String relationshipName; private final String hashName; private final ItemReporter itemReporter; private final List<ImmutableList<T>> groups = new ArrayList<>(); RelationshipTester( Equivalence<? super T> equivalence, String relationshipName, String hashName, ItemReporter itemReporter) { this.equivalence = checkNotNull(equivalence); this.relationshipName = checkNotNull(relationshipName); this.hashName = checkNotNull(hashName); this.itemReporter = checkNotNull(itemReporter); } // TODO(cpovirk): should we reject null items, since the tests already check null automatically? @CanIgnoreReturnValue public RelationshipTester<T> addRelatedGroup(Iterable<? extends T> group) { groups.add(ImmutableList.copyOf(group)); return this; } public void test() { for (int groupNumber = 0; groupNumber < groups.size(); groupNumber++) { ImmutableList<T> group = groups.get(groupNumber); for (int itemNumber = 0; itemNumber < group.size(); itemNumber++) { // check related items in same group for (int relatedItemNumber = 0; relatedItemNumber < group.size(); relatedItemNumber++) { if (itemNumber != relatedItemNumber) { assertRelated(groupNumber, itemNumber, relatedItemNumber); } } // check unrelated items in all other groups for (int unrelatedGroupNumber = 0; unrelatedGroupNumber < groups.size(); unrelatedGroupNumber++) { if (groupNumber != unrelatedGroupNumber) { ImmutableList<T> unrelatedGroup = groups.get(unrelatedGroupNumber); for (int unrelatedItemNumber = 0; unrelatedItemNumber < unrelatedGroup.size(); unrelatedItemNumber++) { assertUnrelated(groupNumber, itemNumber, unrelatedGroupNumber, unrelatedItemNumber); } } } } } } private void assertRelated(int groupNumber, int itemNumber, int relatedItemNumber) { Item<T> itemInfo = getItem(groupNumber, itemNumber); Item<T> relatedInfo = getItem(groupNumber, relatedItemNumber); T item = itemInfo.value; T related = relatedInfo.value; assertWithTemplate( "$ITEM must be $RELATIONSHIP to $OTHER", itemInfo, relatedInfo, equivalence.equivalent(item, related)); int itemHash = equivalence.hash(item); int relatedHash = equivalence.hash(related); assertWithTemplate( "the $HASH (" + itemHash + ") of $ITEM must be equal to the $HASH (" + relatedHash + ") of $OTHER", itemInfo, relatedInfo, itemHash == relatedHash); } private void assertUnrelated( int groupNumber, int itemNumber, int unrelatedGroupNumber, int unrelatedItemNumber) { Item<T> itemInfo = getItem(groupNumber, itemNumber); Item<T> unrelatedInfo = getItem(unrelatedGroupNumber, unrelatedItemNumber); assertWithTemplate( "$ITEM must not be $RELATIONSHIP to $OTHER", itemInfo, unrelatedInfo, !equivalence.equivalent(itemInfo.value, unrelatedInfo.value)); } private void assertWithTemplate(String template, Item<T> item, Item<T> other, boolean condition) { if (!condition) { throw new AssertionFailedError( template .replace("$RELATIONSHIP", relationshipName) .replace("$HASH", hashName) .replace("$ITEM", itemReporter.reportItem(item)) .replace("$OTHER", itemReporter.reportItem(other))); } } private Item<T> getItem(int groupNumber, int itemNumber) { return new Item<>(groups.get(groupNumber).get(itemNumber), groupNumber, itemNumber); } static final class Item<T> { final T value; final int groupNumber; final int itemNumber; Item(T value, int groupNumber, int itemNumber) { this.value = value; this.groupNumber = groupNumber; this.itemNumber = itemNumber; } @Override public String toString() { return value + " [group " + (groupNumber + 1) + ", item " + (itemNumber + 1) + ']'; } } }