/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.contacts.tests.mocks; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.text.TextUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import junit.framework.Assert; /** * A programmable mock content provider. */ public class MockContentProvider extends ContentProvider { private static final String TAG = "MockContentProvider"; public static class Query { private final Uri mUri; private String[] mProjection; private String[] mDefaultProjection; private String mSelection; private String[] mSelectionArgs; private String mSortOrder; private ArrayList<Object> mRows = new ArrayList<Object>(); private boolean mAnyProjection; private boolean mAnySelection; private boolean mAnySortOrder; private boolean mAnyNumberOfTimes; private boolean mExecuted; public Query(Uri uri) { mUri = uri; } @Override public String toString() { return queryToString(mUri, mProjection, mSelection, mSelectionArgs, mSortOrder); } public Query withProjection(String... projection) { mProjection = projection; return this; } public Query withDefaultProjection(String... projection) { mDefaultProjection = projection; return this; } public Query withAnyProjection() { mAnyProjection = true; return this; } public Query withSelection(String selection, String... selectionArgs) { mSelection = selection; mSelectionArgs = selectionArgs; return this; } public Query withAnySelection() { mAnySelection = true; return this; } public Query withSortOrder(String sortOrder) { mSortOrder = sortOrder; return this; } public Query withAnySortOrder() { mAnySortOrder = true; return this; } public Query returnRow(ContentValues values) { mRows.add(values); return this; } public Query returnRow(Object... row) { mRows.add(row); return this; } public Query returnEmptyCursor() { mRows.clear(); return this; } public Query anyNumberOfTimes() { mAnyNumberOfTimes = true; return this; } public boolean equals(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { if (!uri.equals(mUri)) { return false; } if (!mAnyProjection && !equals(projection, mProjection)) { return false; } if (!mAnySelection && !equals(selection, mSelection)) { return false; } if (!mAnySelection && !equals(selectionArgs, mSelectionArgs)) { return false; } if (!mAnySortOrder && !equals(sortOrder, mSortOrder)) { return false; } return true; } private boolean equals(String string1, String string2) { if (TextUtils.isEmpty(string1)) { string1 = null; } if (TextUtils.isEmpty(string2)) { string2 = null; } return TextUtils.equals(string1, string2); } private static boolean equals(String[] array1, String[] array2) { boolean empty1 = array1 == null || array1.length == 0; boolean empty2 = array2 == null || array2.length == 0; if (empty1 && empty2) { return true; } if (empty1 != empty2 && (empty1 || empty2)) { return false; } if (array1.length != array2.length) return false; for (int i = 0; i < array1.length; i++) { if (!array1[i].equals(array2[i])) { return false; } } return true; } public Cursor getResult(String[] projection) { String[] columnNames; if (mAnyProjection) { columnNames = projection; } else { columnNames = mProjection != null ? mProjection : mDefaultProjection; } MatrixCursor cursor = new MatrixCursor(columnNames); for (Object row : mRows) { if (row instanceof Object[]) { cursor.addRow((Object[]) row); } else { ContentValues values = (ContentValues) row; Object[] columns = new Object[projection.length]; for (int i = 0; i < projection.length; i++) { columns[i] = values.get(projection[i]); } cursor.addRow(columns); } } return cursor; } } public static class TypeQuery { private final Uri mUri; private final String mType; public TypeQuery(Uri uri, String type) { mUri = uri; mType = type; } public Uri getUri() { return mUri; } public String getType() { return mType; } @Override public String toString() { return mUri + " --> " + mType; } public boolean equals(Uri uri) { return getUri().equals(uri); } } private ArrayList<Query> mExpectedQueries = new ArrayList<Query>(); private HashMap<Uri, String> mExpectedTypeQueries = Maps.newHashMap(); @Override public boolean onCreate() { return true; } public Query expectQuery(Uri contentUri) { Query query = new Query(contentUri); mExpectedQueries.add(query); return query; } public void expectTypeQuery(Uri uri, String type) { mExpectedTypeQueries.put(uri, type); } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { for (Iterator<Query> iterator = mExpectedQueries.iterator(); iterator.hasNext();) { Query query = iterator.next(); if (query.equals(uri, projection, selection, selectionArgs, sortOrder)) { query.mExecuted = true; if (!query.mAnyNumberOfTimes) { iterator.remove(); } return query.getResult(projection); } } if (mExpectedQueries.isEmpty()) { Assert.fail("Unexpected query: " + queryToString(uri, projection, selection, selectionArgs, sortOrder)); } else { StringBuilder sb = new StringBuilder(); sb.append(mExpectedQueries.get(0)); for (int i = 1; i < mExpectedQueries.size(); i++) { sb.append("\n ").append(mExpectedQueries.get(i)); } Assert.fail("Incorrect query.\n Expected: " + sb + "\n Actual: " + queryToString(uri, projection, selection, selectionArgs, sortOrder)); } return null; } @Override public int delete(Uri uri, String selection, String[] selectionArgs) { throw new UnsupportedOperationException(); } @Override public String getType(Uri uri) { if (mExpectedTypeQueries.isEmpty()) { Assert.fail("Unexpected getType query: " + uri); } String mimeType = mExpectedTypeQueries.get(uri); if (mimeType != null) { return mimeType; } Assert.fail("Unknown mime type for: " + uri); return null; } @Override public Uri insert(Uri uri, ContentValues values) { throw new UnsupportedOperationException(); } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { throw new UnsupportedOperationException(); } private static String queryToString(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { StringBuilder sb = new StringBuilder(); sb.append(uri).append(" "); if (projection != null) { sb.append(Arrays.toString(projection)); } else { sb.append("[]"); } if (selection != null) { sb.append(" selection: '").append(selection).append("'"); if (selectionArgs != null) { sb.append(Arrays.toString(selectionArgs)); } else { sb.append("[]"); } } if (sortOrder != null) { sb.append(" sort: '").append(sortOrder).append("'"); } return sb.toString(); } public void verify() { ArrayList<Query> mMissedQueries = Lists.newArrayList(); for (Query query : mExpectedQueries) { if (!query.mExecuted) { mMissedQueries.add(query); } } Assert.assertTrue("Not all expected queries have been called: " + mMissedQueries, mMissedQueries.isEmpty()); } }