Loading core/tests/coretests/src/com/android/internal/util/RateLimitingCacheTest.java +43 −29 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -43,7 +45,7 @@ public class RateLimitingCacheTest { @Before public void before() { mCounter = -1; mCounter = 0; } private final RateLimitingCache.ValueFetcher<Integer> mFetcher = () -> { Loading @@ -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); } /** Loading @@ -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); } /** Loading @@ -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); } /** Loading Loading @@ -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); } /** Loading Loading
core/tests/coretests/src/com/android/internal/util/RateLimitingCacheTest.java +43 −29 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -43,7 +45,7 @@ public class RateLimitingCacheTest { @Before public void before() { mCounter = -1; mCounter = 0; } private final RateLimitingCache.ValueFetcher<Integer> mFetcher = () -> { Loading @@ -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); } /** Loading @@ -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); } /** Loading @@ -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); } /** Loading Loading @@ -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); } /** Loading