/
githubmirror
/
guava
Обзор
Документация
Войти
/
githubmirror
/
guava
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
android/guava-tests/test/com/google/common/util/concurrent/AtomicDoubleArrayTest.java
332 строки
11 KB
cpovirk
Continue tearing out parts of `JSR166TestCase`.
26 июн 2026, 22:25
26 июн 2026, 22:25
942631f
Код
Авторство
О чём код?
/* * Written by Doug Lea and Martin Buchholz with assistance from * members of JCP JSR-166 Expert Group and released to the public * domain, as explained at * http://creativecommons.org/publicdomain/zero/1.0/ */ /* * Source: * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/test/tck-jsr166e/AtomicDoubleArrayTest.java?revision=1.13 * (Modified to adapt to guava coding conventions) */ package com.google.common.util.concurrent; import static com.google.common.testing.SerializableTester.reserialize; import static com.google.common.truth.Truth.assertThat; import static java.util.concurrent.Executors.newFixedThreadPool; import static org.junit.Assert.assertThrows; import com.google.common.annotations.GwtIncompatible; import com.google.common.annotations.J2ktIncompatible; import com.google.common.testing.NullPointerTester; import java.util.Arrays; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import org.jspecify.annotations.NullUnmarked; /** Unit test for {@link AtomicDoubleArray}. */ @NullUnmarked @GwtIncompatible @J2ktIncompatible public class AtomicDoubleArrayTest extends JSR166TestCase { private static final double[] VALUES = { Double.NEGATIVE_INFINITY, -Double.MAX_VALUE, (double) Long.MIN_VALUE, (double) Integer.MIN_VALUE, -Math.PI, -1.0, -Double.MIN_VALUE, -0.0, +0.0, Double.MIN_VALUE, 1.0, Math.PI, (double) Integer.MAX_VALUE, (double) Long.MAX_VALUE, Double.MAX_VALUE, Double.POSITIVE_INFINITY, Double.NaN, Float.MAX_VALUE, }; static void assertBitEquals(double x, double y) { assertEquals(Double.doubleToRawLongBits(x), Double.doubleToRawLongBits(y)); } public void testNulls() { new NullPointerTester().testAllPublicStaticMethods(AtomicDoubleArray.class); new NullPointerTester().testAllPublicConstructors(AtomicDoubleArray.class); new NullPointerTester().testAllPublicInstanceMethods(new AtomicDoubleArray(1)); } /** constructor creates array of given size with all elements zero */ public void testConstructor() { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int i = 0; i < SIZE; i++) { assertBitEquals(0.0, aa.get(i)); } } /** constructor with null array throws NPE */ public void testConstructor2NPE() { double[] a = null; assertThrows(NullPointerException.class, () -> new AtomicDoubleArray(a)); } /** constructor with array is of same size and has all elements */ public void testConstructor2() { AtomicDoubleArray aa = new AtomicDoubleArray(VALUES); assertEquals(VALUES.length, aa.length()); for (int i = 0; i < VALUES.length; i++) { assertBitEquals(VALUES[i], aa.get(i)); } } /** constructor with empty array has size 0 and contains no elements */ public void testConstructorEmptyArray() { AtomicDoubleArray aa = new AtomicDoubleArray(new double[0]); assertEquals(0, aa.length()); assertThrows(IndexOutOfBoundsException.class, () -> aa.get(0)); } /** constructor with length zero has size 0 and contains no elements */ public void testConstructorZeroLength() { AtomicDoubleArray aa = new AtomicDoubleArray(0); assertEquals(0, aa.length()); assertThrows(IndexOutOfBoundsException.class, () -> aa.get(0)); } /** get and set for out of bound indices throw IndexOutOfBoundsException */ public void testIndexing() { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int index : new int[] {-1, SIZE}) { assertThrows(IndexOutOfBoundsException.class, () -> aa.get(index)); assertThrows(IndexOutOfBoundsException.class, () -> aa.set(index, 1.0)); assertThrows(IndexOutOfBoundsException.class, () -> aa.lazySet(index, 1.0)); assertThrows(IndexOutOfBoundsException.class, () -> aa.compareAndSet(index, 1.0, 2.0)); assertThrows(IndexOutOfBoundsException.class, () -> aa.weakCompareAndSet(index, 1.0, 2.0)); assertThrows(IndexOutOfBoundsException.class, () -> aa.getAndAdd(index, 1.0)); assertThrows(IndexOutOfBoundsException.class, () -> aa.addAndGet(index, 1.0)); } } /** get returns the last value set at index */ public void testGetSet() { AtomicDoubleArray aa = new AtomicDoubleArray(VALUES.length); for (int i = 0; i < VALUES.length; i++) { assertBitEquals(0.0, aa.get(i)); aa.set(i, VALUES[i]); assertBitEquals(VALUES[i], aa.get(i)); aa.set(i, -3.0); assertBitEquals(-3.0, aa.get(i)); } } /** get returns the last value lazySet at index by same thread */ public void testGetLazySet() { AtomicDoubleArray aa = new AtomicDoubleArray(VALUES.length); for (int i = 0; i < VALUES.length; i++) { assertBitEquals(0.0, aa.get(i)); aa.lazySet(i, VALUES[i]); assertBitEquals(VALUES[i], aa.get(i)); aa.lazySet(i, -3.0); assertBitEquals(-3.0, aa.get(i)); } } /** compareAndSet succeeds in changing value if equal to expected else fails */ public void testCompareAndSet() { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int i : new int[] {0, SIZE - 1}) { double prev = 0.0; double unused = Math.E + Math.PI; for (double x : VALUES) { assertBitEquals(prev, aa.get(i)); assertFalse(aa.compareAndSet(i, unused, x)); assertBitEquals(prev, aa.get(i)); assertTrue(aa.compareAndSet(i, prev, x)); assertBitEquals(x, aa.get(i)); prev = x; } } } /** compareAndSet in one thread enables another waiting for value to succeed */ public void testCompareAndSetInMultipleThreads() { AtomicDoubleArray a = new AtomicDoubleArray(1); a.set(0, 1.0); @SuppressWarnings("ThreadPriorityCheck") // doing our best to test for races Thread t = newStartedThread( () -> { while (!a.compareAndSet(0, 2.0, 3.0)) { Thread.yield(); } }); assertTrue(a.compareAndSet(0, 1.0, 2.0)); awaitTermination(t); assertBitEquals(3.0, a.get(0)); } /** repeated weakCompareAndSet succeeds in changing value when equal to expected */ public void testWeakCompareAndSet() { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int i : new int[] {0, SIZE - 1}) { double prev = 0.0; double unused = Math.E + Math.PI; for (double x : VALUES) { assertBitEquals(prev, aa.get(i)); assertFalse(aa.weakCompareAndSet(i, unused, x)); assertBitEquals(prev, aa.get(i)); while (!aa.weakCompareAndSet(i, prev, x)) {} assertBitEquals(x, aa.get(i)); prev = x; } } } /** getAndSet returns previous value and sets to given value at given index */ public void testGetAndSet() { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int i : new int[] {0, SIZE - 1}) { double prev = 0.0; for (double x : VALUES) { assertBitEquals(prev, aa.getAndSet(i, x)); prev = x; } } } /** getAndAdd returns previous value and adds given value */ public void testGetAndAdd() { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int i : new int[] {0, SIZE - 1}) { for (double x : VALUES) { for (double y : VALUES) { aa.set(i, x); double z = aa.getAndAdd(i, y); assertBitEquals(x, z); assertBitEquals(x + y, aa.get(i)); } } } } /** addAndGet adds given value to current, and returns current value */ public void testAddAndGet() { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int i : new int[] {0, SIZE - 1}) { for (double x : VALUES) { for (double y : VALUES) { aa.set(i, x); double z = aa.addAndGet(i, y); assertBitEquals(x + y, z); assertBitEquals(x + y, aa.get(i)); } } } } private static final long COUNTDOWN = 100000; private static final class Counter implements Callable<Long> { final AtomicDoubleArray aa; Counter(AtomicDoubleArray a) { aa = a; } @Override public Long call() { long counts = 0; for (; ; ) { boolean done = true; for (int i = 0; i < aa.length(); i++) { double v = aa.get(i); assertThat(v).isAtLeast(0); if (v != 0) { done = false; if (aa.compareAndSet(i, v, v - 1.0)) { ++counts; } } } if (done) { return counts; } } } } /** * Multiple threads using same array of counters successfully update a number of times equal to * total count */ public void testCountingInMultipleThreads() throws Exception { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int i = 0; i < SIZE; i++) { aa.set(i, (double) COUNTDOWN); } ExecutorService executor = newFixedThreadPool(2); try { Future<Long> c1 = executor.submit(new Counter(aa)); Future<Long> c2 = executor.submit(new Counter(aa)); assertEquals(SIZE * COUNTDOWN, c1.get() + c2.get()); } finally { executor.shutdown(); } } /** a deserialized serialized array holds same values */ @SuppressWarnings("ReferenceEquality") public void testSerialization() { AtomicDoubleArray x = new AtomicDoubleArray(SIZE); for (int i = 0; i < SIZE; i++) { x.set(i, (double) -i); } AtomicDoubleArray y = reserialize(x); assertThat(y).isNotSameInstanceAs(x); assertEquals(x.length(), y.length()); for (int i = 0; i < SIZE; i++) { assertBitEquals(x.get(i), y.get(i)); } AtomicDoubleArray a = new AtomicDoubleArray(VALUES); AtomicDoubleArray b = reserialize(a); assertFalse(a.equals(b)); assertFalse(b.equals(a)); assertEquals(a.length(), b.length()); for (int i = 0; i < VALUES.length; i++) { assertBitEquals(a.get(i), b.get(i)); } } /** toString returns current value */ public void testToString() { AtomicDoubleArray aa = new AtomicDoubleArray(VALUES); assertThat(aa.toString()).isEqualTo(Arrays.toString(VALUES)); assertThat(new AtomicDoubleArray(0).toString()).isEqualTo("[]"); assertThat(new AtomicDoubleArray(new double[0]).toString()).isEqualTo("[]"); } /** compareAndSet treats +0.0 and -0.0 as distinct values */ public void testDistinctZeros() { AtomicDoubleArray aa = new AtomicDoubleArray(SIZE); for (int i : new int[] {0, SIZE - 1}) { assertFalse(aa.compareAndSet(i, -0.0, 7.0)); assertFalse(aa.weakCompareAndSet(i, -0.0, 7.0)); assertBitEquals(+0.0, aa.get(i)); assertTrue(aa.compareAndSet(i, +0.0, -0.0)); assertBitEquals(-0.0, aa.get(i)); assertFalse(aa.compareAndSet(i, +0.0, 7.0)); assertFalse(aa.weakCompareAndSet(i, +0.0, 7.0)); assertBitEquals(-0.0, aa.get(i)); } } }