Finish porting tests to Robolectric, and appease PMD.
To appease PMD, we now have a three rulesets in `config/pmd/*.xml`: * `rules.xml`: The bulk of the rules, used by both main and test code. * `rules-main.xml`: Rules specific to the andoid client code. * `rules-test.xml`: Rules specific to test code. The rationale is because checkstyle by default checks for "too many static imports", which is a fair call. However in JUnit4 code, it is common to import many `assert*` static methods.
This commit is contained in:
parent
253900e927
commit
4e73d1e5e6
@ -230,13 +230,22 @@ pmd {
|
||||
consoleOutput = true
|
||||
}
|
||||
|
||||
task pmd(type: Pmd, dependsOn: assembleDebug) {
|
||||
ruleSetFiles = files("${project.rootDir}/config/pmd/rules.xml")
|
||||
task pmdMain(type: Pmd, dependsOn: assembleDebug) {
|
||||
ruleSetFiles = files("${project.rootDir}/config/pmd/rules.xml", "${project.rootDir}/config/pmd/rules-main.xml")
|
||||
ruleSets = [] // otherwise defaults clash with the list in rules.xml
|
||||
source 'src/main/java', 'src/test/java', 'src/androidTest/java'
|
||||
source 'src/main/java'
|
||||
include '**/*.java'
|
||||
}
|
||||
|
||||
task pmdTest(type: Pmd, dependsOn: assembleDebug) {
|
||||
ruleSetFiles = files("${project.rootDir}/config/pmd/rules.xml", "${project.rootDir}/config/pmd/rules-test.xml")
|
||||
ruleSets = [] // otherwise defaults clash with the list in rules.xml
|
||||
source 'src/test/java', 'src/androidTest/java'
|
||||
include '**/*.java'
|
||||
}
|
||||
|
||||
task pmd(dependsOn: [pmdMain, pmdTest]) {}
|
||||
|
||||
// This person took the example code below from another blogpost online, however
|
||||
// I lost the reference to it:
|
||||
// http://stackoverflow.com/questions/23297562/gradle-javadoc-and-android-documentation
|
||||
|
Binary file not shown.
@ -1,257 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.test;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.Resources;
|
||||
import android.database.DatabaseUtils;
|
||||
import android.os.Build;
|
||||
import android.test.mock.MockContentResolver;
|
||||
import android.test.mock.MockContext;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* This test case class provides a framework for testing a single
|
||||
* {@link ContentProvider} and for testing your app code with an
|
||||
* isolated content provider. Instead of using the system map of
|
||||
* providers that is based on the manifests of other applications, the test
|
||||
* case creates its own internal map. It then uses this map to resolve providers
|
||||
* given an authority. This allows you to inject test providers and to null out
|
||||
* providers that you do not want to use.
|
||||
* <p>
|
||||
* This test case also sets up the following mock objects:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>
|
||||
* An {@link android.test.IsolatedContext} that stubs out Context methods that might
|
||||
* affect the rest of the running system, while allowing tests to do real file and
|
||||
* database work.
|
||||
* </li>
|
||||
* <li>
|
||||
* A {@link android.test.mock.MockContentResolver} that provides the functionality of a
|
||||
* regular content resolver, but uses {@link IsolatedContext}. It stubs out
|
||||
* {@link ContentResolver#notifyChange(Uri, ContentObserver, boolean)} to
|
||||
* prevent the test from affecting the running system.
|
||||
* </li>
|
||||
* <li>
|
||||
* An instance of the provider under test, running in an {@link IsolatedContext}.
|
||||
* </li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* This framework is set up automatically by the base class' {@link #setUp()} method. If you
|
||||
* override this method, you must call the super method as the first statement in
|
||||
* your override.
|
||||
* </p>
|
||||
* <p>
|
||||
* In order for their tests to be run, concrete subclasses must provide their own
|
||||
* constructor with no arguments. This constructor must call
|
||||
* {@link #ProviderTestCase2MockContext(Class, String)} as its first operation.
|
||||
* </p>
|
||||
* For more information on content provider testing, please see
|
||||
* <a href="{@docRoot}tools/testing/contentprovider_testing.html">Content Provider Testing</a>.
|
||||
*/
|
||||
public abstract class ProviderTestCase2MockContext<T extends ContentProvider> extends AndroidTestCase {
|
||||
|
||||
Class<T> mProviderClass;
|
||||
String mProviderAuthority;
|
||||
|
||||
private IsolatedContext mProviderContext;
|
||||
private MockContentResolver mResolver;
|
||||
|
||||
private class MockContext2 extends MockContext {
|
||||
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
return getContext().getResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDir(String name, int mode) {
|
||||
// name the directory so the directory will be separated from
|
||||
// one created through the regular Context
|
||||
return getContext().getDir("mockcontext2_" + name, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPackageName() {
|
||||
return "org.fdroid.fdroid";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param providerClass The class name of the provider under test
|
||||
* @param providerAuthority The provider's authority string
|
||||
*/
|
||||
public ProviderTestCase2MockContext(Class<T> providerClass, String providerAuthority) {
|
||||
mProviderClass = providerClass;
|
||||
mProviderAuthority = providerAuthority;
|
||||
}
|
||||
|
||||
private T mProvider;
|
||||
|
||||
/**
|
||||
* Returns the content provider created by this class in the {@link #setUp()} method.
|
||||
* @return T An instance of the provider class given as a parameter to the test case class.
|
||||
*/
|
||||
public T getProvider() {
|
||||
return mProvider;
|
||||
}
|
||||
|
||||
protected abstract Context createMockContext(Context delegate);
|
||||
|
||||
/**
|
||||
* Sets up the environment for the test fixture.
|
||||
* <p>
|
||||
* Creates a new
|
||||
* {@link android.test.mock.MockContentResolver}, a new IsolatedContext
|
||||
* that isolates the provider's file operations, and a new instance of
|
||||
* the provider under test within the isolated environment.
|
||||
* </p>
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
@Before
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
mResolver = new MockContentResolver();
|
||||
final String filenamePrefix = "test.";
|
||||
final RenamingDelegatingContext targetContextWrapper = new
|
||||
RenamingDelegatingContext(
|
||||
createMockContext(new MockContext2()), // The context that most methods are delegated to
|
||||
getContext(), // The context that file methods are delegated to
|
||||
filenamePrefix);
|
||||
|
||||
mProviderContext = new IsolatedContext(mResolver, new ContextWrapper(targetContextWrapper) {
|
||||
// The FDroidProvider class needs access to an application context in order to initialize
|
||||
// the singleton DBHelper instance.
|
||||
@Override
|
||||
public Context getApplicationContext() {
|
||||
return targetContextWrapper;
|
||||
}
|
||||
});
|
||||
|
||||
mProvider = mProviderClass.newInstance();
|
||||
mProvider.attachInfo(mProviderContext, null);
|
||||
assertNotNull(mProvider);
|
||||
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 mProvider.
|
||||
*/
|
||||
@Override
|
||||
@After
|
||||
protected void tearDown() throws Exception {
|
||||
shutdownProvider();
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
private void shutdownProvider() {
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
mProvider.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link MockContentResolver} created by this class during initialization. You
|
||||
* must use the methods of this resolver to access the provider under test.
|
||||
*
|
||||
* @return A {@link MockContentResolver} instance.
|
||||
*/
|
||||
public MockContentResolver getMockContentResolver() {
|
||||
return mResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link IsolatedContext} created by this class during initialization.
|
||||
* @return The {@link IsolatedContext} instance
|
||||
*/
|
||||
public IsolatedContext getMockContext() {
|
||||
return mProviderContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Creates a new content provider of the same type as that passed to the test case class,
|
||||
* with an authority name set to the authority parameter, and using an SQLite database as
|
||||
* the underlying data source. The SQL statement parameter is used to create the database.
|
||||
* This method also creates a new {@link MockContentResolver} and adds the provider to it.
|
||||
* </p>
|
||||
* <p>
|
||||
* Both the new provider and the new resolver are put into an {@link IsolatedContext}
|
||||
* that uses the targetContext parameter for file operations and a {@link MockContext}
|
||||
* for everything else. The IsolatedContext prepends the filenamePrefix parameter to
|
||||
* file, database, and directory names.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is a convenience method for creating a "mock" provider that can contain test data.
|
||||
* </p>
|
||||
*
|
||||
* @param targetContext The context to use as the basis of the IsolatedContext
|
||||
* @param filenamePrefix A string that is prepended to file, database, and directory names
|
||||
* @param providerClass The type of the provider being tested
|
||||
* @param authority The authority string to associated with the test provider
|
||||
* @param databaseName The name assigned to the database
|
||||
* @param databaseVersion The version assigned to the database
|
||||
* @param sql A string containing the SQL statements that are needed to create the desired
|
||||
* database and its tables. The format is the same as that generated by the
|
||||
* <a href="http://www.sqlite.org/sqlite.html">sqlite3</a> tool's <code>.dump</code> command.
|
||||
* @return ContentResolver A new {@link MockContentResolver} linked to the provider
|
||||
*
|
||||
* @throws IllegalAccessException
|
||||
* @throws InstantiationException
|
||||
*/
|
||||
public static <T extends ContentProvider> ContentResolver newResolverWithContentProviderFromSql(
|
||||
Context targetContext, String filenamePrefix, Class<T> providerClass, String authority,
|
||||
String databaseName, int databaseVersion, String sql)
|
||||
throws IllegalAccessException, InstantiationException {
|
||||
MockContentResolver resolver = new MockContentResolver();
|
||||
RenamingDelegatingContext targetContextWrapper = new RenamingDelegatingContext(
|
||||
new MockContext(), // The context that most methods are delegated to
|
||||
targetContext, // The context that file methods are delegated to
|
||||
filenamePrefix);
|
||||
Context context = new IsolatedContext(resolver, targetContextWrapper);
|
||||
DatabaseUtils.createDbFromSqlStatements(context, databaseName, databaseVersion, sql);
|
||||
|
||||
T provider = providerClass.newInstance();
|
||||
provider.attachInfo(context, null);
|
||||
resolver.addProvider(authority, provider);
|
||||
|
||||
return resolver;
|
||||
}
|
||||
}
|
@ -1,7 +1,10 @@
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.util.Log;
|
||||
@ -14,10 +17,15 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
|
||||
/**
|
||||
@ -36,8 +44,8 @@ public class FileCompatTest {
|
||||
@Before
|
||||
public void setUp() {
|
||||
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
File dir = TestUtilsOld.getWriteableDir(instrumentation);
|
||||
sourceFile = SanitizedFile.knownSanitized(TestUtilsOld.copyAssetToDir(instrumentation.getContext(), "simpleIndex.jar", dir));
|
||||
File dir = getWriteableDir(instrumentation);
|
||||
sourceFile = SanitizedFile.knownSanitized(copyAssetToDir(instrumentation.getContext(), "simpleIndex.jar", dir));
|
||||
destFile = new SanitizedFile(dir, "dest-" + UUID.randomUUID() + ".testproduct");
|
||||
assertFalse(destFile.exists());
|
||||
assertTrue(sourceFile.getAbsolutePath() + " should exist.", sourceFile.exists());
|
||||
@ -62,24 +70,70 @@ public class FileCompatTest {
|
||||
|
||||
@Test
|
||||
public void testSymlinkLibcore() {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 19) {
|
||||
assumeTrue(Build.VERSION.SDK_INT >= 19);
|
||||
FileCompatForTest.symlinkLibcoreTest(sourceFile, destFile);
|
||||
assertTrue(destFile.getAbsolutePath() + " should exist after symlinking", destFile.exists());
|
||||
} else {
|
||||
Log.w(TAG, "Cannot test symlink-libcore on this device. Requires android-19, but this has android-" + Build.VERSION.SDK_INT);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSymlinkOs() {
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
assumeTrue(Build.VERSION.SDK_INT >= 21);
|
||||
FileCompatForTest.symlinkOsTest(sourceFile, destFile);
|
||||
assertTrue(destFile.getAbsolutePath() + " should exist after symlinking", destFile.exists());
|
||||
} else {
|
||||
Log.w(TAG, "Cannot test symlink-os on this device. Requires android-21, but only has android-" + Build.VERSION.SDK_INT);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static File copyAssetToDir(Context context, String assetName, File directory) {
|
||||
File tempFile;
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
try {
|
||||
tempFile = File.createTempFile(assetName + "-", ".testasset", directory);
|
||||
Log.i(TAG, "Copying asset file " + assetName + " to directory " + directory);
|
||||
input = context.getAssets().open(assetName);
|
||||
output = new FileOutputStream(tempFile);
|
||||
Utils.copy(input, output);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
Utils.closeQuietly(output);
|
||||
Utils.closeQuietly(input);
|
||||
}
|
||||
return tempFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer internal over external storage, because external tends to be FAT filesystems,
|
||||
* which don't support symlinks (which we test using this method).
|
||||
*/
|
||||
private static File getWriteableDir(Instrumentation instrumentation) {
|
||||
Context context = instrumentation.getContext();
|
||||
Context targetContext = instrumentation.getTargetContext();
|
||||
|
||||
File[] dirsToTry = new File[]{
|
||||
context.getCacheDir(),
|
||||
context.getFilesDir(),
|
||||
targetContext.getCacheDir(),
|
||||
targetContext.getFilesDir(),
|
||||
context.getExternalCacheDir(),
|
||||
context.getExternalFilesDir(null),
|
||||
targetContext.getExternalCacheDir(),
|
||||
targetContext.getExternalFilesDir(null),
|
||||
Environment.getExternalStorageDirectory(),
|
||||
};
|
||||
|
||||
return getWriteableDir(dirsToTry);
|
||||
}
|
||||
|
||||
private static File getWriteableDir(File[] dirsToTry) {
|
||||
|
||||
for (File dir : dirsToTry) {
|
||||
if (dir != null && dir.canWrite()) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -1,73 +0,0 @@
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class TestUtilsOld {
|
||||
|
||||
private static final String TAG = "TestUtilsOld";
|
||||
|
||||
@Nullable
|
||||
public static File copyAssetToDir(Context context, String assetName, File directory) {
|
||||
File tempFile;
|
||||
InputStream input = null;
|
||||
OutputStream output = null;
|
||||
try {
|
||||
tempFile = File.createTempFile(assetName + "-", ".testasset", directory);
|
||||
Log.i(TAG, "Copying asset file " + assetName + " to directory " + directory);
|
||||
input = context.getAssets().open(assetName);
|
||||
output = new FileOutputStream(tempFile);
|
||||
Utils.copy(input, output);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
Utils.closeQuietly(output);
|
||||
Utils.closeQuietly(input);
|
||||
}
|
||||
return tempFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prefer internal over external storage, because external tends to be FAT filesystems,
|
||||
* which don't support symlinks (which we test using this method).
|
||||
*/
|
||||
public static File getWriteableDir(Instrumentation instrumentation) {
|
||||
Context context = instrumentation.getContext();
|
||||
Context targetContext = instrumentation.getTargetContext();
|
||||
|
||||
File[] dirsToTry = new File[]{
|
||||
context.getCacheDir(),
|
||||
context.getFilesDir(),
|
||||
targetContext.getCacheDir(),
|
||||
targetContext.getFilesDir(),
|
||||
context.getExternalCacheDir(),
|
||||
context.getExternalFilesDir(null),
|
||||
targetContext.getExternalCacheDir(),
|
||||
targetContext.getExternalFilesDir(null),
|
||||
Environment.getExternalStorageDirectory(),
|
||||
};
|
||||
|
||||
return getWriteableDir(dirsToTry);
|
||||
}
|
||||
|
||||
private static File getWriteableDir(File[] dirsToTry) {
|
||||
|
||||
for (File dir : dirsToTry) {
|
||||
if (dir != null && dir.canWrite()) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.RepoUpdater.UpdateException;
|
||||
import org.fdroid.fdroid.data.Repo;
|
||||
import org.fdroid.fdroid.data.RepoProvider;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@Config(constants = BuildConfig.class)
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
public class AcceptableMultiRepoUpdaterTest extends MultiRepoUpdaterTest {
|
||||
private static final String TAG = "AcceptableMultiRepoTest";
|
||||
|
||||
private void assertSomewhatAcceptable() {
|
||||
Log.i(TAG, "Asserting at least one versions of each .apk is in index.");
|
||||
List<Repo> repos = RepoProvider.Helper.all(context);
|
||||
assertEquals("Repos", 3, repos.size());
|
||||
|
||||
assertApp2048();
|
||||
assertAppAdaway();
|
||||
assertAppAdbWireless();
|
||||
assertAppIcsImport();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableConflictingThenMainThenArchive() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateConflicting() && updateMain() && updateArchive()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableConflictingThenArchiveThenMain() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateConflicting() && updateArchive() && updateMain()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableArchiveThenMainThenConflicting() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateArchive() && updateMain() && updateConflicting()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableArchiveThenConflictingThenMain() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateArchive() && updateConflicting() && updateMain()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableMainThenArchiveThenConflicting() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateMain() && updateArchive() && updateConflicting()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableMainThenConflictingThenArchive() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateMain() && updateConflicting() && updateArchive()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -5,7 +5,6 @@ import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.RepoUpdater.UpdateException;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
@ -16,10 +15,6 @@ import org.fdroid.fdroid.data.Repo;
|
||||
import org.fdroid.fdroid.data.RepoProvider;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
@ -30,18 +25,16 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@Config(constants = BuildConfig.class)
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
public class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
private static final String TAG = "MultiRepoUpdaterTest";
|
||||
public abstract class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
private static final String TAG = "AcceptableMultiRepoUpdaterTest"; // NOPMD
|
||||
|
||||
private static final String REPO_MAIN = "Test F-Droid repo";
|
||||
private static final String REPO_ARCHIVE = "Test F-Droid repo (Archive)";
|
||||
private static final String REPO_CONFLICTING = "Test F-Droid repo with different apps";
|
||||
protected static final String REPO_MAIN = "Test F-Droid repo";
|
||||
protected static final String REPO_ARCHIVE = "Test F-Droid repo (Archive)";
|
||||
protected static final String REPO_CONFLICTING = "Test F-Droid repo with different apps";
|
||||
|
||||
private RepoUpdater conflictingRepoUpdater;
|
||||
private RepoUpdater mainRepoUpdater;
|
||||
private RepoUpdater archiveRepoUpdater;
|
||||
protected RepoUpdater conflictingRepoUpdater;
|
||||
protected RepoUpdater mainRepoUpdater;
|
||||
protected RepoUpdater archiveRepoUpdater;
|
||||
|
||||
private static final String PUB_KEY =
|
||||
"3082050b308202f3a003020102020420d8f212300d06092a864886f70d01010b050030363110300e0603" +
|
||||
@ -77,7 +70,7 @@ public class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
"e8af60597c4ae2977977cf61dc715a572e241ae717cafdb4f71781943945ac52e0f50b";
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
public final void setupMultiRepo() throws Exception {
|
||||
// On a fresh database install, there will be F-Droid + GP repos, including their Archive
|
||||
// repos that we are not interested in.
|
||||
RepoProvider.Helper.remove(context, 1);
|
||||
@ -93,123 +86,33 @@ public class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
public final void tearDownMultiRepo() {
|
||||
Preferences.clearSingletonForTesting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all of the expected apps and apk versions are available in the database. This
|
||||
* check will take into account the repository the apks came from, to ensure that each
|
||||
* repository indeed contains the apks that it said it would provide.
|
||||
*/
|
||||
private void assertExpected() {
|
||||
Log.i(TAG, "Asserting all versions of each .apk are in index.");
|
||||
List<Repo> repos = RepoProvider.Helper.all(context);
|
||||
assertEquals("Repos", 3, repos.size());
|
||||
|
||||
assertMainRepo(repos);
|
||||
assertMainArchiveRepo(repos);
|
||||
assertConflictingRepo(repos);
|
||||
}
|
||||
|
||||
private void assertSomewhatAcceptable() {
|
||||
Log.i(TAG, "Asserting at least one versions of each .apk is in index.");
|
||||
List<Repo> repos = RepoProvider.Helper.all(context);
|
||||
assertEquals("Repos", 3, repos.size());
|
||||
|
||||
assertApp2048();
|
||||
assertAppAdaway();
|
||||
assertAppAdbWireless();
|
||||
assertAppIcsImport();
|
||||
}
|
||||
|
||||
private void assertApp(String packageName, int[] versionCodes) {
|
||||
protected void assertApp(String packageName, int[] versionCodes) {
|
||||
List<Apk> apks = ApkProvider.Helper.findByPackageName(context, packageName, ApkProvider.DataColumns.ALL);
|
||||
assertApksExist(apks, packageName, versionCodes);
|
||||
}
|
||||
|
||||
private void assertApp2048() {
|
||||
protected void assertApp2048() {
|
||||
assertApp("com.uberspot.a2048", new int[]{19, 18});
|
||||
}
|
||||
|
||||
private void assertAppAdaway() {
|
||||
protected void assertAppAdaway() {
|
||||
assertApp("org.adaway", new int[]{54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 42, 40, 38, 37, 36, 35});
|
||||
}
|
||||
|
||||
private void assertAppAdbWireless() {
|
||||
protected void assertAppAdbWireless() {
|
||||
assertApp("siir.es.adbWireless", new int[]{12});
|
||||
}
|
||||
|
||||
private void assertAppIcsImport() {
|
||||
protected void assertAppIcsImport() {
|
||||
assertApp("org.dgtale.icsimport", new int[]{3, 2});
|
||||
}
|
||||
|
||||
/**
|
||||
* + 2048 (com.uberspot.a2048)
|
||||
* - Version 1.96 (19)
|
||||
* - Version 1.95 (18)
|
||||
* + AdAway (org.adaway)
|
||||
* - Version 3.0.2 (54)
|
||||
* - Version 3.0.1 (53)
|
||||
* - Version 3.0 (52)
|
||||
* + adbWireless (siir.es.adbWireless)
|
||||
* - Version 1.5.4 (12)
|
||||
*/
|
||||
private void assertMainRepo(List<Repo> allRepos) {
|
||||
Repo repo = findRepo(REPO_MAIN, allRepos);
|
||||
|
||||
List<Apk> apks = ApkProvider.Helper.findByRepo(context, repo, ApkProvider.DataColumns.ALL);
|
||||
assertEquals("Apks for main repo", apks.size(), 6);
|
||||
assertApksExist(apks, "com.uberspot.a2048", new int[]{18, 19});
|
||||
assertApksExist(apks, "org.adaway", new int[]{52, 53, 54});
|
||||
assertApksExist(apks, "siir.es.adbWireless", new int[]{12});
|
||||
}
|
||||
|
||||
/**
|
||||
* + AdAway (org.adaway)
|
||||
* - Version 2.9.2 (51)
|
||||
* - Version 2.9.1 (50)
|
||||
* - Version 2.9 (49)
|
||||
* - Version 2.8.1 (48)
|
||||
* - Version 2.8 (47)
|
||||
* - Version 2.7 (46)
|
||||
* - Version 2.6 (45)
|
||||
* - Version 2.3 (42)
|
||||
* - Version 2.1 (40)
|
||||
* - Version 1.37 (38)
|
||||
* - Version 1.36 (37)
|
||||
* - Version 1.35 (36)
|
||||
* - Version 1.34 (35)
|
||||
*/
|
||||
private void assertMainArchiveRepo(List<Repo> allRepos) {
|
||||
Repo repo = findRepo(REPO_ARCHIVE, allRepos);
|
||||
|
||||
List<Apk> apks = ApkProvider.Helper.findByRepo(context, repo, ApkProvider.DataColumns.ALL);
|
||||
assertEquals("Apks for main archive repo", 13, apks.size());
|
||||
assertApksExist(apks, "org.adaway", new int[]{35, 36, 37, 38, 40, 42, 45, 46, 47, 48, 49, 50, 51});
|
||||
}
|
||||
|
||||
/**
|
||||
* + AdAway (org.adaway)
|
||||
* - Version 3.0.1 (53) *
|
||||
* - Version 3.0 (52) *
|
||||
* - Version 2.9.2 (51) *
|
||||
* - Version 2.2.1 (50) *
|
||||
* + Add to calendar (org.dgtale.icsimport)
|
||||
* - Version 1.2 (3)
|
||||
* - Version 1.1 (2)
|
||||
*/
|
||||
private void assertConflictingRepo(List<Repo> allRepos) {
|
||||
Repo repo = findRepo(REPO_CONFLICTING, allRepos);
|
||||
|
||||
List<Apk> apks = ApkProvider.Helper.findByRepo(context, repo, ApkProvider.DataColumns.ALL);
|
||||
assertEquals("Apks for main repo", 6, apks.size());
|
||||
assertApksExist(apks, "org.adaway", new int[]{50, 51, 52, 53});
|
||||
assertApksExist(apks, "org.dgtale.icsimport", new int[]{2, 3});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Repo findRepo(@NonNull String name, List<Repo> allRepos) {
|
||||
protected Repo findRepo(@NonNull String name, List<Repo> allRepos) {
|
||||
Repo repo = null;
|
||||
for (Repo r : allRepos) {
|
||||
if (TextUtils.equals(name, r.getName())) {
|
||||
@ -225,7 +128,7 @@ public class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
/**
|
||||
* Checks that each version of appId as specified in versionCodes is present in apksToCheck.
|
||||
*/
|
||||
private void assertApksExist(List<Apk> apksToCheck, String appId, int[] versionCodes) {
|
||||
protected void assertApksExist(List<Apk> apksToCheck, String appId, int[] versionCodes) {
|
||||
for (int versionCode : versionCodes) {
|
||||
boolean found = false;
|
||||
for (Apk apk : apksToCheck) {
|
||||
@ -239,7 +142,7 @@ public class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void assertEmpty() {
|
||||
protected void assertEmpty() {
|
||||
assertEquals("No apps present", 0, AppProvider.Helper.all(context.getContentResolver()).size());
|
||||
|
||||
String[] packages = {
|
||||
@ -253,102 +156,6 @@ public class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
}
|
||||
}
|
||||
|
||||
/* At time fo writing, the following tests did not pass. This is because the multi-repo support
|
||||
in F-Droid was not sufficient. When working on proper multi repo support than this should be
|
||||
ucommented and all these tests should pass:
|
||||
|
||||
public void testCorrectConflictingThenMainThenArchive() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateConflicting() && updateMain() && updateArchive()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCorrectConflictingThenArchiveThenMain() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateConflicting() && updateArchive() && updateMain()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCorrectArchiveThenMainThenConflicting() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateArchive() && updateMain() && updateConflicting()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCorrectArchiveThenConflictingThenMain() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateArchive() && updateConflicting() && updateMain()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCorrectMainThenArchiveThenConflicting() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateMain() && updateArchive() && updateConflicting()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
public void testCorrectMainThenConflictingThenArchive() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateMain() && updateConflicting() && updateArchive()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testAcceptableConflictingThenMainThenArchive() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateConflicting() && updateMain() && updateArchive()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableConflictingThenArchiveThenMain() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateConflicting() && updateArchive() && updateMain()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableArchiveThenMainThenConflicting() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateArchive() && updateMain() && updateConflicting()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableArchiveThenConflictingThenMain() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateArchive() && updateConflicting() && updateMain()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableMainThenArchiveThenConflicting() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateMain() && updateArchive() && updateConflicting()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAcceptableMainThenConflictingThenArchive() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateMain() && updateConflicting() && updateArchive()) {
|
||||
assertSomewhatAcceptable();
|
||||
}
|
||||
}
|
||||
|
||||
private RepoUpdater createUpdater(String name, Context context) {
|
||||
Repo repo = new Repo();
|
||||
repo.signingCertificate = PUB_KEY;
|
||||
@ -367,15 +174,15 @@ public class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
return new RepoUpdater(context, RepoProvider.Helper.findByAddress(context, repo.address));
|
||||
}
|
||||
|
||||
private boolean updateConflicting() throws UpdateException {
|
||||
protected boolean updateConflicting() throws UpdateException {
|
||||
return updateRepo(conflictingRepoUpdater, "multiRepo.conflicting.jar");
|
||||
}
|
||||
|
||||
private boolean updateMain() throws UpdateException {
|
||||
protected boolean updateMain() throws UpdateException {
|
||||
return updateRepo(mainRepoUpdater, "multiRepo.normal.jar");
|
||||
}
|
||||
|
||||
private boolean updateArchive() throws UpdateException {
|
||||
protected boolean updateArchive() throws UpdateException {
|
||||
return updateRepo(archiveRepoUpdater, "multiRepo.archive.jar");
|
||||
}
|
||||
|
||||
@ -385,7 +192,7 @@ public class MultiRepoUpdaterTest extends FDroidProviderTest {
|
||||
updater.processDownloadedFile(indexJar);
|
||||
} finally {
|
||||
if (indexJar != null && indexJar.exists()) {
|
||||
indexJar.delete();
|
||||
assertTrue(indexJar.delete());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -0,0 +1,155 @@
|
||||
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.fdroid.fdroid.RepoUpdater.UpdateException;
|
||||
import org.fdroid.fdroid.data.Apk;
|
||||
import org.fdroid.fdroid.data.ApkProvider;
|
||||
import org.fdroid.fdroid.data.Repo;
|
||||
import org.fdroid.fdroid.data.RepoProvider;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/*
|
||||
At time fo writing, the following tests did not pass. This is because the multi-repo support
|
||||
in F-Droid was not sufficient. When working on proper multi repo support than this should be
|
||||
uncommented and all these tests will be required to pass:
|
||||
|
||||
@Config(constants = BuildConfig.class)
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
*/
|
||||
public class ProperMultiRepoUpdaterTest extends MultiRepoUpdaterTest {
|
||||
private static final String TAG = "ProperMultiRepoSupport";
|
||||
|
||||
@Test
|
||||
public void testCorrectConflictingThenMainThenArchive() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateConflicting() && updateMain() && updateArchive()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectConflictingThenArchiveThenMain() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateConflicting() && updateArchive() && updateMain()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectArchiveThenMainThenConflicting() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateArchive() && updateMain() && updateConflicting()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectArchiveThenConflictingThenMain() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateArchive() && updateConflicting() && updateMain()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectMainThenArchiveThenConflicting() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateMain() && updateArchive() && updateConflicting()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectMainThenConflictingThenArchive() throws UpdateException {
|
||||
assertEmpty();
|
||||
if (updateMain() && updateConflicting() && updateArchive()) {
|
||||
assertExpected();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that all of the expected apps and apk versions are available in the database. This
|
||||
* check will take into account the repository the apks came from, to ensure that each
|
||||
* repository indeed contains the apks that it said it would provide.
|
||||
*/
|
||||
private void assertExpected() {
|
||||
Log.i(TAG, "Asserting all versions of each .apk are in index.");
|
||||
List<Repo> repos = RepoProvider.Helper.all(context);
|
||||
assertEquals("Repos", 3, repos.size());
|
||||
|
||||
assertMainRepo(repos);
|
||||
assertMainArchiveRepo(repos);
|
||||
assertConflictingRepo(repos);
|
||||
}
|
||||
|
||||
/**
|
||||
* + 2048 (com.uberspot.a2048)
|
||||
* - Version 1.96 (19)
|
||||
* - Version 1.95 (18)
|
||||
* + AdAway (org.adaway)
|
||||
* - Version 3.0.2 (54)
|
||||
* - Version 3.0.1 (53)
|
||||
* - Version 3.0 (52)
|
||||
* + adbWireless (siir.es.adbWireless)
|
||||
* - Version 1.5.4 (12)
|
||||
*/
|
||||
private void assertMainRepo(List<Repo> allRepos) {
|
||||
Repo repo = findRepo(REPO_MAIN, allRepos);
|
||||
|
||||
List<Apk> apks = ApkProvider.Helper.findByRepo(context, repo, ApkProvider.DataColumns.ALL);
|
||||
assertEquals("Apks for main repo", apks.size(), 6);
|
||||
assertApksExist(apks, "com.uberspot.a2048", new int[]{18, 19});
|
||||
assertApksExist(apks, "org.adaway", new int[]{52, 53, 54});
|
||||
assertApksExist(apks, "siir.es.adbWireless", new int[]{12});
|
||||
}
|
||||
|
||||
/**
|
||||
* + AdAway (org.adaway)
|
||||
* - Version 2.9.2 (51)
|
||||
* - Version 2.9.1 (50)
|
||||
* - Version 2.9 (49)
|
||||
* - Version 2.8.1 (48)
|
||||
* - Version 2.8 (47)
|
||||
* - Version 2.7 (46)
|
||||
* - Version 2.6 (45)
|
||||
* - Version 2.3 (42)
|
||||
* - Version 2.1 (40)
|
||||
* - Version 1.37 (38)
|
||||
* - Version 1.36 (37)
|
||||
* - Version 1.35 (36)
|
||||
* - Version 1.34 (35)
|
||||
*/
|
||||
private void assertMainArchiveRepo(List<Repo> allRepos) {
|
||||
Repo repo = findRepo(REPO_ARCHIVE, allRepos);
|
||||
|
||||
List<Apk> apks = ApkProvider.Helper.findByRepo(context, repo, ApkProvider.DataColumns.ALL);
|
||||
assertEquals("Apks for main archive repo", 13, apks.size());
|
||||
assertApksExist(apks, "org.adaway", new int[]{35, 36, 37, 38, 40, 42, 45, 46, 47, 48, 49, 50, 51});
|
||||
}
|
||||
|
||||
/**
|
||||
* + AdAway (org.adaway)
|
||||
* - Version 3.0.1 (53) *
|
||||
* - Version 3.0 (52) *
|
||||
* - Version 2.9.2 (51) *
|
||||
* - Version 2.2.1 (50) *
|
||||
* + Add to calendar (org.dgtale.icsimport)
|
||||
* - Version 1.2 (3)
|
||||
* - Version 1.1 (2)
|
||||
*/
|
||||
private void assertConflictingRepo(List<Repo> allRepos) {
|
||||
Repo repo = findRepo(REPO_CONFLICTING, allRepos);
|
||||
|
||||
List<Apk> apks = ApkProvider.Helper.findByRepo(context, repo, ApkProvider.DataColumns.ALL);
|
||||
assertEquals("Apks for main repo", 6, apks.size());
|
||||
assertApksExist(apks, "org.adaway", new int[]{50, 51, 52, 53});
|
||||
assertApksExist(apks, "org.dgtale.icsimport", new int[]{2, 3});
|
||||
}
|
||||
|
||||
}
|
@ -6,11 +6,13 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class TestUtils {
|
||||
|
||||
private static final String TAG = "TestUtils";
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = "TestUtils"; // NOPMD
|
||||
|
||||
public static File copyResourceToTempFile(String resourceName) {
|
||||
File tempFile = null;
|
||||
@ -24,7 +26,7 @@ public class TestUtils {
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
if (tempFile != null && tempFile.exists()) {
|
||||
tempFile.delete();
|
||||
assertTrue(tempFile.delete());
|
||||
}
|
||||
fail();
|
||||
return null;
|
||||
|
@ -1,14 +1,14 @@
|
||||
|
||||
package org.fdroid.fdroid;
|
||||
|
||||
import android.app.Instrumentation;
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricGradleTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@ -17,7 +17,8 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@Config(constants = BuildConfig.class)
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
public class UtilsTest {
|
||||
|
||||
String fdroidFingerprint = "43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB";
|
||||
@ -50,7 +51,7 @@ public class UtilsTest {
|
||||
|
||||
@Test
|
||||
public void testFormatFingerprint() {
|
||||
Context context = InstrumentationRegistry.getTargetContext();
|
||||
Context context = RuntimeEnvironment.application;
|
||||
String badResult = Utils.formatFingerprint(context, "");
|
||||
// real fingerprints
|
||||
String formatted;
|
||||
@ -145,22 +146,29 @@ public class UtilsTest {
|
||||
|
||||
@Test
|
||||
public void testClearOldFiles() throws IOException, InterruptedException {
|
||||
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
|
||||
File dir = new File(TestUtilsOld.getWriteableDir(instrumentation), "clearOldFiles");
|
||||
File tempDir = new File(System.getProperty("java.io.tmpdir"));
|
||||
assertTrue(tempDir.isDirectory());
|
||||
assertTrue(tempDir.canWrite());
|
||||
|
||||
File dir = new File(tempDir, "F-Droid-test.clearOldFiles");
|
||||
FileUtils.deleteQuietly(dir);
|
||||
dir.mkdirs();
|
||||
assertTrue(dir.mkdirs());
|
||||
assertTrue(dir.isDirectory());
|
||||
|
||||
File first = new File(dir, "first");
|
||||
first.deleteOnExit();
|
||||
|
||||
File second = new File(dir, "second");
|
||||
second.deleteOnExit();
|
||||
|
||||
assertFalse(first.exists());
|
||||
assertFalse(second.exists());
|
||||
|
||||
first.createNewFile();
|
||||
assertTrue(first.createNewFile());
|
||||
assertTrue(first.exists());
|
||||
|
||||
Thread.sleep(7000);
|
||||
second.createNewFile();
|
||||
assertTrue(second.createNewFile());
|
||||
assertTrue(second.exists());
|
||||
|
||||
Utils.clearOldFiles(dir, 3);
|
@ -23,7 +23,6 @@ import java.util.List;
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertCantDelete;
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertContainsOnly;
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertResultCount;
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.insertApk;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
@ -38,8 +37,8 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
@Test
|
||||
public void testAppApks() {
|
||||
for (int i = 1; i <= 10; i++) {
|
||||
insertApk(contentResolver, "org.fdroid.fdroid", i);
|
||||
insertApk(contentResolver, "com.example", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "org.fdroid.fdroid", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "com.example", i);
|
||||
}
|
||||
|
||||
assertTotalApkCount(20);
|
||||
@ -187,23 +186,12 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
Apk apk = new MockApk("org.fdroid.fdroid", 13);
|
||||
|
||||
// Insert a new record...
|
||||
Uri newUri = insertApk(contentResolver, apk.packageName, apk.versionCode);
|
||||
Uri newUri = ProviderTestUtils.insertApk(contentResolver, apk.packageName, apk.versionCode);
|
||||
assertEquals(ApkProvider.getContentUri(apk).toString(), newUri.toString());
|
||||
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
|
||||
// PACKAGE_NAME.
|
||||
@ -214,12 +202,19 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
assertEquals(13, toCheck.versionCode);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCursorMustMoveToFirst() {
|
||||
ProviderTestUtils.insertApk(contentResolver, "org.example.test", 12);
|
||||
Cursor cursor = queryAllApks();
|
||||
new Apk(cursor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCount() {
|
||||
String[] projectionCount = new String[] {ApkProvider.DataColumns._COUNT};
|
||||
|
||||
for (int i = 0; i < 13; i++) {
|
||||
insertApk(contentResolver, "com.example", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "com.example", i);
|
||||
}
|
||||
|
||||
Uri all = ApkProvider.getContentUri();
|
||||
@ -236,38 +231,48 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
allWithCount.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertWithExtraFields() {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testInsertWithInvalidExtraFieldDescription() {
|
||||
assertInvalidExtraField(RepoProvider.DataColumns.DESCRIPTION);
|
||||
}
|
||||
|
||||
assertResultCount(0, queryAllApks());
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testInsertWithInvalidExtraFieldAddress() {
|
||||
assertInvalidExtraField(RepoProvider.DataColumns.ADDRESS);
|
||||
}
|
||||
|
||||
String[] repoFields = new String[] {
|
||||
RepoProvider.DataColumns.DESCRIPTION,
|
||||
RepoProvider.DataColumns.ADDRESS,
|
||||
RepoProvider.DataColumns.FINGERPRINT,
|
||||
RepoProvider.DataColumns.NAME,
|
||||
RepoProvider.DataColumns.SIGNING_CERT,
|
||||
};
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testInsertWithInvalidExtraFieldFingerprint() {
|
||||
assertInvalidExtraField(RepoProvider.DataColumns.FINGERPRINT);
|
||||
}
|
||||
|
||||
for (String field : repoFields) {
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testInsertWithInvalidExtraFieldName() {
|
||||
assertInvalidExtraField(RepoProvider.DataColumns.NAME);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testInsertWithInvalidExtraFieldSigningCert() {
|
||||
assertInvalidExtraField(RepoProvider.DataColumns.SIGNING_CERT);
|
||||
}
|
||||
|
||||
public void assertInvalidExtraField(String field) {
|
||||
ContentValues invalidRepo = new ContentValues();
|
||||
invalidRepo.put(field, "Test data");
|
||||
try {
|
||||
insertApk(contentResolver, "org.fdroid.fdroid", 10, invalidRepo);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
ProviderTestUtils.insertApk(contentResolver, "org.fdroid.fdroid", 10, invalidRepo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertWithValidExtraFields() {
|
||||
|
||||
assertResultCount(0, queryAllApks());
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(ApkProvider.DataColumns.REPO_ID, 10);
|
||||
values.put(ApkProvider.DataColumns.REPO_ADDRESS, "http://example.com");
|
||||
values.put(ApkProvider.DataColumns.REPO_VERSION, 3);
|
||||
values.put(ApkProvider.DataColumns.FEATURES, "Some features");
|
||||
Uri uri = insertApk(contentResolver, "com.example.com", 1, values);
|
||||
Uri uri = ProviderTestUtils.insertApk(contentResolver, "com.example.com", 1, values);
|
||||
|
||||
assertResultCount(1, queryAllApks());
|
||||
|
||||
@ -293,18 +298,18 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
public void testKnownApks() {
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
insertApk(contentResolver, "org.fdroid.fdroid", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "org.fdroid.fdroid", i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
insertApk(contentResolver, "org.example", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "org.example", i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
insertApk(contentResolver, "com.example", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "com.example", i);
|
||||
}
|
||||
|
||||
insertApk(contentResolver, "com.apk.thingo", 1);
|
||||
ProviderTestUtils.insertApk(contentResolver, "com.apk.thingo", 1);
|
||||
|
||||
Apk[] known = {
|
||||
new MockApk("org.fdroid.fdroid", 1),
|
||||
@ -351,18 +356,18 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
public void testFindByApp() {
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
insertApk(contentResolver, "org.fdroid.fdroid", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "org.fdroid.fdroid", i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 9; i++) {
|
||||
insertApk(contentResolver, "org.example", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "org.example", i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
insertApk(contentResolver, "com.example", i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "com.example", i);
|
||||
}
|
||||
|
||||
insertApk(contentResolver, "com.apk.thingo", 1);
|
||||
ProviderTestUtils.insertApk(contentResolver, "com.apk.thingo", 1);
|
||||
|
||||
assertTotalApkCount(7 + 9 + 3 + 1);
|
||||
|
||||
@ -386,7 +391,7 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
|
||||
Uri apkUri = insertApk(contentResolver, "com.example", 10);
|
||||
Uri apkUri = ProviderTestUtils.insertApk(contentResolver, "com.example", 10);
|
||||
|
||||
String[] allFields = ApkProvider.DataColumns.ALL;
|
||||
Cursor cursor = contentResolver.query(apkUri, allFields, null, null, null);
|
||||
@ -442,18 +447,18 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
// the Helper.find() method doesn't stumble upon the app we are interested
|
||||
// in by shear dumb luck...
|
||||
for (int i = 0; i < 10; i++) {
|
||||
insertApk(contentResolver, "org.fdroid.apk." + i, i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "org.fdroid.apk." + i, i);
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(ApkProvider.DataColumns.VERSION_NAME, "v1.1");
|
||||
values.put(ApkProvider.DataColumns.HASH, "xxxxyyyy");
|
||||
values.put(ApkProvider.DataColumns.HASH_TYPE, "a hash type");
|
||||
insertApk(contentResolver, "com.example", 11, values);
|
||||
ProviderTestUtils.insertApk(contentResolver, "com.example", 11, values);
|
||||
|
||||
// ...and a few more for good measure...
|
||||
for (int i = 15; i < 20; i++) {
|
||||
insertApk(contentResolver, "com.other.thing." + i, i);
|
||||
ProviderTestUtils.insertApk(contentResolver, "com.other.thing." + i, i);
|
||||
}
|
||||
|
||||
Apk apk = ApkProvider.Helper.find(context, "com.example", 11);
|
||||
@ -529,7 +534,7 @@ public class ApkProviderTest extends FDroidProviderTest {
|
||||
protected Apk insertApkForRepo(String id, int versionCode, long repoId) {
|
||||
ContentValues additionalValues = new ContentValues();
|
||||
additionalValues.put(ApkProvider.DataColumns.REPO_ID, repoId);
|
||||
Uri uri = insertApk(contentResolver, id, versionCode, additionalValues);
|
||||
Uri uri = ProviderTestUtils.insertApk(contentResolver, id, versionCode, additionalValues);
|
||||
return ApkProvider.Helper.get(context, uri);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ 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)
|
||||
@ -224,17 +223,6 @@ public class AppProviderTest extends FDroidProviderTest {
|
||||
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.
|
||||
@ -250,6 +238,17 @@ public class AppProviderTest extends FDroidProviderTest {
|
||||
assertEquals("F-Droid", otherApp.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* We intentionally throw an IllegalArgumentException if you haven't
|
||||
* yet called cursor.move*().
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testCursorMustMoveToFirst() {
|
||||
insertApp("org.fdroid.fdroid", "F-Droid");
|
||||
Cursor cursor = queryAllApps();
|
||||
new App(cursor);
|
||||
}
|
||||
|
||||
private Cursor queryAllApps() {
|
||||
String[] projection = new String[] {
|
||||
AppProvider.DataColumns._ID,
|
||||
|
@ -19,7 +19,6 @@ import static org.fdroid.fdroid.data.ProviderTestUtils.assertResultCount;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@ -85,24 +84,12 @@ public class InstalledAppProviderTest extends FDroidProviderTest{
|
||||
|
||||
@Test
|
||||
public void testUpdate() {
|
||||
|
||||
insertInstalledApp("com.example.app1", 10, "1.0");
|
||||
insertInstalledApp("com.example.app2", 10, "1.0");
|
||||
|
||||
assertResultCount(contentResolver, 2, InstalledAppProvider.getContentUri());
|
||||
assertIsInstalledVersionInDb(contentResolver, "com.example.app2", 10, "1.0");
|
||||
|
||||
try {
|
||||
contentResolver.update(
|
||||
InstalledAppProvider.getAppUri("com.example.app2"),
|
||||
createContentValues(11, "1.1"),
|
||||
null, null
|
||||
);
|
||||
fail();
|
||||
} catch (UnsupportedOperationException e) {
|
||||
// We expect this to happen, because we should be using insert() instead.
|
||||
}
|
||||
|
||||
contentResolver.insert(
|
||||
InstalledAppProvider.getContentUri(),
|
||||
createContentValues("com.example.app2", 11, "1.1")
|
||||
@ -110,7 +97,19 @@ public class InstalledAppProviderTest extends FDroidProviderTest{
|
||||
|
||||
assertResultCount(contentResolver, 2, InstalledAppProvider.getContentUri());
|
||||
assertIsInstalledVersionInDb(contentResolver, "com.example.app2", 11, "1.1");
|
||||
}
|
||||
|
||||
/**
|
||||
* We expect this to happen, because we should be using insert() instead as it will
|
||||
* do an insert/replace query.
|
||||
*/
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testUpdateFails() {
|
||||
contentResolver.update(
|
||||
InstalledAppProvider.getAppUri("com.example.app2"),
|
||||
createContentValues(11, "1.1"),
|
||||
null, null
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -17,7 +17,6 @@ import java.util.List;
|
||||
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertInvalidUri;
|
||||
import static org.fdroid.fdroid.data.ProviderTestUtils.assertValidUri;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
@Config(constants = BuildConfig.class)
|
||||
@RunWith(RobolectricGradleTestRunner.class)
|
||||
@ -124,6 +123,11 @@ public class ProviderUriTests {
|
||||
assertValidUri(resolver, ApkProvider.getContentUri(apks), projection);
|
||||
assertValidUri(resolver, ApkProvider.getContentUri("org.fdroid.fdroid", 100), "content://org.fdroid.fdroid.data.ApkProvider/apk/100/org.fdroid.fdroid", projection);
|
||||
assertValidUri(resolver, ApkProvider.getRepoUri(1000), "content://org.fdroid.fdroid.data.ApkProvider/repo/1000", projection);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void invalidApkUrisWithTooManyApks() {
|
||||
String[] projection = ApkProvider.DataColumns.ALL;
|
||||
|
||||
List<Apk> manyApks = new ArrayList<>(ApkProvider.MAX_APKS_TO_QUERY - 5);
|
||||
for (int i = 0; i < ApkProvider.MAX_APKS_TO_QUERY - 1; i++) {
|
||||
@ -133,18 +137,12 @@ public class ProviderUriTests {
|
||||
|
||||
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(resolver, ApkProvider.getContentUri(manyApks), projection);
|
||||
fail();
|
||||
} catch (IllegalArgumentException e) {
|
||||
// This is the expected error behaviour.
|
||||
} catch (Exception e) {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
BIN
app/src/test/resources/simpleIndex.jar
Normal file
BIN
app/src/test/resources/simpleIndex.jar
Normal file
Binary file not shown.
9
config/pmd/rules-main.xml
Normal file
9
config/pmd/rules-main.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="Custom ruleset (for main code)"
|
||||
xmlns="http://pmd.sf.net/ruleset/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
|
||||
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
|
||||
|
||||
<rule ref="rulesets/java/imports.xml" />
|
||||
</ruleset>
|
11
config/pmd/rules-test.xml
Normal file
11
config/pmd/rules-test.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0"?>
|
||||
<ruleset name="Custom ruleset (for tests)"
|
||||
xmlns="http://pmd.sf.net/ruleset/1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
|
||||
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
|
||||
|
||||
<rule ref="rulesets/java/imports.xml">
|
||||
<exclude name="TooManyStaticImports" /><!-- Static imports are commonly used for JUnit tests -->
|
||||
</rule>
|
||||
</ruleset>
|
@ -12,7 +12,6 @@
|
||||
<rule ref="rulesets/java/android.xml"/>
|
||||
<rule ref="rulesets/java/clone.xml"/>
|
||||
<rule ref="rulesets/java/finalizers.xml"/>
|
||||
<rule ref="rulesets/java/imports.xml"/>
|
||||
<rule ref="rulesets/java/migrating.xml"/>
|
||||
<rule ref="rulesets/java/unnecessary.xml">
|
||||
<exclude name="UselessParentheses"/> <!--Too nitpicky-->
|
||||
|
Loading…
x
Reference in New Issue
Block a user