Skip to content

Commit

Permalink
enable nullaway on unit tests (wip)
Browse files Browse the repository at this point in the history
  • Loading branch information
ben-manes committed Dec 14, 2024
1 parent e512b50 commit 214888d
Show file tree
Hide file tree
Showing 29 changed files with 112 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3163,6 +3163,7 @@ <T> T expireAfterAccessOrder(boolean oldest, Function<@Nullable V, @Nullable V>
* @param mappingFunction the mapping function to compute a value
* @return the computed value
*/
@SuppressWarnings("NullAway")
<T> T snapshot(Iterable<Node<K, V>> iterable, Function<@Nullable V, @Nullable V> transformer,
Function<Stream<CacheEntry<K, V>>, T> mappingFunction) {
requireNonNull(mappingFunction);
Expand Down Expand Up @@ -4009,6 +4010,7 @@ static final class BoundedPolicy<K, V> implements Policy<K, V> {
@Override public @Nullable V getIfPresentQuietly(K key) {
return transformer.apply(cache.getIfPresentQuietly(key));
}
@SuppressWarnings("NullAway")
@Override public @Nullable CacheEntry<K, V> getEntryIfPresentQuietly(K key) {
Node<K, V> node = cache.data.get(cache.nodeFactory.newLookupKey(key));
return (node == null) ? null : cache.nodeToCacheEntry(node, transformer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -998,8 +998,13 @@ public void evict_retired_victim(BoundedLocalCache<Int, Int> cache, CacheContext

@Test(dataProvider = "caches")
@CacheSpec(compute = Compute.SYNC, population = Population.EMPTY,
maximumSize = Maximum.FULL, weigher = CacheWeigher.VALUE)
maximumSize = Maximum.FULL, weigher = CacheWeigher.MOCKITO)
public void evict_zeroWeight_candidate(BoundedLocalCache<Int, Int> cache, CacheContext context) {
when(context.weigher().weigh(any(), any())).thenAnswer(invocation -> {
Int value = invocation.getArgument(1);
return Math.abs(value.intValue());
});

for (int i = 0; i < context.maximumSize(); i++) {
assertThat(cache.put(Int.valueOf(i), Int.valueOf(1))).isNull();
}
Expand All @@ -1019,8 +1024,13 @@ public void evict_zeroWeight_candidate(BoundedLocalCache<Int, Int> cache, CacheC

@Test(dataProvider = "caches")
@CacheSpec(compute = Compute.SYNC, population = Population.EMPTY,
maximumSize = Maximum.FULL, weigher = CacheWeigher.VALUE)
maximumSize = Maximum.FULL, weigher = CacheWeigher.MOCKITO)
public void evict_zeroWeight_victim(BoundedLocalCache<Int, Int> cache, CacheContext context) {
when(context.weigher().weigh(any(), any())).thenAnswer(invocation -> {
Int value = invocation.getArgument(1);
return Math.abs(value.intValue());
});

for (int i = 0; i < context.maximumSize(); i++) {
assertThat(cache.put(Int.valueOf(i), Int.valueOf(1))).isNull();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
package com.github.benmanes.caffeine.cache;

import static com.google.common.truth.Truth.assertAbout;
import static java.util.Objects.requireNonNull;

import java.util.Iterator;

import org.jspecify.annotations.Nullable;

import com.github.benmanes.caffeine.testing.CollectionSubject;
import com.google.common.collect.Sets;
import com.google.common.truth.FailureMetadata;
Expand All @@ -29,10 +32,10 @@
* @author [email protected] (Ben Manes)
*/
final class LinkedDequeSubject extends CollectionSubject {
private final LinkedDeque<Object> actual;
private final @Nullable LinkedDeque<Object> actual;

@SuppressWarnings("unchecked")
private LinkedDequeSubject(FailureMetadata metadata, LinkedDeque<?> subject) {
private LinkedDequeSubject(FailureMetadata metadata, @Nullable LinkedDeque<?> subject) {
super(metadata, subject);
this.actual = (LinkedDeque<Object>) subject;
}
Expand All @@ -46,6 +49,7 @@ public static LinkedDequeSubject assertThat(LinkedDeque<?> actual) {
}

public void isValid() {
requireNonNull(actual);
if (actual.isEmpty()) {
isExhaustivelyEmpty();
}
Expand All @@ -65,6 +69,7 @@ private void checkIterator(Iterator<?> iterator) {
}

private void checkElement(Object element) {
requireNonNull(actual);
var first = actual.peekFirst();
var last = actual.peekLast();
if (element == first) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
import static com.github.benmanes.caffeine.testing.Awaits.await;
import static com.github.benmanes.caffeine.testing.MapSubject.map;
import static com.google.common.truth.Truth.assertThat;
import static java.util.Objects.requireNonNull;

import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.jspecify.annotations.Nullable;

import com.github.benmanes.caffeine.cache.Async.AsyncWeigher;
import com.github.benmanes.caffeine.cache.BoundedLocalCache.BoundedLocalAsyncCache;
import com.github.benmanes.caffeine.cache.BoundedLocalCache.BoundedLocalAsyncLoadingCache;
Expand All @@ -38,7 +41,7 @@
import com.github.benmanes.caffeine.cache.UnboundedLocalCache.UnboundedLocalAsyncLoadingCache;
import com.github.benmanes.caffeine.cache.UnboundedLocalCache.UnboundedLocalManualCache;
import com.github.benmanes.caffeine.cache.stats.StatsCounter;
import com.github.benmanes.caffeine.cache.testing.Weighers;
import com.github.benmanes.caffeine.cache.testing.Weighers.SkippedWeigher;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Sets;
import com.google.common.truth.FailureMetadata;
Expand All @@ -52,9 +55,9 @@
*/
@SuppressWarnings("GuardedBy")
public final class LocalCacheSubject extends Subject {
private final Object actual;
private final @Nullable Object actual;

private LocalCacheSubject(FailureMetadata metadata, Object subject) {
private LocalCacheSubject(FailureMetadata metadata, @Nullable Object subject) {
super(metadata, subject);
this.actual = subject;
}
Expand All @@ -73,6 +76,7 @@ private LocalCacheSubject(FailureMetadata metadata, Object subject) {

@SuppressWarnings({"rawtypes", "unchecked"})
public void isValid() {
requireNonNull(actual);
if (actual instanceof BoundedLocalCache<?, ?>) {
var bounded = (BoundedLocalCache<Object, Object>) actual;
checkBounded(bounded);
Expand Down Expand Up @@ -298,11 +302,12 @@ private void checkLinks(BoundedLocalCache<Object, Object> bounded,
long totalWeightedSize = 0;
Set<Node<Object, Object>> seen = Sets.newIdentityHashSet();
for (var cell : deques.cellSet()) {
long weightedSize = scanLinks(bounded, cell.getValue(), seen);
check("%s: %s in %s", cell.getRowKey(), cell.getValue(), bounded.data)
var deque = requireNonNull(cell.getValue());
long weightedSize = scanLinks(bounded, deque, seen);
check("%s: %s in %s", cell.getRowKey(), deque, bounded.data)
.that(weightedSize).isEqualTo(cell.getColumnKey());
totalSize += cell.getValue().size();
totalWeightedSize += weightedSize;
totalSize += deque.size();
}
check("linkSize").withMessage("cache.size() != links").that(bounded).hasSize(seen.size());
check("totalSize").withMessage("cache.size() == deque.size()").that(bounded).hasSize(totalSize);
Expand Down Expand Up @@ -354,7 +359,7 @@ private void checkNode(BoundedLocalCache<Object, Object> bounded, Node<Object, O
}

private void checkKey(BoundedLocalCache<Object, Object> bounded,
Node<Object, Object> node, Object key, Object value) {
Node<Object, Object> node, @Nullable Object key, @Nullable Object value) {
if (bounded.collectKeys()) {
if ((key != null) && (value != null)) {
check("bounded").that(bounded).containsKey(key);
Expand All @@ -368,18 +373,19 @@ private void checkKey(BoundedLocalCache<Object, Object> bounded,
}

private void checkValue(BoundedLocalCache<Object, Object> bounded,
Node<Object, Object> node, Object key, Object value) {
Node<Object, Object> node, @Nullable Object key, @Nullable Object value) {
if (!bounded.collectValues()) {
check("value").that(value).isNotNull();
if ((key != null) && !bounded.hasExpired(node, bounded.expirationTicker().read())) {
requireNonNull(value);
check("containsValue(value) for key %s", key)
.about(map()).that(bounded).containsValue(value);
}
}
checkIfAsyncValue(value);
}

private void checkIfAsyncValue(Object value) {
private void checkIfAsyncValue(@Nullable Object value) {
if (value instanceof CompletableFuture<?>) {
var future = (CompletableFuture<?>) value;
if (!future.isDone() || future.isCompletedExceptionally()) {
Expand All @@ -390,18 +396,22 @@ private void checkIfAsyncValue(Object value) {
}

private void checkWeight(BoundedLocalCache<Object, Object> bounded,
Node<Object, Object> node, Object key, Object value) {
Node<Object, Object> node, @Nullable Object key, @Nullable Object value) {
check("node.getWeight").that(node.getWeight()).isAtLeast(0);
if ((key == null) || (value == null)) {
return;
}

var weigher = bounded.weigher;
boolean canCheckWeight = (weigher == Weighers.random());
Weigher<?, ?> weigher = bounded.weigher;
if (weigher instanceof AsyncWeigher) {
@SuppressWarnings("rawtypes")
var asyncWeigher = (AsyncWeigher) weigher;
canCheckWeight = (asyncWeigher.delegate == Weighers.random());
weigher = ((AsyncWeigher<?, ?>) weigher).delegate;
}
if (weigher instanceof BoundedWeigher) {
weigher = ((BoundedWeigher<?, ?>) weigher).delegate;
}
if (canCheckWeight) {
check("node.getWeight()").that(node.getWeight()).isEqualTo(weigher.weigh(key, value));
if (!(weigher instanceof SkippedWeigher)) {
int weight = bounded.weigher.weigh(key, value);
check("node.getWeight()").that(node.getWeight()).isEqualTo(weight);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ public void disabledFuture_null() {
/* --------------- guarded --------------- */

@Test
@SuppressWarnings("NullAway")
public void guardedScheduler_null() {
assertThrows(NullPointerException.class, () -> Scheduler.guardedScheduler(null));
}
Expand Down Expand Up @@ -166,6 +167,7 @@ public void guardedScheduler_exception() {
/* --------------- ScheduledExecutorService --------------- */

@Test
@SuppressWarnings("NullAway")
public void scheduledExecutorService_null() {
assertThrows(NullPointerException.class, () -> Scheduler.forScheduledExecutorService(null));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.github.benmanes.caffeine.cache.Scheduler;
import com.github.benmanes.caffeine.cache.Weigher;
import com.github.benmanes.caffeine.cache.testing.RemovalListeners.ConsumingRemovalListener;
import com.github.benmanes.caffeine.cache.testing.Weighers.SkippedWeigher;
import com.github.benmanes.caffeine.testing.ConcurrentTestHarness;
import com.github.benmanes.caffeine.testing.Int;
import com.google.common.collect.Maps;
Expand Down Expand Up @@ -198,12 +199,18 @@ enum CacheWeigher {
VALUE(() -> (key, value) -> Math.abs(((Int) value).intValue())),
/** A flag indicating that the entry is weighted by the value's collection size. */
COLLECTION(() -> (key, value) -> ((Collection<?>) value).size()),
/** A flag indicating that the entry's weight is randomly changing. */
/**
* A flag indicating that the entry's weight is randomly changing and is skipped by automatic
* validation checks.
*/
RANDOM(Weighers::random),
/** A flag indicating that the entry's weight records interactions. */
/**
* A flag indicating that the entry's weight records interactions and is skipped by automatic
* automatic validation checks.
*/
@SuppressWarnings("unchecked")
MOCKITO(() -> {
Weigher<Object, Object> weigher = Mockito.mock();
SkippedWeigher<Object, Object> weigher = Mockito.mock();
when(weigher.weigh(any(), any())).thenReturn(1);
return weigher;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public static <K, V> Weigher<K, V> random() {
return (Weigher<K, V>) RandomWeigher.INSTANCE;
}

/** A marker to instruct the validation to not check the entry's weight for data consistency. */
public interface SkippedWeigher<K, V> extends Weigher<K, V> {}

static final class ConstantWeigher<K, V> implements Weigher<K, V>, Serializable {
private static final long serialVersionUID = 1L;

Expand All @@ -57,7 +60,7 @@ static final class ConstantWeigher<K, V> implements Weigher<K, V>, Serializable
}
}

enum RandomWeigher implements Weigher<Object, Object> {
enum RandomWeigher implements SkippedWeigher<Object, Object> {
INSTANCE;

@Override public int weigh(Object key, Object value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.collections.impl.list.Interval;
import org.eclipse.collections.impl.parallel.ParallelIterate;
import org.eclipse.collections.impl.test.Verify;
import org.jspecify.annotations.NullUnmarked;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
Expand All @@ -35,6 +36,7 @@
*
* Ported from Eclipse Collections 11.0.
*/
@NullUnmarked
@SuppressWarnings("CanIgnoreReturnValueSuggester")
public abstract class ConcurrentHashMapAcceptanceTest {
private ExecutorService executor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.truth.Truth.assertAbout;
import static java.util.Objects.requireNonNull;

import java.util.Collection;
import java.util.Deque;
Expand All @@ -25,6 +26,8 @@
import java.util.Queue;
import java.util.Set;

import org.jspecify.annotations.Nullable;

import com.google.common.truth.FailureMetadata;
import com.google.common.truth.IterableSubject;

Expand All @@ -34,9 +37,9 @@
* @author [email protected] (Ben Manes)
*/
public class CollectionSubject extends IterableSubject {
private final Collection<?> actual;
private final @Nullable Collection<?> actual;

public CollectionSubject(FailureMetadata metadata, Collection<?> subject) {
public CollectionSubject(FailureMetadata metadata, @Nullable Collection<?> subject) {
super(metadata, subject);
this.actual = subject;
}
Expand All @@ -56,6 +59,7 @@ public final void hasSize(long expectedSize) {

/** Fails if the collection does not have less than the given size. */
public void hasSizeLessThan(long other) {
requireNonNull(actual);
checkArgument(other >= 0, "expectedSize (%s) must be >= 0", other);
check("size()").that(actual.size()).isLessThan(Math.toIntExact(other));
}
Expand All @@ -68,6 +72,7 @@ public void hasSizeLessThan(long other) {
public void isExhaustivelyEmpty() {
checkIterable();
checkCollection();
requireNonNull(actual);
if (actual instanceof Set<?>) {
checkSet((Set<?>) actual);
}
Expand All @@ -83,11 +88,13 @@ public void isExhaustivelyEmpty() {
}

private void checkIterable() {
requireNonNull(actual);
check("iterator().hasNext()").that(actual.iterator().hasNext()).isFalse();
}

@SuppressWarnings("CollectionToArray")
private void checkCollection() {
requireNonNull(actual);
check("size()").that(actual).hasSize(0);
check("isEmpty()").that(actual).isEmpty();
check("toArray()").that(actual.toArray()).isEmpty();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Objects;
import java.util.function.Predicate;

import org.jspecify.annotations.Nullable;
import org.slf4j.event.Level;

import com.github.valfirst.slf4jtest.LoggingEvent;
Expand All @@ -43,7 +44,8 @@ public final class LoggingEvents extends ForwardingList<LoggingEvent> {
private final List<Predicate<LoggingEvent>> predicates;
private final ImmutableList<LoggingEvent> events;

private ImmutableList<LoggingEvent> filteredEvents;
private @Nullable ImmutableList<LoggingEvent> filteredEvents;

private boolean exclusive;

private LoggingEvents(Iterable<LoggingEvent> events) {
Expand Down
Loading

0 comments on commit 214888d

Please sign in to comment.