TestContentProvider.java revision fa39e2bca1b284ad7c931d9194287770b7b507fa
1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/* 2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2017 The Android Open Source Project 3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License. 6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at 7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software 11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and 14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License. 15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage android.support.content; 18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport static org.junit.Assert.assertEquals; 20282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 21282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.ContentProvider; 22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.ContentResolver; 23282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.content.ContentValues; 24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.database.AbstractWindowedCursor; 25282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.database.Cursor; 26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.database.CursorWindow; 27282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.database.MatrixCursor; 28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.database.MatrixCursor.RowBuilder; 29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.net.Uri; 30282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.os.Bundle; 31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.os.CancellationSignal; 32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.support.annotation.Nullable; 33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.support.annotation.VisibleForTesting; 34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/** 36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * A stub data paging provider used for testing of paging support. 37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Ignores client supplied projections. 38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic final class TestContentProvider extends ContentProvider { 40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String AUTHORITY = "android.support.content.test.testpagingprovider"; 42282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 43282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String UNPAGED_PATH = "/un-paged"; 44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String PAGED_PATH = "/paged"; 45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String PAGED_WINDOWED_PATH = PAGED_PATH + "/windowed"; 46282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final Uri UNPAGED_URI = new Uri.Builder() 48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .scheme("content") 49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .authority(AUTHORITY) 50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .path(UNPAGED_PATH) 51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .build(); 52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final Uri PAGED_URI = new Uri.Builder() 53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .scheme("content") 54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .authority(AUTHORITY) 55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .path(PAGED_PATH) 56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .build(); 57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final Uri PAGED_WINDOWED_URI = new Uri.Builder() 58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .scheme("content") 59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .authority(AUTHORITY) 60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .path(PAGED_WINDOWED_PATH) 61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .build(); 62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 63282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String COLUMN_POS = "ColumnPos"; 64282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String COLUMN_A = "ColumnA"; 65282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String COLUMN_B = "ColumnB"; 66282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String COLUMN_C = "ColumnC"; 67282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String COLUMN_D = "ColumnD"; 68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String[] PROJECTION = { 69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COLUMN_POS, 70282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COLUMN_A, 71282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COLUMN_B, 72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COLUMN_C, 73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski COLUMN_D 74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }; 75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @VisibleForTesting 77282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final String RECORD_COUNT = "test-record-count"; 78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @VisibleForTesting 80282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static final int DEFAULT_RECORD_COUNT = 567; 81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static final String TAG = "TestPagingProvider"; 8391447d88f2bdf9c2bf8d1a53570efef6172fba74Narayan Kamath 84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public boolean onCreate() { 86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 89282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public Cursor query( 91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Uri uri, @Nullable String[] projection, String selection, String[] selectionArgs, 92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski String sortOrder) { 93282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return query(uri, projection, null, null); 94282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 95282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 96282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 97282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public Cursor query(Uri uri, String[] ignored, Bundle queryArgs, 98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski CancellationSignal cancellationSignal) { 99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY; 101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int recordCount = getIntValue(RECORD_COUNT, queryArgs, uri, DEFAULT_RECORD_COUNT); 103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (recordCount < 0) { 104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new RuntimeException("Recordset size must be >= 0"); 105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Cursor cursor = null; 108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski switch (uri.getPath()) { 109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case UNPAGED_PATH: 110282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski cursor = buildUnpagedResults(recordCount); 111282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 112282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case PAGED_PATH: 113282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski cursor = buildPagedResults(uri, queryArgs, recordCount); 114282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 115282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case PAGED_WINDOWED_PATH: 116282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski cursor = buildPagedWindowedResults(uri, queryArgs, recordCount); 117282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 118282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski default: 119282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new IllegalArgumentException("Unrecognized path: " + uri.getPath()); 120282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 121282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 122282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski cursor.setNotificationUri(getContext().getContentResolver(), uri); 123282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 124282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return cursor; 125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 126282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 127282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 128282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Return a int value specified in Bundle key, Uri query arg, or fallback default value. 129282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 130282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static int getIntValue(String key, Bundle queryArgs, Uri uri, int defaultValue) { 131282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int value = queryArgs.getInt(key, Integer.MIN_VALUE); 132282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (value != Integer.MIN_VALUE) { 133282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return value; 134282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 135282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 136282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Nullable String argValue = uri.getQueryParameter(key); 137282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (argValue != null) { 138282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski try { 139282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Integer.parseInt(argValue); 140282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } catch (NumberFormatException ignored) { 141282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 142282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 143282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return defaultValue; 145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private MatrixCursor buildPagedResults(Uri uri, Bundle queryArgs, int recordsetSize) { 148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int offset = getIntValue(ContentResolver.QUERY_ARG_OFFSET, queryArgs, uri, 0); 149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int limit = getIntValue(ContentResolver.QUERY_ARG_LIMIT, queryArgs, uri, recordsetSize); 150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MatrixCursor c = createInMemoryCursor(); 152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bundle extras = c.getExtras(); 153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Calculate the number of items to include in the cursor. 155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int numItems = constrain(recordsetSize - offset, 0, limit); 156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski // Build the paged result set. 158282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = offset; i < offset + numItems; i++) { 159282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fillRow(c.newRow(), i); 160282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 161282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 162282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, new String[] { 163282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ContentResolver.QUERY_ARG_OFFSET, 164282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski ContentResolver.QUERY_ARG_LIMIT 165282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski }); 166282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski extras.putInt(ContentResolver.EXTRA_TOTAL_COUNT, recordsetSize); 167282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return c; 168282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 169eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown 170eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown private AbstractWindowedCursor buildPagedWindowedResults( 171eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown Uri uri, Bundle queryArgs, int recordsetSize) { 172eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown int offset = getIntValue(ContentResolver.QUERY_ARG_OFFSET, queryArgs, uri, 0); 173eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown int limit = getIntValue(ContentResolver.QUERY_ARG_LIMIT, queryArgs, uri, recordsetSize); 174eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown 175eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown int windowSize = limit - 1; 176eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown 177eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown TestWindowedCursor c = new TestWindowedCursor(PROJECTION, recordsetSize); 178eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown CursorWindow window = c.getWindow(); 179eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown window.setNumColumns(PROJECTION.length); 180eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown 181eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown Bundle extras = c.getExtras(); 182eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown 183eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown // Build the unpaged result set. 184eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown for (int row = 0; row < windowSize; row++) { 185eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown if (!window.allocRow()) { 186eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown break; 187eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown } 188eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown if (!fillRow(window, row)) { 189eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown window.freeLastRow(); 190eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown break; 191eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown } 192eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown } 193eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown 194eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, new String[] { 195eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown ContentResolver.QUERY_ARG_OFFSET, 196eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown ContentResolver.QUERY_ARG_LIMIT 197eb490d6194bd79adbe144a1230fc126f4c180a2fJeff Brown }); 198282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski extras.putInt(ContentResolver.EXTRA_TOTAL_COUNT, recordsetSize); 199282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return c; 200282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 201282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 202282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private MatrixCursor buildUnpagedResults(int recordsetSize) { 203282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MatrixCursor c = createInMemoryCursor(); 204282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 2057cce7bb5d8d68e78a414c176dc89a803f706c9ceChet Haase // Build the unpaged result set. 206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 0; i < recordsetSize; i++) { 207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski fillRow(c.newRow(), i); 208282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return c; 211282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns data type of the given object's value. 215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *<p> 216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returned values are 217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <ul> 218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <li>{@link Cursor#FIELD_TYPE_NULL}</li> 219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <li>{@link Cursor#FIELD_TYPE_INTEGER}</li> 220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <li>{@link Cursor#FIELD_TYPE_FLOAT}</li> 221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <li>{@link Cursor#FIELD_TYPE_STRING}</li> 222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <li>{@link Cursor#FIELD_TYPE_BLOB}</li> 223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *</ul> 224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *</p> 225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static int getTypeOfObject(Object obj) { 227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (obj == null) { 228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Cursor.FIELD_TYPE_NULL; 229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (obj instanceof byte[]) { 230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Cursor.FIELD_TYPE_BLOB; 231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (obj instanceof Float || obj instanceof Double) { 232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Cursor.FIELD_TYPE_FLOAT; 233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else if (obj instanceof Long || obj instanceof Integer 234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || obj instanceof Short || obj instanceof Byte) { 235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Cursor.FIELD_TYPE_INTEGER; 236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } else { 237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return Cursor.FIELD_TYPE_STRING; 238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private MatrixCursor createInMemoryCursor() { 242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski MatrixCursor c = new MatrixCursor(PROJECTION); 243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski Bundle extras = new Bundle(); 244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski c.setExtras(extras); 245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return c; 246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private void fillRow(RowBuilder row, int rowId) { 249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski row.add(createCellValue(rowId, 0)); 250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski row.add(createCellValue(rowId, 1)); 251282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski row.add(createCellValue(rowId, 2)); 252282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski row.add(createCellValue(rowId, 3)); 253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski row.add(createCellValue(rowId, 4)); 254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @return true if the row was successfully populated. If false, caller should freeLastRow. 258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static boolean fillRow(CursorWindow window, int row) { 260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!window.putLong((int) createCellValue(row, 0), row, 0)) { 261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski for (int i = 1; i < PROJECTION.length; i++) { 264282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski if (!window.putString((String) createCellValue(row, i), row, i)) { 265282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return false; 266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return true; 269282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static Object createCellValue(int row, int col) { 272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski switch(col) { 273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 0: 274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return row; 275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 1: 276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "--aaa--" + row; 277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 2: 278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "**bbb**" + row; 279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 3: 280282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return ("^^ccc^^" + row); 281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case 4: 282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return "##ddd##" + row; 283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski default: 284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new IllegalArgumentException("Unsupported column: " + col); 285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Asserts that the value at the current cursor position x column 290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * is expected test data for the supplied row. 291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * <p>Cursor must be pre-positioned. 293282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * 294282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param cursor must be prepositioned to the row to be tested. 295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param row row value expected to be reflected in cell. This can be different 296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * than the cursor position due to paging. 297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @param column 298282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 299282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @VisibleForTesting 300282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static void assertExpectedCellValue(Cursor cursor, int row, int column) { 301282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski int type = cursor.getType(column); 302282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski switch(type) { 303282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case Cursor.FIELD_TYPE_NULL: 304282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new UnsupportedOperationException("Not implemented."); 305282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case Cursor.FIELD_TYPE_INTEGER: 306282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assertEquals(createCellValue(row, column), cursor.getInt(column)); 307282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 308282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case Cursor.FIELD_TYPE_FLOAT: 309282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assertEquals(createCellValue(row, column), cursor.getDouble(column)); 310282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 311282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case Cursor.FIELD_TYPE_BLOB: 312282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assertEquals(createCellValue(row, column), cursor.getBlob(column)); 313282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 314282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski case Cursor.FIELD_TYPE_STRING: 315282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assertEquals(createCellValue(row, column), cursor.getString(column)); 316282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski break; 317282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski default: 318282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new UnsupportedOperationException("Unknown column type: " + type); 319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 322282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 323282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public String getType(Uri uri) { 324282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new UnsupportedOperationException(); 325282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 326282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 327282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 328282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public Uri insert(Uri uri, ContentValues values) { 329282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new UnsupportedOperationException(); 330282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 331282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public int delete(Uri uri, String selection, String[] selectionArgs) { 334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new UnsupportedOperationException(); 335282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski throw new UnsupportedOperationException(); 340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static int constrain(int amount, int low, int high) { 343282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return amount < low ? low : (amount > high ? high : amount); 344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski /** 347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Returns a Uri that includes paging information embedded in the URI. 348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This allows a test client to force paged results when running on older SDKs... 349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * pre Android O SDKs lacking the ContentResolver#query w/ Bundle override 350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * necessary for paging. 351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */ 352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static Uri forcePagingSpec(Uri uri, int offset, int limit) { 353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski assert (uri.getPath().equals(TestContentProvider.PAGED_PATH) 354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski || uri.getPath().equals(TestContentProvider.PAGED_WINDOWED_PATH)); 355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return uri.buildUpon() 356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .appendQueryParameter(ContentResolver.QUERY_ARG_OFFSET, String.valueOf(offset)) 357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .appendQueryParameter(ContentResolver.QUERY_ARG_LIMIT, String.valueOf(limit)) 358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .build(); 359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public static Uri forceRecordCount(Uri uri, int recordCount) { 362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return uri.buildUpon() 363282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .appendQueryParameter(RECORD_COUNT, String.valueOf(recordCount)) 364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski .build(); 365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private static final class TestWindowedCursor extends AbstractWindowedCursor { 368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final String[] mProjection; 370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final int mCount; 371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski private final Bundle mExtras; 372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski TestWindowedCursor(String[] projection, int count) { 374282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mProjection = projection; 375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mCount = count; 376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski mExtras = new Bundle(); 377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski setWindow(new CursorWindow("stevie")); 379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public Bundle getExtras() { 383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mExtras; 384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 385282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public int getCount() { 388282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mCount; 389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski 391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski @Override 392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski public String[] getColumnNames() { 393282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski return mProjection; 394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski } 396282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski} 397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski