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 8c3c84f
Show file tree
Hide file tree
Showing 27 changed files with 87 additions and 45 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 @@ -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 @@ -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,23 @@ 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 != Weighers.random()) {
@SuppressWarnings({"rawtypes", "unchecked"})
int weight = ((Weigher) 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 @@ -67,7 +67,7 @@ public void concurrent_unbounded(LoadingCache<Int, Int> cache, CacheContext cont
}

@Test(dataProvider = "caches")
@CacheSpec(maximumSize = Maximum.FULL, weigher = {CacheWeigher.DISABLED, CacheWeigher.RANDOM},
@CacheSpec(maximumSize = Maximum.FULL, weigher = {CacheWeigher.RANDOM},
stats = Stats.DISABLED, population = Population.EMPTY, removalListener = Listener.DISABLED,
refreshAfterWrite = { Expire.DISABLED, Expire.ONE_MILLISECOND },
keys = ReferenceType.STRONG, values = ReferenceType.STRONG,
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 @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
import static com.github.benmanes.caffeine.testing.CollectionSubject.collection;
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.Map;

import org.jspecify.annotations.Nullable;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Range;
import com.google.common.truth.FailureMetadata;
Expand All @@ -34,9 +37,9 @@
*/
public class MapSubject extends com.google.common.truth.MapSubject {
@SuppressWarnings("ImmutableMemberCollection")
private final Map<?, ?> actual;
private final @Nullable Map<?, ?> actual;

public MapSubject(FailureMetadata metadata, Map<?, ?> subject) {
public MapSubject(FailureMetadata metadata, @Nullable Map<?, ?> subject) {
super(metadata, subject);
this.actual = subject;
}
Expand All @@ -56,29 +59,34 @@ public final void hasSize(long expectedSize) {

/** Fails if the map 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));
}

/** Fails if the map's size is not in {@code range}. */
public void hasSizeIn(Range<Integer> range) {
requireNonNull(actual);
check("size()").that(actual.size()).isIn(range);
}

/** Fails if the map does not contain the given keys, where duplicate keys are ignored. */
@CanIgnoreReturnValue
public Ordered containsExactlyKeys(Iterable<?> keys) {
requireNonNull(actual);
return check("containsKeys").that(actual.keySet())
.containsExactlyElementsIn(ImmutableSet.copyOf(keys));
}

/** Fails if the map does not contain the given value. */
public void containsValue(Object value) {
requireNonNull(actual);
check("containsValue").that(actual.values()).contains(value);
}

/** Fails if the map does contain the given value. */
public void doesNotContainValue(Object value) {
requireNonNull(actual);
check("containsValue").that(actual.values()).doesNotContain(value);
}

Expand All @@ -87,6 +95,7 @@ public void doesNotContainValue(Object value) {
* methods.
*/
public void isExhaustivelyEmpty() {
requireNonNull(actual);
isEqualTo(Map.of());
hasSize(0);
isEmpty();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[versions]
caffeine = "3.1.8"
junit = "5.11.3"
reactor = "3.7.0"
reactor = "3.7.1"
truth = "1.4.4"
versions = "0.51.0"

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-rc-1-bin.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Expand Down
2 changes: 1 addition & 1 deletion examples/coalescing-bulkloader-reactor/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
plugins {
id("com.gradle.develocity") version "3.18.2"
id("com.gradle.develocity") version "3.19"
id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.2"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-rc-1-bin.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
Expand Down
2 changes: 1 addition & 1 deletion examples/graal-native/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pluginManagement {
}
}
plugins {
id("com.gradle.develocity") version "3.18.2"
id("com.gradle.develocity") version "3.19"
id("com.gradle.common-custom-user-data-gradle-plugin") version "2.0.2"
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
Expand Down
Loading

0 comments on commit 8c3c84f

Please sign in to comment.