TestContentProvider.java revision c01ec9664a26a603d90b067d1ca7ca39950eb025
1c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay/* 2c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Copyright (C) 2017 The Android Open Source Project 3c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * 4c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Licensed under the Apache License, Version 2.0 (the "License"); 5c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * you may not use this file except in compliance with the License. 6c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * You may obtain a copy of the License at 7c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * 8c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * http://www.apache.org/licenses/LICENSE-2.0 9c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * 10c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Unless required by applicable law or agreed to in writing, software 11c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * distributed under the License is distributed on an "AS IS" BASIS, 12c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * See the License for the specific language governing permissions and 14c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * limitations under the License. 15c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 16c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 17c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKaypackage android.support.content; 18c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 19c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport static junit.framework.Assert.assertEquals; 20c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 21c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.content.ContentProvider; 22c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.content.ContentResolver; 23c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.content.ContentValues; 24c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.database.AbstractWindowedCursor; 25c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.database.Cursor; 26c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.database.CursorWindow; 27c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.database.MatrixCursor; 28c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.database.MatrixCursor.RowBuilder; 29c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.net.Uri; 30c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.Bundle; 31c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.os.CancellationSignal; 32c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.support.annotation.Nullable; 33c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKayimport android.support.annotation.VisibleForTesting; 34c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 35c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay/** 36c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * A stub data paging provider used for testing of paging support. 37c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Ignores client supplied projections. 38c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 39c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKaypublic final class TestContentProvider extends ContentProvider { 40c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 41c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String AUTHORITY = "android.support.content.test.testpagingprovider"; 42c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 43c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String UNPAGED_PATH = "/un-paged"; 44c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String PAGED_PATH = "/paged"; 45c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String PAGED_WINDOWED_PATH = PAGED_PATH + "/windowed"; 46c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 47c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final Uri UNPAGED_URI = new Uri.Builder() 48c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .scheme("content") 49c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .authority(AUTHORITY) 50c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .path(UNPAGED_PATH) 51c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .build(); 52c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final Uri PAGED_URI = new Uri.Builder() 53c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .scheme("content") 54c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .authority(AUTHORITY) 55c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .path(PAGED_PATH) 56c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .build(); 57c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final Uri PAGED_WINDOWED_URI = new Uri.Builder() 58c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .scheme("content") 59c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .authority(AUTHORITY) 60c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .path(PAGED_WINDOWED_PATH) 61c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .build(); 62c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 63c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String COLUMN_POS = "ColumnPos"; 64c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String COLUMN_A = "ColumnA"; 65c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String COLUMN_B = "ColumnB"; 66c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String COLUMN_C = "ColumnC"; 67c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String COLUMN_D = "ColumnD"; 68c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String[] PROJECTION = { 69c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay COLUMN_POS, 70c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay COLUMN_A, 71c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay COLUMN_B, 72c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay COLUMN_C, 73c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay COLUMN_D 74c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay }; 75c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 76c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @VisibleForTesting 77c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final String RECORD_COUNT = "test-record-count"; 78c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 79c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @VisibleForTesting 80c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static final int DEFAULT_RECORD_COUNT = 567; 81c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 82c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private static final String TAG = "TestPagingProvider"; 83c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 84c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 85c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public boolean onCreate() { 86c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return true; 87c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 88c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 89c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 90c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public Cursor query( 91c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Uri uri, @Nullable String[] projection, String selection, String[] selectionArgs, 92c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay String sortOrder) { 93c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return query(uri, projection, null, null); 94c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 95c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 96c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 97c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public Cursor query(Uri uri, String[] ignored, Bundle queryArgs, 98c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay CancellationSignal cancellationSignal) { 99c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 100c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay queryArgs = queryArgs != null ? queryArgs : Bundle.EMPTY; 101c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 102c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int recordCount = getIntValue(RECORD_COUNT, queryArgs, uri, DEFAULT_RECORD_COUNT); 103c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (recordCount < 0) { 104c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new RuntimeException("Recordset size must be >= 0"); 105c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 106c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 107c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Cursor cursor = null; 108c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay switch (uri.getPath()) { 109c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case UNPAGED_PATH: 110c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay cursor = buildUnpagedResults(recordCount); 111c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 112c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case PAGED_PATH: 113c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay cursor = buildPagedResults(uri, queryArgs, recordCount); 114c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 115c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case PAGED_WINDOWED_PATH: 116c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay cursor = buildPagedWindowedResults(uri, queryArgs, recordCount); 117c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 118c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay default: 119c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new IllegalArgumentException("Unrecognized path: " + uri.getPath()); 120c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 121c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 122c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay cursor.setNotificationUri(getContext().getContentResolver(), uri); 123c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 124c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return cursor; 125c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 126c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 127c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 128c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Return a int value specified in Bundle key, Uri query arg, or fallback default value. 129c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 130c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private static int getIntValue(String key, Bundle queryArgs, Uri uri, int defaultValue) { 131c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int value = queryArgs.getInt(key, Integer.MIN_VALUE); 132c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (value != Integer.MIN_VALUE) { 133c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return value; 134c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 135c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 136c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Nullable String argValue = uri.getQueryParameter(key); 137c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (argValue != null) { 138c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay try { 139c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return Integer.parseInt(argValue); 140c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } catch (NumberFormatException ignored) { 141c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 142c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 143c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 144c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return defaultValue; 145c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 146c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 147c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private MatrixCursor buildPagedResults(Uri uri, Bundle queryArgs, int recordsetSize) { 148c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int offset = getIntValue(ContentResolver.QUERY_ARG_OFFSET, queryArgs, uri, 0); 149c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int limit = getIntValue(ContentResolver.QUERY_ARG_LIMIT, queryArgs, uri, recordsetSize); 150c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 151c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay MatrixCursor c = createInMemoryCursor(); 152c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Bundle extras = c.getExtras(); 153c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 154c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay // Calculate the number of items to include in the cursor. 155c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int numItems = constrain(recordsetSize - offset, 0, limit); 156c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 157c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay // Build the paged result set. 158c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay for (int i = offset; i < offset + numItems; i++) { 159c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay fillRow(c.newRow(), i); 160c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 161c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 162c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, new String[] { 163c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay ContentResolver.QUERY_ARG_OFFSET, 164c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay ContentResolver.QUERY_ARG_LIMIT 165c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay }); 166c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay extras.putInt(ContentResolver.EXTRA_TOTAL_COUNT, recordsetSize); 167c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return c; 168c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 169c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 170c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private AbstractWindowedCursor buildPagedWindowedResults( 171c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Uri uri, Bundle queryArgs, int recordsetSize) { 172c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int offset = getIntValue(ContentResolver.QUERY_ARG_OFFSET, queryArgs, uri, 0); 173c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int limit = getIntValue(ContentResolver.QUERY_ARG_LIMIT, queryArgs, uri, recordsetSize); 174c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 175c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int windowSize = limit - 1; 176c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 177c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay TestWindowedCursor c = new TestWindowedCursor(PROJECTION, recordsetSize); 178c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay CursorWindow window = c.getWindow(); 179c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay window.setNumColumns(PROJECTION.length); 180c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 181c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Bundle extras = c.getExtras(); 182c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 183c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay // Build the unpaged result set. 184c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay for (int row = 0; row < windowSize; row++) { 185c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (!window.allocRow()) { 186c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 187c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 188c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (!fillRow(window, row)) { 189c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay window.freeLastRow(); 190c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 191c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 192c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 193c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 194c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay extras.putStringArray(ContentResolver.EXTRA_HONORED_ARGS, new String[] { 195c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay ContentResolver.QUERY_ARG_OFFSET, 196c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay ContentResolver.QUERY_ARG_LIMIT 197c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay }); 198c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay extras.putInt(ContentResolver.EXTRA_TOTAL_COUNT, recordsetSize); 199c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return c; 200c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 201c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 202c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private MatrixCursor buildUnpagedResults(int recordsetSize) { 203c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay MatrixCursor c = createInMemoryCursor(); 204c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 205c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay // Build the unpaged result set. 206c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay for (int i = 0; i < recordsetSize; i++) { 207c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay fillRow(c.newRow(), i); 208c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 209c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 210c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return c; 211c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 212c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 213c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 214c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Returns data type of the given object's value. 215c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *<p> 216c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Returned values are 217c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * <ul> 218c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * <li>{@link Cursor#FIELD_TYPE_NULL}</li> 219c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * <li>{@link Cursor#FIELD_TYPE_INTEGER}</li> 220c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * <li>{@link Cursor#FIELD_TYPE_FLOAT}</li> 221c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * <li>{@link Cursor#FIELD_TYPE_STRING}</li> 222c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * <li>{@link Cursor#FIELD_TYPE_BLOB}</li> 223c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *</ul> 224c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay *</p> 225c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 226c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static int getTypeOfObject(Object obj) { 227c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (obj == null) { 228c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return Cursor.FIELD_TYPE_NULL; 229c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } else if (obj instanceof byte[]) { 230c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return Cursor.FIELD_TYPE_BLOB; 231c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } else if (obj instanceof Float || obj instanceof Double) { 232c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return Cursor.FIELD_TYPE_FLOAT; 233c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } else if (obj instanceof Long || obj instanceof Integer 234c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay || obj instanceof Short || obj instanceof Byte) { 235c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return Cursor.FIELD_TYPE_INTEGER; 236c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } else { 237c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return Cursor.FIELD_TYPE_STRING; 238c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 239c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 240c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 241c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private MatrixCursor createInMemoryCursor() { 242c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay MatrixCursor c = new MatrixCursor(PROJECTION); 243c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay Bundle extras = new Bundle(); 244c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay c.setExtras(extras); 245c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return c; 246c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 247c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 248c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private void fillRow(RowBuilder row, int rowId) { 249c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay row.add(createCellValue(rowId, 0)); 250c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay row.add(createCellValue(rowId, 1)); 251c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay row.add(createCellValue(rowId, 2)); 252c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay row.add(createCellValue(rowId, 3)); 253c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay row.add(createCellValue(rowId, 4)); 254c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 255c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 256c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 257c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * @return true if the row was successfully populated. If false, caller should freeLastRow. 258c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 259c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private static boolean fillRow(CursorWindow window, int row) { 260c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (!window.putLong((int) createCellValue(row, 0), row, 0)) { 261c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return false; 262c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 263c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay for (int i = 1; i < PROJECTION.length; i++) { 264c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay if (!window.putString((String) createCellValue(row, i), row, i)) { 265c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return false; 266c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 267c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 268c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return true; 269c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 270c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 271c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private static Object createCellValue(int row, int col) { 272c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay switch(col) { 273c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case 0: 274c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return row; 275c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case 1: 276c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return "--aaa--" + row; 277c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case 2: 278c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return "**bbb**" + row; 279c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case 3: 280c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return ("^^ccc^^" + row); 281c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case 4: 282c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return "##ddd##" + row; 283c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay default: 284c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new IllegalArgumentException("Unsupported column: " + col); 285c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 286c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 287c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 288c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 289c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Asserts that the value at the current cursor position x column 290c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * is expected test data for the supplied row. 291c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * 292c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * <p>Cursor must be pre-positioned. 293c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * 294c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * @param cursor must be prepositioned to the row to be tested. 295c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * @param row row value expected to be reflected in cell. This can be different 296c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * than the cursor position due to paging. 297c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * @param column 298c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 299c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @VisibleForTesting 300c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static void assertExpectedCellValue(Cursor cursor, int row, int column) { 301c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay int type = cursor.getType(column); 302c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay switch(type) { 303c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case Cursor.FIELD_TYPE_NULL: 304c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new UnsupportedOperationException("Not implemented."); 305c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case Cursor.FIELD_TYPE_INTEGER: 306c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay assertEquals(createCellValue(row, column), cursor.getInt(column)); 307c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 308c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case Cursor.FIELD_TYPE_FLOAT: 309c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay assertEquals(createCellValue(row, column), cursor.getDouble(column)); 310c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 311c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case Cursor.FIELD_TYPE_BLOB: 312c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay assertEquals(createCellValue(row, column), cursor.getBlob(column)); 313c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 314c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay case Cursor.FIELD_TYPE_STRING: 315c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay assertEquals(createCellValue(row, column), cursor.getString(column)); 316c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay break; 317c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay default: 318c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new UnsupportedOperationException("Unknown column type: " + type); 319c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 320c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 321c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 322c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 323c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public String getType(Uri uri) { 324c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new UnsupportedOperationException(); 325c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 326c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 327c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 328c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public Uri insert(Uri uri, ContentValues values) { 329c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new UnsupportedOperationException(); 330c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 331c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 332c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 333c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public int delete(Uri uri, String selection, String[] selectionArgs) { 334c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new UnsupportedOperationException(); 335c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 336c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 337c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 338c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 339c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay throw new UnsupportedOperationException(); 340c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 341c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 342c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private static int constrain(int amount, int low, int high) { 343c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return amount < low ? low : (amount > high ? high : amount); 344c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 345c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 346c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay /** 347c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * Returns a Uri that includes paging information embedded in the URI. 348c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * This allows a test client to force paged results when running on older SDKs... 349c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * pre Android O SDKs lacking the ContentResolver#query w/ Bundle override 350c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay * necessary for paging. 351c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay */ 352c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static Uri forcePagingSpec(Uri uri, int offset, int limit) { 353c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay assert (uri.getPath().equals(TestContentProvider.PAGED_PATH) 354c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay || uri.getPath().equals(TestContentProvider.PAGED_WINDOWED_PATH)); 355c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return uri.buildUpon() 356c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .appendQueryParameter(ContentResolver.QUERY_ARG_OFFSET, String.valueOf(offset)) 357c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .appendQueryParameter(ContentResolver.QUERY_ARG_LIMIT, String.valueOf(limit)) 358c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .build(); 359c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 360c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 361c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public static Uri forceRecordCount(Uri uri, int recordCount) { 362c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return uri.buildUpon() 363c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .appendQueryParameter(RECORD_COUNT, String.valueOf(recordCount)) 364c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay .build(); 365c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 366c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 367c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private static final class TestWindowedCursor extends AbstractWindowedCursor { 368c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 369c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final String[] mProjection; 370c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final int mCount; 371c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay private final Bundle mExtras; 372c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 373c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay TestWindowedCursor(String[] projection, int count) { 374c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mProjection = projection; 375c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mCount = count; 376c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay mExtras = new Bundle(); 377c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 378c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay setWindow(new CursorWindow("stevie")); 379c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 380c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 381c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 382c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public Bundle getExtras() { 383c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mExtras; 384c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 385c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 386c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 387c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public int getCount() { 388c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mCount; 389c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 390c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay 391c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay @Override 392c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay public String[] getColumnNames() { 393c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay return mProjection; 394c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 395c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay } 396c01ec9664a26a603d90b067d1ca7ca39950eb025Steve McKay} 397