From 0c9e14aa4aa1370e01872dc05238f822f2dd552c Mon Sep 17 00:00:00 2001
From: Vasu Nori
Date: Wed, 4 Aug 2010 13:31:48 -0700
Subject: add shutdown() to ContentProvider & call in
ProviderTestCase*.tearDown
Change-Id: I3dd69b6907d68b7c1184139f22297ab92337f043
---
core/java/android/content/ContentProvider.java | 33 ++++++++++++++++++++++
test-runner/src/android/test/ProviderTestCase.java | 12 ++++++++
.../src/android/test/ProviderTestCase2.java | 12 ++++++++
3 files changed, 57 insertions(+)
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 9b9f796a1607..a3252ed2f40c 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.
*/
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.
+ *
+ * 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:
+ *
+ * - Say, there are 2 test methods in the unittest
+ * - test1() (or setUp()) causes ContentProvider object to be initialized and
+ * assume it opens a database connection to "foo.db"
+ * - est1() completes and test2() starts
+ * - During the execution of test2() there will be 2 connections to "foo.db"
+ * - Different threads in the ContentProvider may have one of these two connection
+ * handles. This is not a problem per se
+ * - But if the two threads with 2 database connections don't interact correctly,
+ * there could be unexpected errors from sqlite
+ * - Some of those unexpected errros are "disk I/O error" or "corruption" error
+ * - Common practice in tearDown() is to delete test directory (and the database files)
+ * - If this is done while some threads are still holding unclosed database connections,
+ * sqlite quite easily gets into corruption and disk I/O errors
+ *
+ *
+ * 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 e1172cf21ff7..1ffda2681e1b 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
mResolver.addProvider(mProviderAuthority, getProvider());
}
+ /**
+ * Tears down the environment for the test fixture.
+ *
+ * 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 1fb5538d6ef2..feb5ef464fbd 100644
--- a/test-runner/src/android/test/ProviderTestCase2.java
+++ b/test-runner/src/android/test/ProviderTestCase2.java
@@ -140,6 +140,18 @@ public abstract class ProviderTestCase2 extends Andro
mResolver.addProvider(mProviderAuthority, getProvider());
}
+ /**
+ * Tears down the environment for the test fixture.
+ *
+ * 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.
--
cgit v1.2.3-59-g8ed1b