1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.contentpager.content; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertTrue; 22 23 import android.database.Cursor; 24 import android.database.MatrixCursor; 25 import android.net.Uri; 26 import android.os.Bundle; 27 28 import androidx.annotation.Nullable; 29 import androidx.core.util.Pair; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 import java.util.concurrent.CountDownLatch; 34 import java.util.concurrent.TimeUnit; 35 36 final class TestQueryCallback implements ContentPager.QueryRunner.Callback { 37 38 private static final String URI_KEY = "testUri"; 39 private static final String URI_PAGE_ID = "testPageId"; 40 41 private CollectorLatch<Query> mQueryLatch; 42 private CollectorLatch<Pair<Integer, Cursor>> mReplyLatch; 43 44 @Override 45 public @Nullable Cursor runQueryInBackground(Query query) { 46 mQueryLatch.accept(query); 47 Bundle extras = new Bundle(); 48 extras.putParcelable(URI_KEY, query.getUri()); 49 extras.putInt(URI_PAGE_ID, query.getId()); 50 MatrixCursor cursor = new MatrixCursor(new String[]{"id"}, 0); 51 cursor.setExtras(extras); 52 return cursor; 53 } 54 55 @Override 56 public void onQueryFinished(Query query, Cursor cursor) { 57 mReplyLatch.accept(new Pair<>(query.getId(), cursor)); 58 } 59 60 public void reset(int expectedCount) throws InterruptedException { 61 mQueryLatch = new CollectorLatch<>(expectedCount); 62 mReplyLatch = new CollectorLatch<>(expectedCount); 63 } 64 65 public void waitFor(int seconds) throws InterruptedException { 66 assertTrue(mQueryLatch.await(seconds, TimeUnit.SECONDS)); 67 assertTrue(mReplyLatch.await(seconds, TimeUnit.SECONDS)); 68 } 69 70 public void assertQueried(final int expectedPageId) { 71 mQueryLatch.assertHasItem(new Matcher<Query>() { 72 @Override 73 public boolean matches(Query query) { 74 return expectedPageId == query.getId(); 75 } 76 }); 77 } 78 79 public void assertReceivedContent(Uri expectedUri, final int expectedPageId) { 80 mReplyLatch.assertHasItem(new Matcher<Pair<Integer, Cursor>>() { 81 @Override 82 public boolean matches(Pair<Integer, Cursor> value) { 83 return expectedPageId == value.first; 84 } 85 }); 86 List<Pair<Integer, Cursor>> collected = mReplyLatch.getCollected(); 87 Cursor cursor = null; 88 89 for (Pair<Integer, Cursor> pair : collected) { 90 if (expectedPageId == pair.first) { 91 cursor = pair.second; 92 } 93 } 94 95 assertEquals(0, cursor.getCount()); // we don't add any records to our test cursor. 96 Bundle extras = cursor.getExtras(); 97 assertNotNull(extras); 98 assertTrue(extras.containsKey(URI_KEY)); 99 assertEquals(extras.getParcelable(URI_KEY), expectedUri); 100 assertTrue(extras.containsKey(URI_PAGE_ID)); 101 assertEquals(extras.getInt(URI_PAGE_ID), expectedPageId); 102 } 103 104 private static final class CollectorLatch<T> extends CountDownLatch { 105 106 private final List<T> mCollected = new ArrayList<>(); 107 108 CollectorLatch(int count) { 109 super(count); 110 } 111 112 void accept(@Nullable T value) { 113 onReceived(value); 114 super.countDown(); 115 } 116 117 @Override 118 public void countDown() { 119 throw new UnsupportedOperationException("Count is incremented by calls to accept."); 120 } 121 122 void onReceived(@Nullable T value) { 123 mCollected.add(value); 124 } 125 126 List<T> getCollected() { 127 return mCollected; 128 } 129 130 public void assertHasItem(Matcher<T> matcher) { 131 T item = null; 132 for (T val : mCollected) { 133 if (matcher.matches(val)) { 134 item = val; 135 } 136 } 137 assertNotNull(item); 138 } 139 140 public @Nullable T get(int index) { 141 return mCollected.get(index); 142 } 143 } 144 145 interface Matcher<T> { 146 boolean matches(T value); 147 } 148 } 149