Home | History | Annotate | Download | only in mocks
      1 /*
      2  * Copyright (C) 2010 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 com.android.contacts.common.test.mocks;
     18 
     19 import android.content.ContentProvider;
     20 import android.content.ContentValues;
     21 import android.database.Cursor;
     22 import android.database.MatrixCursor;
     23 import android.net.Uri;
     24 import android.text.TextUtils;
     25 
     26 import com.google.common.collect.Lists;
     27 import com.google.common.collect.Maps;
     28 
     29 import junit.framework.Assert;
     30 
     31 import java.util.ArrayList;
     32 import java.util.Arrays;
     33 import java.util.HashMap;
     34 import java.util.Iterator;
     35 
     36 /**
     37  * A programmable mock content provider.
     38  */
     39 public class MockContentProvider extends ContentProvider {
     40     private static final String TAG = "MockContentProvider";
     41 
     42     public static class Query {
     43 
     44         private final Uri mUri;
     45         private String[] mProjection;
     46         private String[] mDefaultProjection;
     47         private String mSelection;
     48         private String[] mSelectionArgs;
     49         private String mSortOrder;
     50         private ArrayList<Object> mRows = new ArrayList<Object>();
     51         private boolean mAnyProjection;
     52         private boolean mAnySelection;
     53         private boolean mAnySortOrder;
     54         private boolean mAnyNumberOfTimes;
     55 
     56         private boolean mExecuted;
     57 
     58         public Query(Uri uri) {
     59             mUri = uri;
     60         }
     61 
     62         @Override
     63         public String toString() {
     64             return queryToString(mUri, mProjection, mSelection, mSelectionArgs, mSortOrder);
     65         }
     66 
     67         public Query withProjection(String... projection) {
     68             mProjection = projection;
     69             return this;
     70         }
     71 
     72         public Query withDefaultProjection(String... projection) {
     73             mDefaultProjection = projection;
     74             return this;
     75         }
     76 
     77         public Query withAnyProjection() {
     78             mAnyProjection = true;
     79             return this;
     80         }
     81 
     82         public Query withSelection(String selection, String... selectionArgs) {
     83             mSelection = selection;
     84             mSelectionArgs = selectionArgs;
     85             return this;
     86         }
     87 
     88         public Query withAnySelection() {
     89             mAnySelection = true;
     90             return this;
     91         }
     92 
     93         public Query withSortOrder(String sortOrder) {
     94             mSortOrder = sortOrder;
     95             return this;
     96         }
     97 
     98         public Query withAnySortOrder() {
     99             mAnySortOrder = true;
    100             return this;
    101         }
    102 
    103         public Query returnRow(ContentValues values) {
    104             mRows.add(values);
    105             return this;
    106         }
    107 
    108         public Query returnRow(Object... row) {
    109             mRows.add(row);
    110             return this;
    111         }
    112 
    113         public Query returnEmptyCursor() {
    114             mRows.clear();
    115             return this;
    116         }
    117 
    118         public Query anyNumberOfTimes() {
    119             mAnyNumberOfTimes = true;
    120             return this;
    121         }
    122 
    123         public boolean equals(Uri uri, String[] projection, String selection,
    124                 String[] selectionArgs, String sortOrder) {
    125             if (!uri.equals(mUri)) {
    126                 return false;
    127             }
    128 
    129             if (!mAnyProjection && !equals(projection, mProjection)) {
    130                 return false;
    131             }
    132 
    133             if (!mAnySelection && !equals(selection, mSelection)) {
    134                 return false;
    135             }
    136 
    137             if (!mAnySelection && !equals(selectionArgs, mSelectionArgs)) {
    138                 return false;
    139             }
    140 
    141             if (!mAnySortOrder && !equals(sortOrder, mSortOrder)) {
    142                 return false;
    143             }
    144 
    145             return true;
    146         }
    147 
    148         private boolean equals(String string1, String string2) {
    149             if (TextUtils.isEmpty(string1)) {
    150                 string1 = null;
    151             }
    152             if (TextUtils.isEmpty(string2)) {
    153                 string2 = null;
    154             }
    155             return TextUtils.equals(string1, string2);
    156         }
    157 
    158         private static boolean equals(String[] array1, String[] array2) {
    159             boolean empty1 = array1 == null || array1.length == 0;
    160             boolean empty2 = array2 == null || array2.length == 0;
    161             if (empty1 && empty2) {
    162                 return true;
    163             }
    164             if (empty1 != empty2 && (empty1 || empty2)) {
    165                 return false;
    166             }
    167 
    168             if (array1.length != array2.length) return false;
    169 
    170             for (int i = 0; i < array1.length; i++) {
    171                 if (!array1[i].equals(array2[i])) {
    172                     return false;
    173                 }
    174             }
    175             return true;
    176         }
    177 
    178         public Cursor getResult(String[] projection) {
    179             String[] columnNames;
    180             if (mAnyProjection) {
    181                 columnNames = projection;
    182             } else {
    183                 columnNames = mProjection != null ? mProjection : mDefaultProjection;
    184             }
    185 
    186             MatrixCursor cursor = new MatrixCursor(columnNames);
    187             for (Object row : mRows) {
    188                 if (row instanceof Object[]) {
    189                     cursor.addRow((Object[]) row);
    190                 } else {
    191                     ContentValues values = (ContentValues) row;
    192                     Object[] columns = new Object[projection.length];
    193                     for (int i = 0; i < projection.length; i++) {
    194                         columns[i] = values.get(projection[i]);
    195                     }
    196                     cursor.addRow(columns);
    197                 }
    198             }
    199             return cursor;
    200         }
    201     }
    202 
    203     public static class TypeQuery {
    204         private final Uri mUri;
    205         private final String mType;
    206 
    207         public TypeQuery(Uri uri, String type) {
    208             mUri = uri;
    209             mType = type;
    210         }
    211 
    212         public Uri getUri() {
    213             return mUri;
    214         }
    215 
    216         public String getType() {
    217             return mType;
    218         }
    219 
    220         @Override
    221         public String toString() {
    222             return mUri + " --> " + mType;
    223         }
    224 
    225         public boolean equals(Uri uri) {
    226             return getUri().equals(uri);
    227         }
    228     }
    229 
    230     private ArrayList<Query> mExpectedQueries = new ArrayList<Query>();
    231     private HashMap<Uri, String> mExpectedTypeQueries = Maps.newHashMap();
    232 
    233     @Override
    234     public boolean onCreate() {
    235         return true;
    236     }
    237 
    238     public Query expectQuery(Uri contentUri) {
    239         Query query = new Query(contentUri);
    240         mExpectedQueries.add(query);
    241         return query;
    242     }
    243 
    244     public void expectTypeQuery(Uri uri, String type) {
    245         mExpectedTypeQueries.put(uri, type);
    246     }
    247 
    248     @Override
    249     public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
    250             String sortOrder) {
    251 
    252         for (Iterator<Query> iterator = mExpectedQueries.iterator(); iterator.hasNext();) {
    253             Query query = iterator.next();
    254             if (query.equals(uri, projection, selection, selectionArgs, sortOrder)) {
    255                 query.mExecuted = true;
    256                 if (!query.mAnyNumberOfTimes) {
    257                     iterator.remove();
    258                 }
    259                 return query.getResult(projection);
    260             }
    261         }
    262 
    263         if (mExpectedQueries.isEmpty()) {
    264             Assert.fail("Unexpected query: "
    265                     + queryToString(uri, projection, selection, selectionArgs, sortOrder));
    266         } else {
    267             StringBuilder sb = new StringBuilder();
    268             sb.append(mExpectedQueries.get(0));
    269             for (int i = 1; i < mExpectedQueries.size(); i++) {
    270                 sb.append("\n              ").append(mExpectedQueries.get(i));
    271             }
    272             Assert.fail("Incorrect query.\n    Expected: " + sb + "\n      Actual: " +
    273                     queryToString(uri, projection, selection, selectionArgs, sortOrder));
    274         }
    275         return null;
    276     }
    277 
    278     @Override
    279     public int delete(Uri uri, String selection, String[] selectionArgs) {
    280         throw new UnsupportedOperationException();
    281     }
    282 
    283     @Override
    284     public String getType(Uri uri) {
    285         if (mExpectedTypeQueries.isEmpty()) {
    286             Assert.fail("Unexpected getType query: " + uri);
    287         }
    288 
    289         String mimeType = mExpectedTypeQueries.get(uri);
    290         if (mimeType != null) {
    291             return mimeType;
    292         }
    293 
    294         Assert.fail("Unknown mime type for: " + uri);
    295         return null;
    296     }
    297 
    298     @Override
    299     public Uri insert(Uri uri, ContentValues values) {
    300         throw new UnsupportedOperationException();
    301     }
    302 
    303     @Override
    304     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
    305         throw new UnsupportedOperationException();
    306     }
    307 
    308     private static String queryToString(Uri uri, String[] projection, String selection,
    309             String[] selectionArgs, String sortOrder) {
    310         StringBuilder sb = new StringBuilder();
    311         sb.append(uri).append(" ");
    312         if (projection != null) {
    313             sb.append(Arrays.toString(projection));
    314         } else {
    315             sb.append("[]");
    316         }
    317         if (selection != null) {
    318             sb.append(" selection: '").append(selection).append("'");
    319             if (selectionArgs != null) {
    320                 sb.append(Arrays.toString(selectionArgs));
    321             } else {
    322                 sb.append("[]");
    323             }
    324         }
    325         if (sortOrder != null) {
    326             sb.append(" sort: '").append(sortOrder).append("'");
    327         }
    328         return sb.toString();
    329     }
    330 
    331     public void verify() {
    332         ArrayList<Query> mMissedQueries = Lists.newArrayList();
    333         for (Query query : mExpectedQueries) {
    334             if (!query.mExecuted) {
    335                 mMissedQueries.add(query);
    336             }
    337         }
    338         Assert.assertTrue("Not all expected queries have been called: " +
    339                 mMissedQueries, mMissedQueries.isEmpty());
    340     }
    341 }
    342