diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowContentProviderClientTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowContentProviderClientTest.java index 6954bd678ce..a50e9c73522 100644 --- a/robolectric/src/test/java/org/robolectric/shadows/ShadowContentProviderClientTest.java +++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowContentProviderClientTest.java @@ -1,60 +1,65 @@ package org.robolectric.shadows; -import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; +import static android.os.Build.VERSION_CODES.M; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.verify; -import static org.mockito.MockitoAnnotations.initMocks; +import static org.junit.Assert.assertThrows; import static org.robolectric.Shadows.shadowOf; import android.content.ContentProvider; import android.content.ContentProviderClient; -import android.content.ContentProviderOperation; import android.content.ContentResolver; -import android.content.ContentValues; -import android.net.Uri; -import android.os.Bundle; -import android.os.CancellationSignal; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import java.util.ArrayList; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.android.controller.ContentProviderController; import org.robolectric.annotation.Config; +import org.robolectric.shadows.testing.TestContentProvider1; @RunWith(AndroidJUnit4.class) public class ShadowContentProviderClientTest { private static final String AUTHORITY = "org.robolectric"; - private final Uri URI = Uri.parse("content://" + AUTHORITY); - private final ContentValues VALUES = new ContentValues(); - private static final String[] PROJECTION = null; - private static final String SELECTION = "1=?"; - private static final String[] SELECTION_ARGS = {"1"}; - private static final String SORT_ORDER = "DESC"; - private static final String MIME_TYPE = "application/octet-stream"; - @Mock ContentProvider provider; + private final ContentProviderController controller = + Robolectric.buildContentProvider(TestContentProvider1.class); + + ContentProvider provider = controller.create().get(); + ContentResolver contentResolver = ApplicationProvider.getApplicationContext().getContentResolver(); + ContentProviderClient client; + @Before public void setUp() { - initMocks(this); ShadowContentResolver.registerProviderInternal(AUTHORITY, provider); } + @After + public void tearDown() { + if (client != null) { + if (RuntimeEnvironment.getApiLevel() > M) { + client.close(); + } else { + client.release(); + } + } + } + @Test public void acquireContentProviderClient_isStable() { - ContentProviderClient client = contentResolver.acquireContentProviderClient(AUTHORITY); + client = contentResolver.acquireContentProviderClient(AUTHORITY); assertThat(shadowOf(client).isStable()).isTrue(); } @Test public void acquireUnstableContentProviderClient_isUnstable() { - ContentProviderClient client = contentResolver.acquireUnstableContentProviderClient(AUTHORITY); + client = contentResolver.acquireUnstableContentProviderClient(AUTHORITY); assertThat(shadowOf(client).isStable()).isFalse(); } @@ -67,63 +72,11 @@ public void release_shouldRelease() { assertThat(shadow.isReleased()).isTrue(); } - @Test(expected = IllegalStateException.class) + @Test + @Config(maxSdk = M) public void release_shouldFailWhenCalledTwice() { ContentProviderClient client = contentResolver.acquireContentProviderClient(AUTHORITY); client.release(); - client.release(); - fail("client.release() was called twice and did not throw"); - } - - @Test - @Config(minSdk = JELLY_BEAN_MR2) - public void shouldDelegateToContentProvider() throws Exception { - ContentProviderClient client = contentResolver.acquireContentProviderClient(AUTHORITY); - - client.query(URI, PROJECTION, SELECTION, SELECTION_ARGS, SORT_ORDER); - verify(provider).query(URI, PROJECTION, SELECTION, SELECTION_ARGS, SORT_ORDER); - - CancellationSignal signal = new CancellationSignal(); - client.query(URI, PROJECTION, SELECTION, SELECTION_ARGS, SORT_ORDER, signal); - verify(provider).query(URI, PROJECTION, SELECTION, SELECTION_ARGS, SORT_ORDER, signal); - - client.insert(URI, VALUES); - verify(provider).insert(URI, VALUES); - - client.update(URI, VALUES, SELECTION, SELECTION_ARGS); - verify(provider).update(URI, VALUES, SELECTION, SELECTION_ARGS); - - client.delete(URI, SELECTION, SELECTION_ARGS); - verify(provider).delete(URI, SELECTION, SELECTION_ARGS); - - client.getType(URI); - verify(provider).getType(URI); - - client.openFile(URI, "rw"); - verify(provider).openFile(URI, "rw"); - - client.openAssetFile(URI, "r"); - verify(provider).openAssetFile(URI, "r"); - - final Bundle opts = new Bundle(); - client.openTypedAssetFileDescriptor(URI, MIME_TYPE, opts); - verify(provider).openTypedAssetFile(URI, MIME_TYPE, opts); - - client.getStreamTypes(URI, MIME_TYPE); - verify(provider).getStreamTypes(URI, MIME_TYPE); - - final ArrayList ops = new ArrayList<>(); - client.applyBatch(ops); - verify(provider).applyBatch(ops); - - final ContentValues[] values = {VALUES}; - client.bulkInsert(URI, values); - verify(provider).bulkInsert(URI, values); - - final String method = "method"; - final String arg = "arg"; - final Bundle extras = new Bundle(); - client.call(method, arg, extras); - verify(provider).call(method, arg, extras); + assertThrows(IllegalStateException.class, () -> client.release()); } } diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowContentProviderClient.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowContentProviderClient.java index ce4ec846d27..4652869c09d 100644 --- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowContentProviderClient.java +++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowContentProviderClient.java @@ -1,6 +1,7 @@ package org.robolectric.shadows; import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; +import static org.robolectric.util.reflector.Reflector.reflector; import android.content.ContentProvider; import android.content.ContentProviderClient; @@ -11,22 +12,26 @@ import android.content.res.AssetFileDescriptor; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import java.io.FileNotFoundException; import java.util.ArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.annotation.RealObject; -import org.robolectric.util.ReflectionHelpers; +import org.robolectric.util.reflector.Accessor; +import org.robolectric.util.reflector.Direct; +import org.robolectric.util.reflector.ForType; @Implements(ContentProviderClient.class) public class ShadowContentProviderClient { @RealObject private ContentProviderClient realContentProviderClient; - private boolean released; private ContentProvider provider; @Implementation(minSdk = JELLY_BEAN_MR1) @@ -108,31 +113,41 @@ protected ContentProviderResult[] applyBatch(ArrayList return provider.applyBatch(operations); } - @Implementation - protected boolean release() { - synchronized (this) { - if (released) { - throw new IllegalStateException("Already released"); - } - released = true; - } - return true; - } - @Implementation protected ContentProvider getLocalContentProvider() { return ContentProvider.coerceToLocalContentProvider(provider.getIContentProvider()); } public boolean isStable() { - return ReflectionHelpers.getField(realContentProviderClient, "mStable"); + return reflector(ContentProviderClientReflector.class, realContentProviderClient).getStable(); } public boolean isReleased() { - return released; + ContentProviderClientReflector contentProviderClientReflector = + reflector(ContentProviderClientReflector.class, realContentProviderClient); + if (RuntimeEnvironment.getApiLevel() <= Build.VERSION_CODES.M) { + return contentProviderClientReflector.getReleased(); + } else { + return contentProviderClientReflector.getClosed().get(); + } } void setContentProvider(ContentProvider provider) { this.provider = provider; } + + @ForType(ContentProviderClient.class) + interface ContentProviderClientReflector { + @Direct + boolean release(); + + @Accessor("mStable") + boolean getStable(); + + @Accessor("mReleased") + boolean getReleased(); + + @Accessor("mClosed") + AtomicBoolean getClosed(); + } }