diff options
| -rw-r--r-- | core/java/android/content/ContentProvider.java | 33 | ||||
| -rw-r--r-- | test-runner/src/android/test/ProviderTestCase.java | 12 | ||||
| -rw-r--r-- | test-runner/src/android/test/ProviderTestCase2.java | 12 |
3 files changed, 57 insertions, 0 deletions
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 9b9f796..a3252ed 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -32,6 +32,7 @@ import android.os.Binder; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.Process; +import android.util.Log; import java.io.File; import java.io.FileNotFoundException; @@ -76,6 +77,8 @@ import java.util.ArrayList; * cross-process calls.</p> */ public abstract class ContentProvider implements ComponentCallbacks { + private static final String TAG = "ContentProvider"; + /* * Note: if you add methods to ContentProvider, you must add similar methods to * MockContentProvider. @@ -831,4 +834,34 @@ public abstract class ContentProvider implements ComponentCallbacks { public Bundle call(String method, String request, Bundle args) { return null; } + + /** + * Shuts down this instance of the ContentProvider. It is useful when writing tests that use + * the ContentProvider. + * <p> + * If a unittest starts the ContentProvider in its test(..() methods, it could run into sqlite + * errors "disk I/O error" or "corruption" in the following scenario: + * <ul> + * <li>Say, there are 2 test methods in the unittest</li> + * <li>test1() (or setUp()) causes ContentProvider object to be initialized and + * assume it opens a database connection to "foo.db"</li> + * <li>est1() completes and test2() starts</li> + * <li>During the execution of test2() there will be 2 connections to "foo.db"</li> + * <li>Different threads in the ContentProvider may have one of these two connection + * handles. This is not a problem per se</li> + * <li>But if the two threads with 2 database connections don't interact correctly, + * there could be unexpected errors from sqlite</li> + * <li>Some of those unexpected errros are "disk I/O error" or "corruption" error</li> + * <li>Common practice in tearDown() is to delete test directory (and the database files)</li> + * <li>If this is done while some threads are still holding unclosed database connections, + * sqlite quite easily gets into corruption and disk I/O errors</li> + * </ul> + * <p> + * tearDown() in the unittests should call this method to have ContentProvider gracefully + * shutdown all database connections. + */ + public void shutdown() { + Log.w(TAG, "implement ContentProvider shutdown() to make sure all database " + + "connections are gracefully shutdown"); + } } diff --git a/test-runner/src/android/test/ProviderTestCase.java b/test-runner/src/android/test/ProviderTestCase.java index e1172cf..1ffda26 100644 --- a/test-runner/src/android/test/ProviderTestCase.java +++ b/test-runner/src/android/test/ProviderTestCase.java @@ -73,6 +73,18 @@ public abstract class ProviderTestCase<T extends ContentProvider> mResolver.addProvider(mProviderAuthority, getProvider()); } + /** + * Tears down the environment for the test fixture. + * <p> + * Calls {@link android.content.ContentProvider#shutdown()} on the + * {@link android.content.ContentProvider} represented by {@link #mProvider} + */ + @Override + protected void tearDown() throws Exception { + mProvider.shutdown(); + super.tearDown(); + } + public MockContentResolver getMockContentResolver() { return mResolver; } diff --git a/test-runner/src/android/test/ProviderTestCase2.java b/test-runner/src/android/test/ProviderTestCase2.java index 1fb5538..feb5ef4 100644 --- a/test-runner/src/android/test/ProviderTestCase2.java +++ b/test-runner/src/android/test/ProviderTestCase2.java @@ -141,6 +141,18 @@ public abstract class ProviderTestCase2<T extends ContentProvider> extends Andro } /** + * Tears down the environment for the test fixture. + * <p> + * Calls {@link android.content.ContentProvider#shutdown()} on the + * {@link android.content.ContentProvider} represented by {@link #mProvider}. + */ + @Override + protected void tearDown() throws Exception { + mProvider.shutdown(); + super.tearDown(); + } + + /** * Gets the {@link MockContentResolver} created by this class during initialization. You * must use the methods of this resolver to access the provider under test. * |
