Home | History | Annotate | Download | only in utils
      1 /*
      2  * Copyright (C) 2011 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.browser.tests.utils;
     18 
     19 import com.android.browser.provider.BrowserProvider2;
     20 
     21 import java.io.File;
     22 import java.io.FilenameFilter;
     23 
     24 import android.content.ContentValues;
     25 import android.database.ContentObserver;
     26 import android.net.Uri;
     27 import android.provider.Browser;
     28 import android.provider.BrowserContract;
     29 import android.provider.BrowserContract.Bookmarks;
     30 import android.provider.BrowserContract.History;
     31 import android.util.Log;
     32 
     33 /**
     34  *  This is a replacement for ProviderTestCase2 that can handle notifyChange testing.
     35  *  It also has helper methods specifically for testing BrowserProvider2
     36  */
     37 public abstract class BP2TestCaseHelper extends ProviderTestCase3<BrowserProvider2> {
     38 
     39     // Tag for potential performance impacts
     40     private static final String PERFTAG = "BP2-PerfCheck";
     41 
     42     private TriggeredObserver mLegacyObserver;
     43     private TriggeredObserver mRootObserver;
     44     private TriggeredObserver mBookmarksObserver;
     45     private TriggeredObserver mHistoryObserver;
     46     private TriggeredObserver mWidgetObserver;
     47 
     48     @Override
     49     protected void setUp() throws Exception {
     50         super.setUp();
     51         mLegacyObserver = new TriggeredObserver(Browser.BOOKMARKS_URI);
     52         mRootObserver = new TriggeredObserver(BrowserContract.AUTHORITY_URI);
     53         mBookmarksObserver = new TriggeredObserver(Bookmarks.CONTENT_URI);
     54         mHistoryObserver = new TriggeredObserver(History.CONTENT_URI);
     55         mWidgetObserver = new TriggeredObserver();
     56         // We don't need to worry about setting this back to null since this
     57         // is a private instance local to the MockContentResolver
     58         getProvider().setWidgetObserver(mWidgetObserver);
     59     }
     60 
     61     public BP2TestCaseHelper() {
     62         super(BrowserProvider2.class,
     63                 BrowserContract.AUTHORITY, BrowserProvider2.LEGACY_AUTHORITY);
     64     }
     65 
     66     public void perfIdeallyUntriggered(TriggeredObserver... obs) {
     67         for (TriggeredObserver ob : obs) {
     68             if (ob.checkTriggered()) {
     69                 // Not ideal, unnecessary notification
     70                 Log.i(PERFTAG, ob.mUri + " onChange called but content unaltered!");
     71             }
     72         }
     73     }
     74 
     75     public void assertObserversTriggered(boolean triggered,
     76             TriggeredObserver... observers) {
     77         for (TriggeredObserver obs : observers) {
     78             assertEquals(obs.mUri + ", descendents:" + obs.mNotifyForDescendents,
     79                     triggered, obs.checkTriggered());
     80         }
     81     }
     82 
     83     public class TriggeredObserver extends ContentObserver {
     84         private boolean mTriggered;
     85         Uri mUri;
     86         boolean mNotifyForDescendents;
     87 
     88         /**
     89          * Creates an unmanaged TriggeredObserver
     90          */
     91         public TriggeredObserver() {
     92             super(null);
     93         }
     94 
     95         /**
     96          * Same as TriggeredObserver(uri, true);
     97          */
     98         public TriggeredObserver(Uri uri) {
     99             this(uri, true);
    100         }
    101 
    102         /**
    103          * Creates a managed TriggeredObserver that self-registers with the
    104          * mock ContentResolver
    105          */
    106         public TriggeredObserver(Uri uri, boolean notifyForDescendents) {
    107             super(null);
    108             mUri = uri;
    109             mNotifyForDescendents = notifyForDescendents;
    110             registerContentObserver(uri, notifyForDescendents, this);
    111         }
    112 
    113         @Override
    114         public void onChange(boolean selfChange) {
    115             super.onChange(selfChange);
    116             mTriggered = true;
    117         }
    118 
    119         public boolean checkTriggered() {
    120             boolean ret = mTriggered;
    121             mTriggered = false;
    122             return ret;
    123         }
    124     }
    125 
    126     Uri mockInsert(Uri uri, ContentValues values) {
    127         assertObserversTriggered(false, mLegacyObserver, mRootObserver);
    128         Uri ret = getMockContentResolver().insert(uri, values);
    129         assertObserversTriggered(true, mLegacyObserver, mRootObserver);
    130         return ret;
    131     }
    132 
    133     int mockUpdate(Uri uri, ContentValues values, String where,
    134             String[] selectionArgs) {
    135         assertObserversTriggered(false, mLegacyObserver, mRootObserver);
    136         int ret = getMockContentResolver().update(uri, values, where, selectionArgs);
    137         if (ret > 0) {
    138             assertObserversTriggered(true, mLegacyObserver, mRootObserver);
    139         } else {
    140             perfIdeallyUntriggered(mLegacyObserver);
    141             perfIdeallyUntriggered(mRootObserver);
    142         }
    143         return ret;
    144     }
    145 
    146     public Uri insertBookmark(String url, String title) {
    147         ContentValues values = new ContentValues();
    148         values.put(BrowserContract.Bookmarks.TITLE, title);
    149         values.put(BrowserContract.Bookmarks.URL, url);
    150         values.put(BrowserContract.Bookmarks.IS_FOLDER, 0);
    151         return insertBookmark(values);
    152     }
    153 
    154     public Uri insertBookmark(ContentValues values) {
    155         assertObserversTriggered(false, mBookmarksObserver, mWidgetObserver);
    156         Uri ret = mockInsert(Bookmarks.CONTENT_URI, values);
    157         assertObserversTriggered(true, mBookmarksObserver, mWidgetObserver);
    158         perfIdeallyUntriggered(mHistoryObserver);
    159         return ret;
    160     }
    161 
    162     public boolean updateBookmark(Uri uri, String url, String title) {
    163         ContentValues values = new ContentValues();
    164         values.put(BrowserContract.Bookmarks.TITLE, title);
    165         values.put(BrowserContract.Bookmarks.URL, url);
    166         return updateBookmark(uri, values);
    167     }
    168 
    169     public boolean updateBookmark(Uri uri, ContentValues values) {
    170         assertObserversTriggered(false, mBookmarksObserver, mWidgetObserver);
    171         int modifyCount = mockUpdate(uri, values, null, null);
    172         assertTrue("UpdatedBookmark modified too much! " + uri, modifyCount <= 1);
    173         boolean updated = modifyCount == 1;
    174         if (updated) {
    175             assertObserversTriggered(updated, mBookmarksObserver, mWidgetObserver);
    176         } else {
    177             perfIdeallyUntriggered(mBookmarksObserver, mWidgetObserver);
    178         }
    179         perfIdeallyUntriggered(mHistoryObserver);
    180         return updated;
    181     }
    182 
    183     public Uri insertHistory(String url, String title) {
    184         ContentValues values = new ContentValues();
    185         values.put(BrowserContract.History.TITLE, title);
    186         values.put(BrowserContract.History.URL, url);
    187         assertObserversTriggered(false, mHistoryObserver);
    188         Uri ret = mockInsert(History.CONTENT_URI, values);
    189         assertObserversTriggered(true, mHistoryObserver);
    190         perfIdeallyUntriggered(mBookmarksObserver, mWidgetObserver);
    191         return ret;
    192     }
    193 
    194     public boolean updateHistory(Uri uri, String url, String title) {
    195         ContentValues values = new ContentValues();
    196         values.put(BrowserContract.History.TITLE, title);
    197         values.put(BrowserContract.History.URL, url);
    198         return updateHistory(uri, values);
    199     }
    200 
    201     public boolean updateHistory(Uri uri, ContentValues values) {
    202         assertObserversTriggered(false, mHistoryObserver);
    203         int modifyCount = mockUpdate(uri, values, null, null);
    204         assertTrue("UpdatedHistory modified too much! " + uri, modifyCount <= 1);
    205         boolean updated = modifyCount == 1;
    206         if (updated) {
    207             assertObserversTriggered(updated, mHistoryObserver);
    208         } else {
    209             perfIdeallyUntriggered(mHistoryObserver);
    210         }
    211         perfIdeallyUntriggered(mBookmarksObserver, mWidgetObserver);
    212         return updated;
    213     }
    214 
    215     @Override
    216     protected void tearDown() throws Exception {
    217         super.tearDown();
    218         // Delete the test databases so that subsequent runs have a clean slate
    219         File f = getMockContext().getDatabasePath("test");
    220         File dir = f.getParentFile();
    221         File testFiles[] = dir.listFiles(new FilenameFilter() {
    222 
    223             @Override
    224             public boolean accept(File dir, String filename) {
    225                 return filename.startsWith(ProviderTestCase3.FILENAME_PREFIX);
    226             }
    227         });
    228         for (File testFile : testFiles) {
    229             testFile.delete();
    230         }
    231     }
    232 }
    233