Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22e6a226 authored by Shai Barack's avatar Shai Barack Committed by Android (Google) Code Review
Browse files

Merge "Relax test assertion in intrinsically racy concurrency test" into main

parents 6da6b524 5817192b
Loading
Loading
Loading
Loading
+43 −29
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@ import android.platform.test.annotations.Presubmit;

import androidx.test.runner.AndroidJUnit4;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
@@ -43,7 +45,7 @@ public class RateLimitingCacheTest {

    @Before
    public void before() {
        mCounter = -1;
        mCounter = 0;
    }

    private final RateLimitingCache.ValueFetcher<Integer> mFetcher = () -> {
@@ -59,12 +61,12 @@ public class RateLimitingCacheTest {
        TestRateLimitingCache<Integer> s = new TestRateLimitingCache<>(0);

        int first = s.get(mFetcher);
        assertEquals(0, first);
        assertEquals(1, first);
        int second = s.get(mFetcher);
        assertEquals(1, second);
        assertEquals(2, second);
        s.advanceTime(20);
        int third = s.get(mFetcher);
        assertEquals(2, third);
        assertEquals(3, third);
    }

    /**
@@ -76,17 +78,17 @@ public class RateLimitingCacheTest {
        TestRateLimitingCache<Integer> s = new TestRateLimitingCache<>(100);

        int first = s.get(mFetcher);
        assertEquals(0, first);
        assertEquals(1, first);
        int second = s.get(mFetcher);
        // Too early to change
        assertEquals(0, second);
        assertEquals(1, second);
        s.advanceTime(150);
        int third = s.get(mFetcher);
        // Changed by now
        assertEquals(1, third);
        assertEquals(2, third);
        int fourth = s.get(mFetcher);
        // Too early to change again
        assertEquals(1, fourth);
        assertEquals(2, fourth);
    }

    /**
@@ -98,11 +100,11 @@ public class RateLimitingCacheTest {
        TestRateLimitingCache<Integer> s = new TestRateLimitingCache<>(-1);

        int first = s.get(mFetcher);
        assertEquals(0, first);
        assertEquals(1, first);
        s.advanceTime(200);
        // Should return the original value every time
        int second = s.get(mFetcher);
        assertEquals(0, second);
        assertEquals(1, second);
    }

    /**
@@ -132,32 +134,44 @@ public class RateLimitingCacheTest {
     */
    @Test
    public void testMultipleThreads() throws InterruptedException {
        final long periodMillis = 1000;
        // Definitely won't have more than one period elapsed during the test.
        final long periodMillis = 1_000 * 60 * 10;  // 10 minutes
        final int maxCountPerPeriod = 10;
        final RateLimitingCache<Integer> s =
                new RateLimitingCache<>(periodMillis, maxCountPerPeriod);

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
        final int maxIncrementsPerWorker = 1_000;
        Runnable work = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < maxIncrementsPerWorker; i++) {
                    s.get(mFetcher);
                }
        });
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                s.get(mFetcher);
            }
        });
        };

        final long startTimeMillis = SystemClock.elapsedRealtime();
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        final long endTimeMillis = SystemClock.elapsedRealtime();
        final int numWorkers = 5;
        List<Thread> workers = new ArrayList<>(numWorkers);
        for (int i = 0; i < numWorkers; i++) {
            workers.add(new Thread(work));
        }
        for (Thread worker : workers) {
            worker.start();
        }
        for (Thread worker : workers) {
            worker.join();
        }

        final long periodsElapsed = 1 + ((endTimeMillis - startTimeMillis) / periodMillis);
        final long expected = Math.min(100 + 100, periodsElapsed * maxCountPerPeriod) - 1;
        assertEquals(expected, mCounter);
        final long expectedAtMost =
                Math.min(
                        // No more than the max increments that each worker can do
                        // times the number of workers
                        maxIncrementsPerWorker * numWorkers,
                        // Workers may race and get at most one more increment each
                        maxCountPerPeriod + numWorkers);
        assertTrue(
                "mCounter should be <=" + expectedAtMost + " but was " + mCounter,
                mCounter <= expectedAtMost);
    }

    /**