mirror of
https://github.com/f-droid/fdroidclient.git
synced 2026-06-19 05:10:05 -04:00
Ported AppProvider tests to Robolectric.
Get around silly `final` methods in `ContentResolver` with Mockito and `delegatesTo`. The Robolectric library presumes that people always want to test content providers by manually invoking the `query`/`update`/`delete` methods on the `ShadowContentResolver`. While that is a great feature for testing, we have helper methods that require testing, and these methods accept either a _real_ `ContentResolver` or `Context`. Robolectric did some cool magic in terms of intercepting runtime calls to content resolvers and forwarding them to the "shadow" verison, to deal with final/package private/etc methods. However, as a side effect, the `ShadowContentProvider` _is not a `ContentProvider` as far as the Java compiler is concerned. By utilising Mockito + `delegatesTo` method, we are able to achieve what is required: * An actual `ContentProvider` instance. * It forwards calls to the `ShadowContentProvider` provided by Robolectric.
This commit is contained in:
374
app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java
Normal file
374
app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java
Normal file
@@ -0,0 +1,374 @@
|
||||
package org.fdroid.fdroid.data;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
import org.fdroid.fdroid.R;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertContainsOnly;
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertResultCount;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@Config(constants = BuildConfig.class, application = Application.class)
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
public class AppProviderTest extends FDroidProviderTest {
|
||||
|
||||
private static final String[] PROJ = AppProvider.DataColumns.ALL;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
ShadowContentResolver.registerProvider(AppProvider.getAuthority(), new AppProvider());
|
||||
}
|
||||
|
||||
/**
|
||||
* Although this doesn't directly relate to the {@link AppProvider}, it is here because
|
||||
* the {@link AppProvider} used to stumble across this bug when asking for installed apps,
|
||||
* and the device had over 1000 apps installed.
|
||||
*/
|
||||
@Test
|
||||
public void testMaxSqliteParams() {
|
||||
insertApp("com.example.app1", "App 1");
|
||||
insertApp("com.example.app100", "App 100");
|
||||
insertApp("com.example.app1000", "App 1000");
|
||||
|
||||
for (int i = 0; i < 50; i++) {
|
||||
InstalledAppTestUtils.install(context, "com.example.app" + i, 1, "v1");
|
||||
}
|
||||
assertResultCount(contentResolver, 1, AppProvider.getInstalledUri(), PROJ);
|
||||
|
||||
for (int i = 50; i < 500; i++) {
|
||||
InstalledAppTestUtils.install(context, "com.example.app" + i, 1, "v1");
|
||||
}
|
||||
assertResultCount(contentResolver, 2, AppProvider.getInstalledUri(), PROJ);
|
||||
|
||||
for (int i = 500; i < 1100; i++) {
|
||||
InstalledAppTestUtils.install(context, "com.example.app" + i, 1, "v1");
|
||||
}
|
||||
assertResultCount(contentResolver, 3, AppProvider.getInstalledUri(), PROJ);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCantFindApp() {
|
||||
assertNull(AppProvider.Helper.findByPackageName(context.getContentResolver(), "com.example.doesnt-exist"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuery() {
|
||||
Cursor cursor = queryAllApps();
|
||||
assertNotNull(cursor);
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
private void insertApps(int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
insertApp("com.example.test." + i, "Test app " + i);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertAndInstallApp(
|
||||
String packageName, int installedVercode, int suggestedVercode,
|
||||
boolean ignoreAll, int ignoreVercode) {
|
||||
ContentValues values = new ContentValues(3);
|
||||
values.put(AppProvider.DataColumns.SUGGESTED_VERSION_CODE, suggestedVercode);
|
||||
values.put(AppProvider.DataColumns.IGNORE_ALLUPDATES, ignoreAll);
|
||||
values.put(AppProvider.DataColumns.IGNORE_THISUPDATE, ignoreVercode);
|
||||
insertApp(packageName, "App: " + packageName, values);
|
||||
|
||||
InstalledAppTestUtils.install(context, packageName, installedVercode, "v" + installedVercode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanUpdate() {
|
||||
insertApp("not installed", "not installed");
|
||||
insertAndInstallApp("installed, only one version available", 1, 1, false, 0);
|
||||
insertAndInstallApp("installed, already latest, no ignore", 10, 10, false, 0);
|
||||
insertAndInstallApp("installed, already latest, ignore all", 10, 10, true, 0);
|
||||
insertAndInstallApp("installed, already latest, ignore latest", 10, 10, false, 10);
|
||||
insertAndInstallApp("installed, already latest, ignore old", 10, 10, false, 5);
|
||||
insertAndInstallApp("installed, old version, no ignore", 5, 10, false, 0);
|
||||
insertAndInstallApp("installed, old version, ignore all", 5, 10, true, 0);
|
||||
insertAndInstallApp("installed, old version, ignore latest", 5, 10, false, 10);
|
||||
insertAndInstallApp("installed, old version, ignore newer, but not latest", 5, 10, false, 8);
|
||||
|
||||
ContentResolver r = context.getContentResolver();
|
||||
|
||||
// Can't "update", although can "install"...
|
||||
App notInstalled = AppProvider.Helper.findByPackageName(r, "not installed");
|
||||
assertFalse(notInstalled.canAndWantToUpdate());
|
||||
|
||||
App installedOnlyOneVersionAvailable = AppProvider.Helper.findByPackageName(r, "installed, only one version available");
|
||||
App installedAlreadyLatestNoIgnore = AppProvider.Helper.findByPackageName(r, "installed, already latest, no ignore");
|
||||
App installedAlreadyLatestIgnoreAll = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore all");
|
||||
App installedAlreadyLatestIgnoreLatest = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore latest");
|
||||
App installedAlreadyLatestIgnoreOld = AppProvider.Helper.findByPackageName(r, "installed, already latest, ignore old");
|
||||
|
||||
assertFalse(installedOnlyOneVersionAvailable.canAndWantToUpdate());
|
||||
assertFalse(installedAlreadyLatestNoIgnore.canAndWantToUpdate());
|
||||
assertFalse(installedAlreadyLatestIgnoreAll.canAndWantToUpdate());
|
||||
assertFalse(installedAlreadyLatestIgnoreLatest.canAndWantToUpdate());
|
||||
assertFalse(installedAlreadyLatestIgnoreOld.canAndWantToUpdate());
|
||||
|
||||
App installedOldNoIgnore = AppProvider.Helper.findByPackageName(r, "installed, old version, no ignore");
|
||||
App installedOldIgnoreAll = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore all");
|
||||
App installedOldIgnoreLatest = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore latest");
|
||||
App installedOldIgnoreNewerNotLatest = AppProvider.Helper.findByPackageName(r, "installed, old version, ignore newer, but not latest");
|
||||
|
||||
assertTrue(installedOldNoIgnore.canAndWantToUpdate());
|
||||
assertFalse(installedOldIgnoreAll.canAndWantToUpdate());
|
||||
assertFalse(installedOldIgnoreLatest.canAndWantToUpdate());
|
||||
assertTrue(installedOldIgnoreNewerNotLatest.canAndWantToUpdate());
|
||||
|
||||
Cursor canUpdateCursor = r.query(AppProvider.getCanUpdateUri(), AppProvider.DataColumns.ALL, null, null, null);
|
||||
assertNotNull(canUpdateCursor);
|
||||
canUpdateCursor.moveToFirst();
|
||||
List<String> canUpdateIds = new ArrayList<>(canUpdateCursor.getCount());
|
||||
while (!canUpdateCursor.isAfterLast()) {
|
||||
canUpdateIds.add(new App(canUpdateCursor).packageName);
|
||||
canUpdateCursor.moveToNext();
|
||||
}
|
||||
canUpdateCursor.close();
|
||||
|
||||
String[] expectedUpdateableIds = {
|
||||
"installed, old version, no ignore",
|
||||
"installed, old version, ignore newer, but not latest",
|
||||
};
|
||||
|
||||
assertContainsOnly(expectedUpdateableIds, canUpdateIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnored() {
|
||||
insertApp("not installed", "not installed");
|
||||
insertAndInstallApp("installed, only one version available", 1, 1, false, 0);
|
||||
insertAndInstallApp("installed, already latest, no ignore", 10, 10, false, 0);
|
||||
insertAndInstallApp("installed, already latest, ignore all", 10, 10, true, 0);
|
||||
insertAndInstallApp("installed, already latest, ignore latest", 10, 10, false, 10);
|
||||
insertAndInstallApp("installed, already latest, ignore old", 10, 10, false, 5);
|
||||
insertAndInstallApp("installed, old version, no ignore", 5, 10, false, 0);
|
||||
insertAndInstallApp("installed, old version, ignore all", 5, 10, true, 0);
|
||||
insertAndInstallApp("installed, old version, ignore latest", 5, 10, false, 10);
|
||||
insertAndInstallApp("installed, old version, ignore newer, but not latest", 5, 10, false, 8);
|
||||
|
||||
assertResultCount(contentResolver, 10, AppProvider.getContentUri(), PROJ);
|
||||
|
||||
String[] projection = {AppProvider.DataColumns.PACKAGE_NAME};
|
||||
List<App> ignoredApps = AppProvider.Helper.findIgnored(context, projection);
|
||||
|
||||
String[] expectedIgnored = {
|
||||
"installed, already latest, ignore all",
|
||||
"installed, already latest, ignore latest",
|
||||
// NOT "installed, already latest, ignore old" - because it
|
||||
// is should only ignore if "ignored version" is >= suggested
|
||||
|
||||
"installed, old version, ignore all",
|
||||
"installed, old version, ignore latest",
|
||||
// NOT "installed, old version, ignore newer, but not latest"
|
||||
// for the same reason as above.
|
||||
};
|
||||
|
||||
assertContainsOnlyIds(ignoredApps, expectedIgnored);
|
||||
}
|
||||
|
||||
private void assertContainsOnlyIds(List<App> actualApps, String[] expectedIds) {
|
||||
List<String> actualIds = new ArrayList<>(actualApps.size());
|
||||
for (App app : actualApps) {
|
||||
actualIds.add(app.packageName);
|
||||
}
|
||||
assertContainsOnly(actualIds, expectedIds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstalled() {
|
||||
insertApps(100);
|
||||
|
||||
assertResultCount(contentResolver, 100, AppProvider.getContentUri(), PROJ);
|
||||
assertResultCount(contentResolver, 0, AppProvider.getInstalledUri(), PROJ);
|
||||
|
||||
for (int i = 10; i < 20; i++) {
|
||||
InstalledAppTestUtils.install(context, "com.example.test." + i, i, "v1");
|
||||
}
|
||||
|
||||
assertResultCount(contentResolver, 10, AppProvider.getInstalledUri(), PROJ);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsert() {
|
||||
|
||||
// Start with an empty database...
|
||||
Cursor cursor = queryAllApps();
|
||||
assertNotNull(cursor);
|
||||
assertEquals(0, cursor.getCount());
|
||||
cursor.close();
|
||||
|
||||
// Insert a new record...
|
||||
insertApp("org.fdroid.fdroid", "F-Droid");
|
||||
cursor = queryAllApps();
|
||||
assertNotNull(cursor);
|
||||
assertEquals(1, cursor.getCount());
|
||||
|
||||
// We intentionally throw an IllegalArgumentException if you haven't
|
||||
// yet called cursor.move*()...
|
||||
try {
|
||||
new App(cursor);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Success!
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
|
||||
// And now we should be able to recover these values from the app
|
||||
// value object (because the queryAllApps() helper asks for NAME and
|
||||
// PACKAGE_NAME.
|
||||
cursor.moveToFirst();
|
||||
App app = new App(cursor);
|
||||
cursor.close();
|
||||
assertEquals("org.fdroid.fdroid", app.packageName);
|
||||
assertEquals("F-Droid", app.name);
|
||||
|
||||
App otherApp = AppProvider.Helper.findByPackageName(context.getContentResolver(), "org.fdroid.fdroid");
|
||||
assertNotNull(otherApp);
|
||||
assertEquals("org.fdroid.fdroid", otherApp.packageName);
|
||||
assertEquals("F-Droid", otherApp.name);
|
||||
}
|
||||
|
||||
private Cursor queryAllApps() {
|
||||
String[] projection = new String[] {
|
||||
AppProvider.DataColumns._ID,
|
||||
AppProvider.DataColumns.NAME,
|
||||
AppProvider.DataColumns.PACKAGE_NAME
|
||||
};
|
||||
return contentResolver.query(AppProvider.getContentUri(), projection, null, null, null);
|
||||
}
|
||||
|
||||
|
||||
// ========================================================================
|
||||
// "Categories"
|
||||
// (at this point) not an additional table, but we treat them sort of
|
||||
// like they are. That means that if we change the implementation to
|
||||
// use a separate table in the future, these should still pass.
|
||||
// ========================================================================
|
||||
|
||||
@Test
|
||||
public void testCategoriesSingle() {
|
||||
insertAppWithCategory("com.dog", "Dog", "Animal");
|
||||
insertAppWithCategory("com.rock", "Rock", "Mineral");
|
||||
insertAppWithCategory("com.banana", "Banana", "Vegetable");
|
||||
|
||||
List<String> categories = AppProvider.Helper.categories(context);
|
||||
String[] expected = new String[] {
|
||||
context.getResources().getString(R.string.category_Whats_New),
|
||||
context.getResources().getString(R.string.category_Recently_Updated),
|
||||
context.getResources().getString(R.string.category_All),
|
||||
"Animal",
|
||||
"Mineral",
|
||||
"Vegetable",
|
||||
};
|
||||
assertContainsOnly(categories, expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCategoriesMultiple() {
|
||||
insertAppWithCategory("com.rock.dog", "Rock-Dog", "Mineral,Animal");
|
||||
insertAppWithCategory("com.dog.rock.apple", "Dog-Rock-Apple", "Animal,Mineral,Vegetable");
|
||||
insertAppWithCategory("com.banana.apple", "Banana", "Vegetable,Vegetable");
|
||||
|
||||
List<String> categories = AppProvider.Helper.categories(context);
|
||||
String[] expected = new String[] {
|
||||
context.getResources().getString(R.string.category_Whats_New),
|
||||
context.getResources().getString(R.string.category_Recently_Updated),
|
||||
context.getResources().getString(R.string.category_All),
|
||||
|
||||
"Animal",
|
||||
"Mineral",
|
||||
"Vegetable",
|
||||
};
|
||||
assertContainsOnly(categories, expected);
|
||||
|
||||
insertAppWithCategory("com.example.game", "Game",
|
||||
"Running,Shooting,Jumping,Bleh,Sneh,Pleh,Blah,Test category," +
|
||||
"The quick brown fox jumps over the lazy dog,With apostrophe's");
|
||||
|
||||
List<String> categoriesLonger = AppProvider.Helper.categories(context);
|
||||
String[] expectedLonger = new String[] {
|
||||
context.getResources().getString(R.string.category_Whats_New),
|
||||
context.getResources().getString(R.string.category_Recently_Updated),
|
||||
context.getResources().getString(R.string.category_All),
|
||||
|
||||
"Animal",
|
||||
"Mineral",
|
||||
"Vegetable",
|
||||
|
||||
"Running",
|
||||
"Shooting",
|
||||
"Jumping",
|
||||
"Bleh",
|
||||
"Sneh",
|
||||
"Pleh",
|
||||
"Blah",
|
||||
"Test category",
|
||||
"The quick brown fox jumps over the lazy dog",
|
||||
"With apostrophe's",
|
||||
};
|
||||
|
||||
assertContainsOnly(categoriesLonger, expectedLonger);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// Misc helper functions
|
||||
// (to be used by any tests in this suite)
|
||||
// =======================================================================
|
||||
|
||||
private void insertApp(String id, String name) {
|
||||
insertApp(id, name, new ContentValues());
|
||||
}
|
||||
|
||||
private void insertAppWithCategory(String id, String name, String categories) {
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(AppProvider.DataColumns.CATEGORIES, categories);
|
||||
insertApp(id, name, values);
|
||||
}
|
||||
|
||||
public void insertApp(String id, String name, ContentValues additionalValues) {
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(AppProvider.DataColumns.PACKAGE_NAME, id);
|
||||
values.put(AppProvider.DataColumns.NAME, name);
|
||||
|
||||
// Required fields (NOT NULL in the database).
|
||||
values.put(AppProvider.DataColumns.SUMMARY, "test summary");
|
||||
values.put(AppProvider.DataColumns.DESCRIPTION, "test description");
|
||||
values.put(AppProvider.DataColumns.LICENSE, "GPL?");
|
||||
values.put(AppProvider.DataColumns.IS_COMPATIBLE, 1);
|
||||
values.put(AppProvider.DataColumns.IGNORE_ALLUPDATES, 0);
|
||||
values.put(AppProvider.DataColumns.IGNORE_THISUPDATE, 0);
|
||||
|
||||
values.putAll(additionalValues);
|
||||
|
||||
Uri uri = AppProvider.getContentUri();
|
||||
|
||||
contentResolver.insert(uri, values);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// https://github.com/robolectric/robolectric/wiki/2.4-to-3.0-Upgrade-Guide
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.fdroid.fdroid.data;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContextWrapper;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.mockito.AdditionalAnswers;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public abstract class FDroidProviderTest {
|
||||
|
||||
protected ShadowContentResolver contentResolver;
|
||||
protected ContextWrapper context;
|
||||
|
||||
@Before
|
||||
public final void setupBase() {
|
||||
contentResolver = Shadows.shadowOf(RuntimeEnvironment.application.getContentResolver());
|
||||
final ContentResolver resolver = mock(ContentResolver.class, AdditionalAnswers.delegatesTo(contentResolver));
|
||||
context = new ContextWrapper(RuntimeEnvironment.application.getApplicationContext()) {
|
||||
@Override
|
||||
public ContentResolver getContentResolver() {
|
||||
return resolver;
|
||||
}
|
||||
};
|
||||
ShadowContentResolver.registerProvider(AppProvider.getAuthority(), new AppProvider());
|
||||
}
|
||||
|
||||
@After
|
||||
public final void tearDownBase() {
|
||||
FDroidProvider.clearDbHelperSingleton();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -6,13 +6,11 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.fdroid.fdroid.BuildConfig;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
|
||||
@@ -27,21 +25,13 @@ import java.util.Map;
|
||||
|
||||
@Config(constants = BuildConfig.class, application = Application.class)
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
public class InstalledAppProviderTest {
|
||||
|
||||
private ShadowContentResolver contentResolver;
|
||||
public class InstalledAppProviderTest extends FDroidProviderTest{
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
contentResolver = Shadows.shadowOf(RuntimeEnvironment.application.getContentResolver());
|
||||
ShadowContentResolver.registerProvider(InstalledAppProvider.getAuthority(), new InstalledAppProvider());
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() {
|
||||
FDroidProvider.clearDbHelperSingleton();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insertSingleApp() {
|
||||
Map<String, Long> foundBefore = InstalledAppProvider.Helper.all(RuntimeEnvironment.application);
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.fdroid.fdroid.data;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
|
||||
public class InstalledAppTestUtils {
|
||||
|
||||
/**
|
||||
* Will tell {@code pm} that we are installing {@code packageName}, and then update the
|
||||
* "installed apps" table in the database.
|
||||
*/
|
||||
public static void install(Context context,
|
||||
String packageName,
|
||||
int versionCode, String versionName) {
|
||||
PackageInfo info = new PackageInfo();
|
||||
info.packageName = packageName;
|
||||
info.versionCode = versionCode;
|
||||
info.versionName = versionName;
|
||||
info.applicationInfo = new ApplicationInfo();
|
||||
info.applicationInfo.publicSourceDir = "/tmp/mock-location";
|
||||
String hashType = "sha256";
|
||||
String hash = "00112233445566778899aabbccddeeff";
|
||||
InstalledAppProviderService.insertAppIntoDb(context, packageName, info, hashType, hash);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,8 +4,12 @@ import android.content.ContentValues;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -15,6 +19,66 @@ import static org.junit.Assert.fail;
|
||||
|
||||
public class ProviderTestUtils {
|
||||
|
||||
public static <T extends Comparable> void assertContainsOnly(List<T> actualList, T[] expectedArray) {
|
||||
List<T> expectedList = new ArrayList<>(expectedArray.length);
|
||||
Collections.addAll(expectedList, expectedArray);
|
||||
assertContainsOnly(actualList, expectedList);
|
||||
}
|
||||
|
||||
public static <T extends Comparable> void assertContainsOnly(T[] actualArray, List<T> expectedList) {
|
||||
List<T> actualList = new ArrayList<>(actualArray.length);
|
||||
Collections.addAll(actualList, actualArray);
|
||||
assertContainsOnly(actualList, expectedList);
|
||||
}
|
||||
|
||||
public static <T extends Comparable> void assertContainsOnly(T[] actualArray, T[] expectedArray) {
|
||||
List<T> expectedList = new ArrayList<>(expectedArray.length);
|
||||
Collections.addAll(expectedList, expectedArray);
|
||||
assertContainsOnly(actualArray, expectedList);
|
||||
}
|
||||
|
||||
public static <T> String listToString(List<T> list) {
|
||||
String string = "[";
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
if (i > 0) {
|
||||
string += ", ";
|
||||
}
|
||||
string += "'" + list.get(i) + "'";
|
||||
}
|
||||
string += "]";
|
||||
return string;
|
||||
}
|
||||
|
||||
public static <T extends Comparable> void assertContainsOnly(List<T> actualList, List<T> expectedContains) {
|
||||
if (actualList.size() != expectedContains.size()) {
|
||||
String message =
|
||||
"List sizes don't match.\n" +
|
||||
"Expected: " +
|
||||
listToString(expectedContains) + "\n" +
|
||||
"Actual: " +
|
||||
listToString(actualList);
|
||||
throw new AssertionFailedError(message);
|
||||
}
|
||||
for (T required : expectedContains) {
|
||||
boolean containsRequired = false;
|
||||
for (T itemInList : actualList) {
|
||||
if (required.equals(itemInList)) {
|
||||
containsRequired = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!containsRequired) {
|
||||
String message =
|
||||
"List doesn't contain \"" + required + "\".\n" +
|
||||
"Expected: " +
|
||||
listToString(expectedContains) + "\n" +
|
||||
"Actual: " +
|
||||
listToString(actualList);
|
||||
throw new AssertionFailedError(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertCantDelete(ShadowContentResolver resolver, Uri uri) {
|
||||
try {
|
||||
resolver.delete(uri, null, null);
|
||||
@@ -62,7 +126,11 @@ public class ProviderTestUtils {
|
||||
}
|
||||
|
||||
public static void assertResultCount(ShadowContentResolver resolver, int expectedCount, Uri uri) {
|
||||
Cursor cursor = resolver.query(uri, new String[] {}, null, null, null);
|
||||
assertResultCount(resolver, expectedCount, uri, new String[] {});
|
||||
}
|
||||
|
||||
public static void assertResultCount(ShadowContentResolver resolver, int expectedCount, Uri uri, String[] projection) {
|
||||
Cursor cursor = resolver.query(uri, projection, null, null, null);
|
||||
assertResultCount(expectedCount, cursor);
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertInvalidUri;
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertValidUri;
|
||||
|
||||
@@ -64,6 +67,36 @@ public class ProviderUriTests {
|
||||
assertValidUri(resolver, RepoProvider.getContentUri(10000L), projection);
|
||||
assertValidUri(resolver, RepoProvider.allExceptSwapUri(), projection);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidAppProviderUris() {
|
||||
ShadowContentResolver.registerProvider(AppProvider.getAuthority(), new AppProvider());
|
||||
assertInvalidUri(resolver, AppProvider.getAuthority());
|
||||
assertInvalidUri(resolver, "blah");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validAppProviderUris() {
|
||||
ShadowContentResolver.registerProvider(AppProvider.getAuthority(), new AppProvider());
|
||||
String[] projection = new String[] { AppProvider.DataColumns._ID };
|
||||
assertValidUri(resolver, AppProvider.getContentUri(), "content://org.fdroid.fdroid.data.AppProvider", projection);
|
||||
assertValidUri(resolver, AppProvider.getSearchUri("'searching!'"), "content://org.fdroid.fdroid.data.AppProvider/search/'searching!'", projection);
|
||||
assertValidUri(resolver, AppProvider.getSearchUri("/"), "content://org.fdroid.fdroid.data.AppProvider/search/%2F", projection);
|
||||
assertValidUri(resolver, AppProvider.getSearchUri(""), "content://org.fdroid.fdroid.data.AppProvider", projection);
|
||||
assertValidUri(resolver, AppProvider.getSearchUri(null), "content://org.fdroid.fdroid.data.AppProvider", projection);
|
||||
assertValidUri(resolver, AppProvider.getNoApksUri(), "content://org.fdroid.fdroid.data.AppProvider/noApks", projection);
|
||||
assertValidUri(resolver, AppProvider.getInstalledUri(), "content://org.fdroid.fdroid.data.AppProvider/installed", projection);
|
||||
assertValidUri(resolver, AppProvider.getCanUpdateUri(), "content://org.fdroid.fdroid.data.AppProvider/canUpdate", projection);
|
||||
|
||||
App app = new App();
|
||||
app.packageName = "org.fdroid.fdroid";
|
||||
|
||||
List<App> apps = new ArrayList<>(1);
|
||||
apps.add(app);
|
||||
|
||||
assertValidUri(resolver, AppProvider.getContentUri(app), "content://org.fdroid.fdroid.data.AppProvider/org.fdroid.fdroid", projection);
|
||||
assertValidUri(resolver, AppProvider.getContentUri(apps), "content://org.fdroid.fdroid.data.AppProvider/apps/org.fdroid.fdroid", projection);
|
||||
assertValidUri(resolver, AppProvider.getContentUri("org.fdroid.fdroid"), "content://org.fdroid.fdroid.data.AppProvider/org.fdroid.fdroid", projection);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user