Started implementing ApkProvider tests.
Refactored a couple of common things from AppProviderTest to either FDroidProviderTest (baseclass) or TestUtils (static methods) where relevant.
This commit is contained in:
parent
43f8ea0814
commit
85f3232de0
@ -366,6 +366,11 @@ public class ApkProvider extends FDroidProvider {
|
|||||||
String[] apkDetails = apkKeys.split(",");
|
String[] apkDetails = apkKeys.split(",");
|
||||||
String[] args = new String[apkDetails.length * 2];
|
String[] args = new String[apkDetails.length * 2];
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
if (apkDetails.length > MAX_APKS_TO_QUERY) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Cannot query more than " + MAX_APKS_TO_QUERY + ". " +
|
||||||
|
"You tried to query " + apkDetails.length);
|
||||||
|
}
|
||||||
for (int i = 0; i < apkDetails.length; i ++) {
|
for (int i = 0; i < apkDetails.length; i ++) {
|
||||||
String[] parts = apkDetails[i].split(":");
|
String[] parts = apkDetails[i].split(":");
|
||||||
String id = parts[0];
|
String id = parts[0];
|
||||||
|
131
test/src/org/fdroid/fdroid/ApkProviderTest.java
Normal file
131
test/src/org/fdroid/fdroid/ApkProviderTest.java
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
package org.fdroid.fdroid;
|
||||||
|
|
||||||
|
import android.content.ContentValues;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import org.fdroid.fdroid.data.Apk;
|
||||||
|
import org.fdroid.fdroid.data.ApkProvider;
|
||||||
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
|
import org.fdroid.fdroid.mock.MockApk;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ApkProviderTest extends FDroidProviderTest<ApkProvider> {
|
||||||
|
|
||||||
|
public ApkProviderTest() {
|
||||||
|
super(ApkProvider.class, ApkProvider.getAuthority());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String[] getMinimalProjection() {
|
||||||
|
return new String[] {
|
||||||
|
ApkProvider.DataColumns.APK_ID,
|
||||||
|
ApkProvider.DataColumns.VERSION_CODE,
|
||||||
|
ApkProvider.DataColumns.NAME
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testUris() {
|
||||||
|
assertInvalidUri(ApkProvider.getAuthority());
|
||||||
|
assertInvalidUri(AppProvider.getContentUri());
|
||||||
|
|
||||||
|
List<Apk> apks = new ArrayList<Apk>(3);
|
||||||
|
for (int i = 0; i < 10; i ++) {
|
||||||
|
apks.add(new MockApk("com.example." + i, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
assertValidUri(ApkProvider.getContentUri());
|
||||||
|
assertValidUri(ApkProvider.getAppUri("org.fdroid.fdroid"));
|
||||||
|
assertValidUri(ApkProvider.getContentUri(new MockApk("org.fdroid.fdroid", 100)));
|
||||||
|
assertValidUri(ApkProvider.getContentUri());
|
||||||
|
assertValidUri(ApkProvider.getContentUri(apks));
|
||||||
|
assertValidUri(ApkProvider.getContentUri("org.fdroid.fdroid", 100));
|
||||||
|
assertValidUri(ApkProvider.getRepoUri(1000));
|
||||||
|
|
||||||
|
List<Apk> manyApks = new ArrayList<Apk>(ApkProvider.MAX_APKS_TO_QUERY - 5);
|
||||||
|
for (int i = 0; i < ApkProvider.MAX_APKS_TO_QUERY - 1; i ++) {
|
||||||
|
manyApks.add(new MockApk("com.example." + i, i));
|
||||||
|
}
|
||||||
|
assertValidUri(ApkProvider.getContentUri(manyApks));
|
||||||
|
|
||||||
|
manyApks.add(new MockApk("org.fdroid.fdroid.1", 1));
|
||||||
|
manyApks.add(new MockApk("org.fdroid.fdroid.2", 2));
|
||||||
|
try {
|
||||||
|
// Technically, it is a valid URI, because it doesn't
|
||||||
|
// throw an UnsupportedOperationException. However it
|
||||||
|
// is still not okay (we run out of bindable parameters
|
||||||
|
// in the sqlite query.
|
||||||
|
assertValidUri(ApkProvider.getContentUri(manyApks));
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// This is the expected error behaviour.
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testQuery() {
|
||||||
|
Cursor cursor = queryAllApks();
|
||||||
|
assertNotNull(cursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertApks(int count) {
|
||||||
|
for (int i = 0; i < count; i ++) {
|
||||||
|
insertApk("com.example.test." + i, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testInsert() {
|
||||||
|
|
||||||
|
// Start with an empty database...
|
||||||
|
Cursor cursor = queryAllApks();
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals(0, cursor.getCount());
|
||||||
|
|
||||||
|
// Insert a new record...
|
||||||
|
insertApk("org.fdroid.fdroid", 13);
|
||||||
|
cursor = queryAllApks();
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals(1, cursor.getCount());
|
||||||
|
|
||||||
|
// We intentionally throw an IllegalArgumentException if you haven't
|
||||||
|
// yet called cursor.move*()...
|
||||||
|
try {
|
||||||
|
new Apk(cursor);
|
||||||
|
fail();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
// Success!
|
||||||
|
} catch (Exception e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
// And now we should be able to recover these values from the apk
|
||||||
|
// value object (because the queryAllApks() helper asks for VERSION_CODE and
|
||||||
|
// APK_ID.
|
||||||
|
cursor.moveToFirst();
|
||||||
|
Apk apk = new Apk(cursor);
|
||||||
|
assertEquals("org.fdroid.fdroid", apk.id);
|
||||||
|
assertEquals(13, apk.vercode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testIgnore() {
|
||||||
|
for (int i = 0; i < 10; i ++) {
|
||||||
|
insertApk("org.fdroid.fdroid", i);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cursor queryAllApks() {
|
||||||
|
return getMockContentResolver().query(ApkProvider.getContentUri(), getMinimalProjection(), null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertApk(String id, int versionCode) {
|
||||||
|
insertApk(id, versionCode, new ContentValues());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertApk(String id, int versionCode,
|
||||||
|
ContentValues additionalValues) {
|
||||||
|
TestUtils.insertApk(getMockContentResolver(), id, versionCode, additionalValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,7 +3,6 @@ package org.fdroid.fdroid;
|
|||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import junit.framework.AssertionFailedError;
|
|
||||||
import mock.MockCategoryResources;
|
import mock.MockCategoryResources;
|
||||||
import mock.MockInstallablePackageManager;
|
import mock.MockInstallablePackageManager;
|
||||||
import org.fdroid.fdroid.data.ApkProvider;
|
import org.fdroid.fdroid.data.ApkProvider;
|
||||||
@ -11,7 +10,6 @@ import org.fdroid.fdroid.data.App;
|
|||||||
import org.fdroid.fdroid.data.AppProvider;
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class AppProviderTest extends FDroidProviderTest<AppProvider> {
|
public class AppProviderTest extends FDroidProviderTest<AppProvider> {
|
||||||
@ -24,7 +22,6 @@ public class AppProviderTest extends FDroidProviderTest<AppProvider> {
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
getSwappableContext().setResources(new MockCategoryResources());
|
getSwappableContext().setResources(new MockCategoryResources());
|
||||||
getSwappableContext().setContentResolver(getMockContentResolver());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String[] getMinimalProjection() {
|
protected String[] getMinimalProjection() {
|
||||||
@ -75,20 +72,14 @@ public class AppProviderTest extends FDroidProviderTest<AppProvider> {
|
|||||||
|
|
||||||
insertApps(100);
|
insertApps(100);
|
||||||
|
|
||||||
assertAppCount(100, AppProvider.getContentUri());
|
assertResultCount(100, AppProvider.getContentUri());
|
||||||
assertAppCount(0, AppProvider.getInstalledUri());
|
assertResultCount(0, AppProvider.getInstalledUri());
|
||||||
|
|
||||||
for (int i = 10; i < 20; i ++) {
|
for (int i = 10; i < 20; i ++) {
|
||||||
pm.install("com.example.test." + i, i, "v1");
|
pm.install("com.example.test." + i, i, "v1");
|
||||||
}
|
}
|
||||||
|
|
||||||
assertAppCount(10, AppProvider.getInstalledUri());
|
assertResultCount(10, AppProvider.getInstalledUri());
|
||||||
}
|
|
||||||
|
|
||||||
private void assertAppCount(int expectedCount, Uri uri) {
|
|
||||||
Cursor cursor = getMockContentResolver().query(uri, getMinimalProjection(), null, null, null);
|
|
||||||
assertNotNull(cursor);
|
|
||||||
assertEquals(expectedCount, cursor.getCount());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testInsert() {
|
public void testInsert() {
|
||||||
@ -142,7 +133,7 @@ public class AppProviderTest extends FDroidProviderTest<AppProvider> {
|
|||||||
"Mineral",
|
"Mineral",
|
||||||
"Vegetable"
|
"Vegetable"
|
||||||
};
|
};
|
||||||
assertContainsOnly(categories, expected);
|
TestUtils.assertContainsOnly(categories, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCategoriesMultiple() {
|
public void testCategoriesMultiple() {
|
||||||
@ -160,7 +151,7 @@ public class AppProviderTest extends FDroidProviderTest<AppProvider> {
|
|||||||
"Mineral",
|
"Mineral",
|
||||||
"Vegetable"
|
"Vegetable"
|
||||||
};
|
};
|
||||||
assertContainsOnly(categories, expected);
|
TestUtils.assertContainsOnly(categories, expected);
|
||||||
|
|
||||||
insertAppWithCategory("com.example.game", "Game",
|
insertAppWithCategory("com.example.game", "Game",
|
||||||
"Running,Shooting,Jumping,Bleh,Sneh,Pleh,Blah,Test category," +
|
"Running,Shooting,Jumping,Bleh,Sneh,Pleh,Blah,Test category," +
|
||||||
@ -188,7 +179,7 @@ public class AppProviderTest extends FDroidProviderTest<AppProvider> {
|
|||||||
"With apostrophe's"
|
"With apostrophe's"
|
||||||
};
|
};
|
||||||
|
|
||||||
assertContainsOnly(categoriesLonger, expectedLonger);
|
TestUtils.assertContainsOnly(categoriesLonger, expectedLonger);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void insertApp(String id, String name) {
|
private void insertApp(String id, String name) {
|
||||||
@ -207,52 +198,4 @@ public class AppProviderTest extends FDroidProviderTest<AppProvider> {
|
|||||||
TestUtils.insertApp(getMockContentResolver(), id, name, additionalValues);
|
TestUtils.insertApp(getMockContentResolver(), id, name, additionalValues);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends Comparable> void assertContainsOnly(List<T> actualList, T[] expectedContains) {
|
|
||||||
List<T> containsList = new ArrayList<T>(expectedContains.length);
|
|
||||||
Collections.addAll(containsList, expectedContains);
|
|
||||||
assertContainsOnly(actualList, containsList);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <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;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,13 @@ public abstract class FDroidProviderTest<T extends FDroidProvider> extends Provi
|
|||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
super.setUp();
|
super.setUp();
|
||||||
Utils.setupInstalledApkCache(new MockInstalledApkCache());
|
Utils.setupInstalledApkCache(new MockInstalledApkCache());
|
||||||
|
|
||||||
|
// The *Provider.Helper.* functions tend to take a Context as their
|
||||||
|
// first parameter. This context is used to connect to the relevant
|
||||||
|
// content provider. Thus, we need a context that is able to connect
|
||||||
|
// to the mock content resolver, in order to reach the provider
|
||||||
|
// under test.
|
||||||
|
getSwappableContext().setContentResolver(getMockContentResolver());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.ECLAIR)
|
@TargetApi(Build.VERSION_CODES.ECLAIR)
|
||||||
@ -74,4 +81,9 @@ public abstract class FDroidProviderTest<T extends FDroidProvider> extends Provi
|
|||||||
*/
|
*/
|
||||||
protected abstract String[] getMinimalProjection();
|
protected abstract String[] getMinimalProjection();
|
||||||
|
|
||||||
|
protected void assertResultCount(int expectedCount, Uri uri) {
|
||||||
|
Cursor cursor = getMockContentResolver().query(uri, getMinimalProjection(), null, null, null);
|
||||||
|
assertNotNull(cursor);
|
||||||
|
assertEquals(expectedCount, cursor.getCount());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,65 @@ package org.fdroid.fdroid;
|
|||||||
|
|
||||||
import android.content.*;
|
import android.content.*;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.test.mock.MockContentResolver;
|
||||||
|
import junit.framework.AssertionFailedError;
|
||||||
|
import org.fdroid.fdroid.data.ApkProvider;
|
||||||
import org.fdroid.fdroid.data.AppProvider;
|
import org.fdroid.fdroid.data.AppProvider;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class TestUtils {
|
public class TestUtils {
|
||||||
|
|
||||||
|
public static <T extends Comparable> void assertContainsOnly(List<T> actualList, T[] expectedContains) {
|
||||||
|
List<T> containsList = new ArrayList<T>(expectedContains.length);
|
||||||
|
Collections.addAll(containsList, expectedContains);
|
||||||
|
assertContainsOnly(actualList, containsList);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 insertApp(ContentResolver resolver, String id, String name, ContentValues additionalValues) {
|
public static void insertApp(ContentResolver resolver, String id, String name, ContentValues additionalValues) {
|
||||||
|
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
@ -27,4 +82,25 @@ public class TestUtils {
|
|||||||
resolver.insert(uri, values);
|
resolver.insert(uri, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void insertApk(ContentResolver resolver, String id, int versionCode, ContentValues additionalValues) {
|
||||||
|
|
||||||
|
ContentValues values = new ContentValues();
|
||||||
|
|
||||||
|
values.put(ApkProvider.DataColumns.APK_ID, id);
|
||||||
|
values.put(ApkProvider.DataColumns.VERSION_CODE, versionCode);
|
||||||
|
|
||||||
|
// Required fields (NOT NULL in the database).
|
||||||
|
values.put(ApkProvider.DataColumns.REPO_ID, 1);
|
||||||
|
values.put(ApkProvider.DataColumns.VERSION, "The good one");
|
||||||
|
values.put(ApkProvider.DataColumns.HASH, "11111111aaaaaaaa");
|
||||||
|
values.put(ApkProvider.DataColumns.NAME, "Test Apk");
|
||||||
|
values.put(ApkProvider.DataColumns.SIZE, 10000);
|
||||||
|
values.put(ApkProvider.DataColumns.IS_COMPATIBLE, 1);
|
||||||
|
|
||||||
|
values.putAll(additionalValues);
|
||||||
|
|
||||||
|
Uri uri = ApkProvider.getContentUri();
|
||||||
|
|
||||||
|
resolver.insert(uri, values);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
12
test/src/org/fdroid/fdroid/mock/MockApk.java
Normal file
12
test/src/org/fdroid/fdroid/mock/MockApk.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package org.fdroid.fdroid.mock;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.data.Apk;
|
||||||
|
|
||||||
|
public class MockApk extends Apk {
|
||||||
|
|
||||||
|
public MockApk(String id, int versionCode) {
|
||||||
|
this.id = id;
|
||||||
|
this.vercode = versionCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
test/src/org/fdroid/fdroid/mock/MockApp.java
Normal file
16
test/src/org/fdroid/fdroid/mock/MockApp.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package org.fdroid.fdroid.mock;
|
||||||
|
|
||||||
|
import org.fdroid.fdroid.data.App;
|
||||||
|
|
||||||
|
public class MockApp extends App {
|
||||||
|
|
||||||
|
public MockApp(String id) {
|
||||||
|
this(id, "App " + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MockApp(String id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user