Merge "Clean-up PersisterQueue tests" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
33f68ebf93
@@ -39,7 +39,6 @@ import java.util.List;
|
|||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build/Install/Run:
|
* Build/Install/Run:
|
||||||
@@ -47,208 +46,222 @@ import java.util.function.Predicate;
|
|||||||
*/
|
*/
|
||||||
@MediumTest
|
@MediumTest
|
||||||
@Presubmit
|
@Presubmit
|
||||||
public class PersisterQueueTests implements PersisterQueue.Listener {
|
public class PersisterQueueTests {
|
||||||
private static final long INTER_WRITE_DELAY_MS = 50;
|
private static final long INTER_WRITE_DELAY_MS = 50;
|
||||||
private static final long PRE_TASK_DELAY_MS = 300;
|
private static final long PRE_TASK_DELAY_MS = 300;
|
||||||
// We allow at most 1s more than the expected timeout.
|
// We allow at most 0.2s more than the expected timeout.
|
||||||
private static final long TIMEOUT_ALLOWANCE = 100;
|
private static final long TIMEOUT_ALLOWANCE = 200;
|
||||||
|
|
||||||
private static final Predicate<MatchingTestItem> TEST_ITEM_PREDICATE = item -> item.mMatching;
|
|
||||||
|
|
||||||
private AtomicInteger mItemCount;
|
|
||||||
private CountDownLatch mSetUpLatch;
|
|
||||||
private volatile CountDownLatch mLatch;
|
|
||||||
private List<Boolean> mProbablyDoneResults;
|
|
||||||
|
|
||||||
private final PersisterQueue mTarget =
|
private final PersisterQueue mTarget =
|
||||||
new PersisterQueue(INTER_WRITE_DELAY_MS, PRE_TASK_DELAY_MS);
|
new PersisterQueue(INTER_WRITE_DELAY_MS, PRE_TASK_DELAY_MS);
|
||||||
|
|
||||||
|
private TestPersisterQueueListener mListener;
|
||||||
|
private TestWriteQueueItemFactory mFactory;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
mItemCount = new AtomicInteger(0);
|
mListener = new TestPersisterQueueListener();
|
||||||
mProbablyDoneResults = new ArrayList<>();
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
mSetUpLatch = new CountDownLatch(1);
|
mTarget.addListener(mListener);
|
||||||
|
|
||||||
|
mFactory = new TestWriteQueueItemFactory();
|
||||||
|
|
||||||
mTarget.addListener(this);
|
|
||||||
mTarget.startPersisting();
|
mTarget.startPersisting();
|
||||||
|
|
||||||
assertTrue("Target didn't call callback on start up.",
|
assertTrue("Target didn't call callback on start up.",
|
||||||
mSetUpLatch.await(TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mListener.waitForAllExpectedCallbackDone(TIMEOUT_ALLOWANCE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
mTarget.stopPersisting();
|
mTarget.stopPersisting();
|
||||||
mTarget.removeListener(this);
|
mTarget.removeListener(mListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCallCallbackOnStartUp() {
|
public void testCallCallbackOnStartUp() {
|
||||||
// The onPreProcessItem() must be called on start up.
|
// The onPreProcessItem() must be called on start up.
|
||||||
assertEquals(1, mProbablyDoneResults.size());
|
assertEquals(1, mListener.mProbablyDoneResults.size());
|
||||||
// The last one must be called with probably done being true.
|
// The last one must be called with probably done being true.
|
||||||
assertTrue("The last probablyDone must be true.", mProbablyDoneResults.get(0));
|
assertTrue("The last probablyDone must be true.", mListener.mProbablyDoneResults.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProcessOneItem() throws Exception {
|
public void testProcessOneItem() throws Exception {
|
||||||
mLatch = new CountDownLatch(1);
|
mFactory.setExpectedProcessedItemNumber(1);
|
||||||
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
|
|
||||||
final long dispatchTime = SystemClock.uptimeMillis();
|
final long dispatchTime = SystemClock.uptimeMillis();
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't process item enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mFactory.waitForAllExpectedItemsProcessed(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process item.", 1, mItemCount.get());
|
assertEquals("Target didn't process item.", 1, mFactory.getTotalProcessedItemCount());
|
||||||
final long processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
final long processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
||||||
assertTrue("Target didn't wait enough time before processing item. duration: "
|
assertTrue("Target didn't wait enough time before processing item. duration: "
|
||||||
+ processDuration + "ms pretask delay: " + PRE_TASK_DELAY_MS + "ms",
|
+ processDuration + "ms pretask delay: " + PRE_TASK_DELAY_MS + "ms",
|
||||||
processDuration >= PRE_TASK_DELAY_MS);
|
processDuration >= PRE_TASK_DELAY_MS);
|
||||||
|
|
||||||
|
assertTrue("Target didn't call callback enough times.",
|
||||||
|
mListener.waitForAllExpectedCallbackDone(TIMEOUT_ALLOWANCE));
|
||||||
// Once before processing this item, once after that.
|
// Once before processing this item, once after that.
|
||||||
assertEquals(2, mProbablyDoneResults.size());
|
assertEquals(2, mListener.mProbablyDoneResults.size());
|
||||||
// The last one must be called with probably done being true.
|
// The last one must be called with probably done being true.
|
||||||
assertTrue("The last probablyDone must be true.", mProbablyDoneResults.get(1));
|
assertTrue("The last probablyDone must be true.", mListener.mProbablyDoneResults.get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProcessOneItem_Flush() throws Exception {
|
public void testProcessOneItem_Flush() throws Exception {
|
||||||
mLatch = new CountDownLatch(1);
|
mFactory.setExpectedProcessedItemNumber(1);
|
||||||
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
|
|
||||||
final long dispatchTime = SystemClock.uptimeMillis();
|
final long dispatchTime = SystemClock.uptimeMillis();
|
||||||
mTarget.addItem(new TestItem(), true);
|
mTarget.addItem(mFactory.createItem(), true);
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't process item enough times.",
|
||||||
mLatch.await(TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mFactory.waitForAllExpectedItemsProcessed(TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process item.", 1, mItemCount.get());
|
assertEquals("Target didn't process item.", 1, mFactory.getTotalProcessedItemCount());
|
||||||
final long processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
final long processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
||||||
assertTrue("Target didn't process item immediately when flushing. duration: "
|
assertTrue("Target didn't process item immediately when flushing. duration: "
|
||||||
+ processDuration + "ms pretask delay: "
|
+ processDuration + "ms pretask delay: "
|
||||||
+ PRE_TASK_DELAY_MS + "ms",
|
+ PRE_TASK_DELAY_MS + "ms",
|
||||||
processDuration < PRE_TASK_DELAY_MS);
|
processDuration < PRE_TASK_DELAY_MS);
|
||||||
|
|
||||||
|
assertTrue("Target didn't call callback enough times.",
|
||||||
|
mFactory.waitForAllExpectedItemsProcessed(TIMEOUT_ALLOWANCE));
|
||||||
// Once before processing this item, once after that.
|
// Once before processing this item, once after that.
|
||||||
assertEquals(2, mProbablyDoneResults.size());
|
assertEquals(2, mListener.mProbablyDoneResults.size());
|
||||||
// The last one must be called with probably done being true.
|
// The last one must be called with probably done being true.
|
||||||
assertTrue("The last probablyDone must be true.", mProbablyDoneResults.get(1));
|
assertTrue("The last probablyDone must be true.", mListener.mProbablyDoneResults.get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProcessTwoItems() throws Exception {
|
public void testProcessTwoItems() throws Exception {
|
||||||
mLatch = new CountDownLatch(2);
|
mFactory.setExpectedProcessedItemNumber(2);
|
||||||
|
mListener.setExpectedOnPreProcessItemCallbackTimes(2);
|
||||||
|
|
||||||
final long dispatchTime = SystemClock.uptimeMillis();
|
final long dispatchTime = SystemClock.uptimeMillis();
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't call callback enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + INTER_WRITE_DELAY_MS + TIMEOUT_ALLOWANCE,
|
mFactory.waitForAllExpectedItemsProcessed(PRE_TASK_DELAY_MS + INTER_WRITE_DELAY_MS
|
||||||
TimeUnit.MILLISECONDS));
|
+ TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process all items.", 2, mItemCount.get());
|
assertEquals("Target didn't process all items.", 2, mFactory.getTotalProcessedItemCount());
|
||||||
final long processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
final long processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
||||||
assertTrue("Target didn't wait enough time before processing item. duration: "
|
assertTrue("Target didn't wait enough time before processing item. duration: "
|
||||||
+ processDuration + "ms pretask delay: " + PRE_TASK_DELAY_MS
|
+ processDuration + "ms pretask delay: " + PRE_TASK_DELAY_MS
|
||||||
+ "ms inter write delay: " + INTER_WRITE_DELAY_MS + "ms",
|
+ "ms inter write delay: " + INTER_WRITE_DELAY_MS + "ms",
|
||||||
processDuration >= PRE_TASK_DELAY_MS + INTER_WRITE_DELAY_MS);
|
processDuration >= PRE_TASK_DELAY_MS + INTER_WRITE_DELAY_MS);
|
||||||
|
assertTrue("Target didn't call the onPreProcess callback enough times",
|
||||||
|
mListener.waitForAllExpectedCallbackDone(TIMEOUT_ALLOWANCE));
|
||||||
// Once before processing this item, once after that.
|
// Once before processing this item, once after that.
|
||||||
assertEquals(3, mProbablyDoneResults.size());
|
assertEquals(3, mListener.mProbablyDoneResults.size());
|
||||||
// The first one must be called with probably done being false.
|
// The first one must be called with probably done being false.
|
||||||
assertFalse("The first probablyDone must be false.", mProbablyDoneResults.get(1));
|
assertFalse("The first probablyDone must be false.", mListener.mProbablyDoneResults.get(1));
|
||||||
// The last one must be called with probably done being true.
|
// The last one must be called with probably done being true.
|
||||||
assertTrue("The last probablyDone must be true.", mProbablyDoneResults.get(2));
|
assertTrue("The last probablyDone must be true.", mListener.mProbablyDoneResults.get(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@FlakyTest(bugId = 128526085)
|
@FlakyTest(bugId = 128526085)
|
||||||
public void testProcessTwoItems_OneAfterAnother() throws Exception {
|
public void testProcessTwoItems_OneAfterAnother() throws Exception {
|
||||||
// First item
|
// First item
|
||||||
mLatch = new CountDownLatch(1);
|
mFactory.setExpectedProcessedItemNumber(1);
|
||||||
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
long dispatchTime = SystemClock.uptimeMillis();
|
long dispatchTime = SystemClock.uptimeMillis();
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't process item enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mFactory.waitForAllExpectedItemsProcessed(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE));
|
||||||
long processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
long processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
||||||
assertTrue("Target didn't wait enough time before processing item."
|
assertTrue("Target didn't wait enough time before processing item."
|
||||||
+ processDuration + "ms pretask delay: "
|
+ processDuration + "ms pretask delay: "
|
||||||
+ PRE_TASK_DELAY_MS + "ms",
|
+ PRE_TASK_DELAY_MS + "ms",
|
||||||
processDuration >= PRE_TASK_DELAY_MS);
|
processDuration >= PRE_TASK_DELAY_MS);
|
||||||
assertEquals("Target didn't process item.", 1, mItemCount.get());
|
assertEquals("Target didn't process item.", 1, mFactory.getTotalProcessedItemCount());
|
||||||
|
assertTrue("Target didn't call callback enough times.",
|
||||||
|
mListener.waitForAllExpectedCallbackDone(TIMEOUT_ALLOWANCE));
|
||||||
|
|
||||||
// Second item
|
// Second item
|
||||||
mLatch = new CountDownLatch(1);
|
mFactory.setExpectedProcessedItemNumber(1);
|
||||||
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
dispatchTime = SystemClock.uptimeMillis();
|
dispatchTime = SystemClock.uptimeMillis();
|
||||||
// Synchronize on the instance to make sure we schedule the item after it starts to wait for
|
// Synchronize on the instance to make sure we schedule the item after it starts to wait for
|
||||||
// task indefinitely.
|
// task indefinitely.
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
}
|
}
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't process item enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mFactory.waitForAllExpectedItemsProcessed(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process all items.", 2, mItemCount.get());
|
assertEquals("Target didn't process all items.", 2, mFactory.getTotalProcessedItemCount());
|
||||||
processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
processDuration = SystemClock.uptimeMillis() - dispatchTime;
|
||||||
assertTrue("Target didn't wait enough time before processing item. Process time: "
|
assertTrue("Target didn't wait enough time before processing item. Process time: "
|
||||||
+ processDuration + "ms pre task delay: "
|
+ processDuration + "ms pre task delay: "
|
||||||
+ PRE_TASK_DELAY_MS + "ms",
|
+ PRE_TASK_DELAY_MS + "ms",
|
||||||
processDuration >= PRE_TASK_DELAY_MS);
|
processDuration >= PRE_TASK_DELAY_MS);
|
||||||
|
|
||||||
|
assertTrue("Target didn't call callback enough times.",
|
||||||
|
mListener.waitForAllExpectedCallbackDone(TIMEOUT_ALLOWANCE));
|
||||||
// Once before processing this item, once after that.
|
// Once before processing this item, once after that.
|
||||||
assertEquals(3, mProbablyDoneResults.size());
|
assertEquals(3, mListener.mProbablyDoneResults.size());
|
||||||
// The last one must be called with probably done being true.
|
// The last one must be called with probably done being true.
|
||||||
assertTrue("The last probablyDone must be true.", mProbablyDoneResults.get(2));
|
assertTrue("The last probablyDone must be true.", mListener.mProbablyDoneResults.get(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFindLastItemNotReturnDifferentType() {
|
public void testFindLastItemNotReturnDifferentType() {
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
assertNull(mTarget.findLastItem(TEST_ITEM_PREDICATE, MatchingTestItem.class));
|
assertNull(mTarget.findLastItem(TestItem::shouldKeepOnFilter,
|
||||||
|
FilterableTestItem.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFindLastItemNotReturnMismatchItem() {
|
public void testFindLastItemNotReturnMismatchItem() {
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
mTarget.addItem(new MatchingTestItem(false), false);
|
mTarget.addItem(mFactory.createFilterableItem(false), false);
|
||||||
assertNull(mTarget.findLastItem(TEST_ITEM_PREDICATE, MatchingTestItem.class));
|
assertNull(mTarget.findLastItem(TestItem::shouldKeepOnFilter,
|
||||||
|
FilterableTestItem.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFindLastItemReturnMatchedItem() {
|
public void testFindLastItemReturnMatchedItem() {
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
final MatchingTestItem item = new MatchingTestItem(true);
|
final FilterableTestItem item = mFactory.createFilterableItem(true);
|
||||||
mTarget.addItem(item, false);
|
mTarget.addItem(item, false);
|
||||||
assertSame(item, mTarget.findLastItem(TEST_ITEM_PREDICATE, MatchingTestItem.class));
|
assertSame(item, mTarget.findLastItem(TestItem::shouldKeepOnFilter,
|
||||||
|
FilterableTestItem.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveItemsNotRemoveDifferentType() throws Exception {
|
public void testRemoveItemsNotRemoveDifferentType() throws Exception {
|
||||||
mLatch = new CountDownLatch(1);
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
mTarget.removeItems(TEST_ITEM_PREDICATE, MatchingTestItem.class);
|
mTarget.removeItems(TestItem::shouldKeepOnFilter, FilterableTestItem.class);
|
||||||
}
|
}
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't call callback enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mListener.waitForAllExpectedCallbackDone(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process item.", 1, mItemCount.get());
|
assertEquals("Target didn't process item.", 1, mFactory.getTotalProcessedItemCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveItemsNotRemoveMismatchedItem() throws Exception {
|
public void testRemoveItemsNotRemoveMismatchedItem() throws Exception {
|
||||||
mLatch = new CountDownLatch(1);
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
mTarget.addItem(new MatchingTestItem(false), false);
|
mTarget.addItem(mFactory.createFilterableItem(false), false);
|
||||||
mTarget.removeItems(TEST_ITEM_PREDICATE, MatchingTestItem.class);
|
mTarget.removeItems(TestItem::shouldKeepOnFilter, FilterableTestItem.class);
|
||||||
}
|
}
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't call callback enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mListener.waitForAllExpectedCallbackDone(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process item.", 1, mItemCount.get());
|
assertEquals("Target didn't process item.", 1, mFactory.getTotalProcessedItemCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateLastOrAddItemUpdatesMatchedItem() throws Exception {
|
public void testUpdateLastOrAddItemUpdatesMatchedItem() throws Exception {
|
||||||
mLatch = new CountDownLatch(1);
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
final MatchingTestItem scheduledItem = new MatchingTestItem(true);
|
final FilterableTestItem scheduledItem = mFactory.createFilterableItem(true);
|
||||||
final MatchingTestItem expected = new MatchingTestItem(true);
|
final FilterableTestItem expected = mFactory.createFilterableItem(true);
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
mTarget.addItem(scheduledItem, false);
|
mTarget.addItem(scheduledItem, false);
|
||||||
mTarget.updateLastOrAddItem(expected, false);
|
mTarget.updateLastOrAddItem(expected, false);
|
||||||
@@ -256,15 +269,15 @@ public class PersisterQueueTests implements PersisterQueue.Listener {
|
|||||||
|
|
||||||
assertSame(expected, scheduledItem.mUpdateFromItem);
|
assertSame(expected, scheduledItem.mUpdateFromItem);
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't call callback enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mListener.waitForAllExpectedCallbackDone(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process item.", 1, mItemCount.get());
|
assertEquals("Target didn't process item.", 1, mFactory.getTotalProcessedItemCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpdateLastOrAddItemUpdatesAddItemWhenNoMatch() throws Exception {
|
public void testUpdateLastOrAddItemUpdatesAddItemWhenNoMatch() throws Exception {
|
||||||
mLatch = new CountDownLatch(2);
|
mListener.setExpectedOnPreProcessItemCallbackTimes(2);
|
||||||
final MatchingTestItem scheduledItem = new MatchingTestItem(false);
|
final FilterableTestItem scheduledItem = mFactory.createFilterableItem(false);
|
||||||
final MatchingTestItem expected = new MatchingTestItem(true);
|
final FilterableTestItem expected = mFactory.createFilterableItem(true);
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
mTarget.addItem(scheduledItem, false);
|
mTarget.addItem(scheduledItem, false);
|
||||||
mTarget.updateLastOrAddItem(expected, false);
|
mTarget.updateLastOrAddItem(expected, false);
|
||||||
@@ -272,73 +285,132 @@ public class PersisterQueueTests implements PersisterQueue.Listener {
|
|||||||
|
|
||||||
assertNull(scheduledItem.mUpdateFromItem);
|
assertNull(scheduledItem.mUpdateFromItem);
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't call callback enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + INTER_WRITE_DELAY_MS + TIMEOUT_ALLOWANCE,
|
mListener.waitForAllExpectedCallbackDone(PRE_TASK_DELAY_MS + INTER_WRITE_DELAY_MS
|
||||||
TimeUnit.MILLISECONDS));
|
+ TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process item.", 2, mItemCount.get());
|
assertEquals("Target didn't process item.", 2, mFactory.getTotalProcessedItemCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRemoveItemsRemoveMatchedItem() throws Exception {
|
public void testRemoveItemsRemoveMatchedItem() throws Exception {
|
||||||
mLatch = new CountDownLatch(1);
|
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
|
||||||
synchronized (mTarget) {
|
synchronized (mTarget) {
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
mTarget.addItem(new MatchingTestItem(true), false);
|
mTarget.addItem(mFactory.createFilterableItem(true), false);
|
||||||
mTarget.removeItems(TEST_ITEM_PREDICATE, MatchingTestItem.class);
|
mTarget.removeItems(TestItem::shouldKeepOnFilter, FilterableTestItem.class);
|
||||||
}
|
}
|
||||||
assertTrue("Target didn't call callback enough times.",
|
assertTrue("Target didn't call callback enough times.",
|
||||||
mLatch.await(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE, TimeUnit.MILLISECONDS));
|
mListener.waitForAllExpectedCallbackDone(PRE_TASK_DELAY_MS + TIMEOUT_ALLOWANCE));
|
||||||
assertEquals("Target didn't process item.", 1, mItemCount.get());
|
assertEquals("Target didn't process item.", 1, mFactory.getTotalProcessedItemCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFlushWaitSynchronously() {
|
public void testFlushWaitSynchronously() {
|
||||||
final long dispatchTime = SystemClock.uptimeMillis();
|
final long dispatchTime = SystemClock.uptimeMillis();
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
mTarget.addItem(new TestItem(), false);
|
mTarget.addItem(mFactory.createItem(), false);
|
||||||
mTarget.flush();
|
mTarget.flush();
|
||||||
assertEquals("Flush should wait until all items are processed before return.",
|
assertEquals("Flush should wait until all items are processed before return.",
|
||||||
2, mItemCount.get());
|
2, mFactory.getTotalProcessedItemCount());
|
||||||
final long processTime = SystemClock.uptimeMillis() - dispatchTime;
|
final long processTime = SystemClock.uptimeMillis() - dispatchTime;
|
||||||
assertWithMessage("Flush should trigger immediate flush without delays. processTime: "
|
assertWithMessage("Flush should trigger immediate flush without delays. processTime: "
|
||||||
+ processTime).that(processTime).isLessThan(TIMEOUT_ALLOWANCE);
|
+ processTime).that(processTime).isLessThan(TIMEOUT_ALLOWANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static class TestWriteQueueItemFactory {
|
||||||
public void onPreProcessItem(boolean queueEmpty) {
|
private final AtomicInteger mItemCount = new AtomicInteger(0);;
|
||||||
mProbablyDoneResults.add(queueEmpty);
|
private CountDownLatch mLatch;
|
||||||
|
|
||||||
final CountDownLatch latch = mLatch;
|
int getTotalProcessedItemCount() {
|
||||||
if (latch != null) {
|
return mItemCount.get();
|
||||||
latch.countDown();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mSetUpLatch.countDown();
|
void setExpectedProcessedItemNumber(int countDown) {
|
||||||
|
mLatch = new CountDownLatch(countDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean waitForAllExpectedItemsProcessed(long timeoutInMilliseconds)
|
||||||
|
throws InterruptedException {
|
||||||
|
return mLatch.await(timeoutInMilliseconds, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
TestItem createItem() {
|
||||||
|
return new TestItem(mItemCount, mLatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
FilterableTestItem createFilterableItem(boolean shouldKeepOnFilter) {
|
||||||
|
return new FilterableTestItem(shouldKeepOnFilter, mItemCount, mLatch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestItem<T extends TestItem<T>> implements PersisterQueue.WriteQueueItem<T> {
|
private static class TestItem<T extends TestItem<T>>
|
||||||
|
implements PersisterQueue.WriteQueueItem<T> {
|
||||||
|
private AtomicInteger mItemCount;
|
||||||
|
private CountDownLatch mLatch;
|
||||||
|
|
||||||
|
TestItem(AtomicInteger itemCount, CountDownLatch latch) {
|
||||||
|
mItemCount = itemCount;
|
||||||
|
mLatch = latch;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process() {
|
public void process() {
|
||||||
mItemCount.getAndIncrement();
|
mItemCount.getAndIncrement();
|
||||||
|
if (mLatch != null) {
|
||||||
|
// Count down the latch at the last step is necessary, as it's a kind of lock to the
|
||||||
|
// next assert in many test cases.
|
||||||
|
mLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean shouldKeepOnFilter() {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MatchingTestItem extends TestItem<MatchingTestItem> {
|
private static class FilterableTestItem extends TestItem<FilterableTestItem> {
|
||||||
private boolean mMatching;
|
private boolean mShouldKeepOnFilter;
|
||||||
|
|
||||||
private MatchingTestItem mUpdateFromItem;
|
private FilterableTestItem mUpdateFromItem;
|
||||||
|
|
||||||
private MatchingTestItem(boolean matching) {
|
private FilterableTestItem(boolean shouldKeepOnFilter, AtomicInteger mItemCount,
|
||||||
mMatching = matching;
|
CountDownLatch mLatch) {
|
||||||
|
super(mItemCount, mLatch);
|
||||||
|
mShouldKeepOnFilter = shouldKeepOnFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(MatchingTestItem item) {
|
public boolean matches(FilterableTestItem item) {
|
||||||
return item.mMatching;
|
return item.mShouldKeepOnFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateFrom(MatchingTestItem item) {
|
public void updateFrom(FilterableTestItem item) {
|
||||||
mUpdateFromItem = item;
|
mUpdateFromItem = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean shouldKeepOnFilter() {
|
||||||
|
return mShouldKeepOnFilter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestPersisterQueueListener implements PersisterQueue.Listener {
|
||||||
|
CountDownLatch mCallbackLatch;
|
||||||
|
final List<Boolean> mProbablyDoneResults = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPreProcessItem(boolean queueEmpty) {
|
||||||
|
mProbablyDoneResults.add(queueEmpty);
|
||||||
|
mCallbackLatch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setExpectedOnPreProcessItemCallbackTimes(int countDown) {
|
||||||
|
mCallbackLatch = new CountDownLatch(countDown);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean waitForAllExpectedCallbackDone(long timeoutInMilliseconds)
|
||||||
|
throws InterruptedException {
|
||||||
|
return mCallbackLatch.await(timeoutInMilliseconds, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user