From 4e73d1e5e6c50815bec692493e2d6ab7c525ae98 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Thu, 9 Jun 2016 09:55:12 +1000 Subject: [PATCH] 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. --- app/build.gradle | 15 +- app/src/androidTest/assets/simpleIndex.jar | Bin 2412 -> 0 bytes .../test/ProviderTestCase2MockContext.java | 257 ------------------ .../org/fdroid/fdroid/FileCompatTest.java | 86 ++++-- .../java/org/fdroid/fdroid/TestUtilsOld.java | 73 ----- .../AcceptableMultiRepoUpdaterTest.java | 82 ++++++ .../fdroid/fdroid/MultiRepoUpdaterTest.java | 237 ++-------------- .../fdroid/ProperMultiRepoUpdaterTest.java | 155 +++++++++++ .../java/org/fdroid/fdroid/TestUtils.java | 6 +- .../java/org/fdroid/fdroid/UtilsTest.java | 28 +- .../fdroid/fdroid/data/ApkProviderTest.java | 109 ++++---- .../fdroid/fdroid/data/AppProviderTest.java | 23 +- .../fdroid/data/InstalledAppProviderTest.java | 25 +- .../fdroid/fdroid/data/ProviderUriTests.java | 24 +- .../assets => test/resources}/README.md | 0 .../resources}/masterKeyIndex.jar | Bin app/src/test/resources/simpleIndex.jar | Bin 0 -> 2412 bytes .../simpleIndexWithCorruptedCertificate.jar | Bin .../simpleIndexWithCorruptedEverything.jar | Bin .../simpleIndexWithCorruptedManifest.jar | Bin .../simpleIndexWithCorruptedSignature.jar | Bin .../simpleIndexWithoutSignature.jar | Bin config/pmd/rules-main.xml | 9 + config/pmd/rules-test.xml | 11 + config/pmd/rules.xml | 1 - 25 files changed, 474 insertions(+), 667 deletions(-) delete mode 100644 app/src/androidTest/java/android/test/ProviderTestCase2MockContext.java delete mode 100644 app/src/androidTest/java/org/fdroid/fdroid/TestUtilsOld.java create mode 100644 app/src/test/java/org/fdroid/fdroid/AcceptableMultiRepoUpdaterTest.java create mode 100644 app/src/test/java/org/fdroid/fdroid/ProperMultiRepoUpdaterTest.java rename app/src/{androidTest => test}/java/org/fdroid/fdroid/UtilsTest.java (97%) rename app/src/{androidTest/assets => test/resources}/README.md (100%) rename app/src/{androidTest/assets => test/resources}/masterKeyIndex.jar (100%) create mode 100644 app/src/test/resources/simpleIndex.jar rename app/src/{androidTest/assets => test/resources}/simpleIndexWithCorruptedCertificate.jar (100%) rename app/src/{androidTest/assets => test/resources}/simpleIndexWithCorruptedEverything.jar (100%) rename app/src/{androidTest/assets => test/resources}/simpleIndexWithCorruptedManifest.jar (100%) rename app/src/{androidTest/assets => test/resources}/simpleIndexWithCorruptedSignature.jar (100%) rename app/src/{androidTest/assets => test/resources}/simpleIndexWithoutSignature.jar (100%) create mode 100644 config/pmd/rules-main.xml create mode 100644 config/pmd/rules-test.xml diff --git a/app/build.gradle b/app/build.gradle index 9443a8917..a9bf227f2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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 diff --git a/app/src/androidTest/assets/simpleIndex.jar b/app/src/androidTest/assets/simpleIndex.jar index 1c173ceb37eb2898f6dbb0df4a9dc849d943c919..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 2412 zcma)82{hDe8z0LsvXpG)VsdH7GPcYZQK@E%F-(YS8QmBRS!xiYELVM|L?jwnK9$Iq zE&GQoX_PTz#uhSCx3M(VM9me$9i4M=`@Zv?@A;qqIq!Sk^ZT9WJn!@Veh(HcA}S96 zfj|K9qMQ?eZ6PmMV~|c(`qp+R1B{iOH45qI1jV2hF$}sbS|8dYjn>y;GFVj(hW#e* z$B9rIjGi^7C;W-1MCSBfYPPZt;SZ(#kjY0nW|K+^V@mt)0y55jCN2<{_fHhM9l%c% zJaYbcW^CdU5qQ~5d8z?lDAHBq09ukfcqy4-u*gjMbTKK623jfwSu^YwW%_Pa1G!=V zELt3-pfAUY5o8xH__6aFeaUu`_i%|A92%$2*m$A6fux5%3p=Ar6`g>mtvPY z(_$^bBGQD7kAk2#WHF~@LG>+Z4l8nJq7 zhH0N>S2{sZxBhb1sL$m1e8Li_rnx!xdpXqLBe%K)rC9l&owhrF~G!z9henOzYw zk<*ZqyD1cct`;)zkk)`>Z{B?nCj|Z}R9mvnura#~eLBWB@j>Qqpi|deGwb#lX;nNj zLui;795Q7cwaXdornXW$Mp|228AFCPIfK;h*4}PV=YCqr%jFK}IlRxW!81OFgc*E5 zApRFGZrNlmUHfOgUuSk~o3Sa9A3;%=QAD^^C9Qn;y=-nyWHvNIQLo`C8NOb|VtT&0 zrkoqz0tV_0(Mzi5Mko3mkHGJB^`F&P)w3LU>hos78$5MW^`04+@6h0EO#pY-D0=2z5S~3Qq+#;O?d%laSZk z+teK|eYwUBj?J5i?We{p^uPE7tA2_XGqI@@=NIrNu97>RH{8FCp?EzjT;Z3~w)4OFx-A)6m1&Rji#o)XaOH zfc8~1K8e0m(UjMX)im|TrN^By;uOB?gY}FuLDM zI1jRjJ+Q!MKHZV3nJ}rOQ#WJ?!$&cgqJWjqI)Yv1UAWOZcQOFl%*$T|yyUzBtrWd_#5_Q*rKHxv4=N-E-{~J7jbfY{5jv zT0mBp^8EB6I_8bb!wOpete%=|4py-IaAP{!z;9v*x3-py8z^`l%IpO`oNh~UwH;Mq zAK}D!BIyp_JGeJrVK`P80N5e2{XvWUAV?Ab(X9?%>jVHqzJmpQ4G>_z$CeuWCl~`mJ28*c(+4@!W}(D?QcN7P~yYNHfEA|tzX6RO79&ET)(?n zA;H$&;!#m3NbPX+5!EiZ>wr;S9^^_K?Ml?)rCLV5C0MbZ;rnSWirw%oRt-8yq2+Kj z?fd3=Ewd|k>OH1iNYPm;cuDQgzQ=zCh<_`f$43D4SFjP1vWW#M(aZ`h{>f;aYwiHV ziJErs70-=0^bk?4HM&clUXXU8iX&;TVbOzj$AFliM+6y`#@2 z%$3qVXCKBqcRzb@-ru9Aj^D^zFV^+uu6Ihz<;2l5+05i&VdrZ$KMTq+m&=%0GbNDF+5U_7Ziv+=MHom+Fx1m&^9U17&x+L%3%G0lh~r zBxXQfx3~7AYoK?%4jGx>FanOlE+;A(gf8-ciD5z9ltI1jMU(}|_ zCk6E?B|B-}3(R6EiPU>dkgPicN?EuG`ggurnew65Jjq;IY|1=)}v_Rn+ zZCuB-hl&)npSXnBxG5FmveI|%o_(#d-e?e_{L#NBYPw##uIb!sCpY4kX4!DA+rf-L zVB#o_<2Ysd3j37}+5I6W=t6VDu$PYMuOT=tv%NBmaz3mvOdaA6Bc5(cyd)QHcVHLA zR^RXIt}NskQ0Nm(^|L}70;xoK#b#H5Qb(#@nkTBd>iKQhA!mA-rmXL*;)Ke5Q!Rq& zfVIzCNhC6`l$h*LxjQpROojw@wFGz!t?u(ehIpW`dmKEgTm=s@?k@#%TrSL zYcONAiShA^V9h=$@jDrmi*Ldvm*-Lpye3A)cbaFZHr)#H^bBVOPJJ`-l>(D< z>ckh9i3piO%S)!5lFW)2P-8waNh;YR#KW!FV*gR^?qDP*7)zi&NFQmZ{ zOeKAu5^$uFuhC$zNGn+kKSyGnn0=H%cn*dJmra|sjEt}?z%C|v^P|h8H)z$x@Ft@r zwXlfD)l-b$QMp-Qjb-}{bG5!%rnyJ(4l95gZ&65C9V=`P!bg&!HV zd)40=S_NdA44eMsi29LXyH;#?+E%cH{u_h9;kHx!r3-&4#)hbD#cjc6Gl>m}`4PIk eIuctr!HOw>ZVC(*4HVlr1qwcdAT3qU#_mtJ{_K$e diff --git a/app/src/androidTest/java/android/test/ProviderTestCase2MockContext.java b/app/src/androidTest/java/android/test/ProviderTestCase2MockContext.java deleted file mode 100644 index 405902649..000000000 --- a/app/src/androidTest/java/android/test/ProviderTestCase2MockContext.java +++ /dev/null @@ -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. - *

- * This test case also sets up the following mock objects: - *

- *
    - *
  • - * 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. - *
  • - *
  • - * 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. - *
  • - *
  • - * An instance of the provider under test, running in an {@link IsolatedContext}. - *
  • - *
- *

- * 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. - *

- *

- * 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. - *

- * For more information on content provider testing, please see - * Content Provider Testing. - */ -public abstract class ProviderTestCase2MockContext extends AndroidTestCase { - - Class 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 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. - *

- * 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. - *

- * - * @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. - *

- * 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; - } - - /** - *

- * 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. - *

- *

- * 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. - *

- *

- * This is a convenience method for creating a "mock" provider that can contain test data. - *

- * - * @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 - * sqlite3 tool's .dump command. - * @return ContentResolver A new {@link MockContentResolver} linked to the provider - * - * @throws IllegalAccessException - * @throws InstantiationException - */ - public static ContentResolver newResolverWithContentProviderFromSql( - Context targetContext, String filenamePrefix, Class 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; - } -} diff --git a/app/src/androidTest/java/org/fdroid/fdroid/FileCompatTest.java b/app/src/androidTest/java/org/fdroid/fdroid/FileCompatTest.java index ff7e86378..18456f749 100644 --- a/app/src/androidTest/java/org/fdroid/fdroid/FileCompatTest.java +++ b/app/src/androidTest/java/org/fdroid/fdroid/FileCompatTest.java @@ -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) { - 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); - } + assumeTrue(Build.VERSION.SDK_INT >= 19); + FileCompatForTest.symlinkLibcoreTest(sourceFile, destFile); + assertTrue(destFile.getAbsolutePath() + " should exist after symlinking", destFile.exists()); } @Test public void testSymlinkOs() { - - if (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); - } + assumeTrue(Build.VERSION.SDK_INT >= 21); + FileCompatForTest.symlinkOsTest(sourceFile, destFile); + assertTrue(destFile.getAbsolutePath() + " should exist after symlinking", destFile.exists()); } + @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; + } } diff --git a/app/src/androidTest/java/org/fdroid/fdroid/TestUtilsOld.java b/app/src/androidTest/java/org/fdroid/fdroid/TestUtilsOld.java deleted file mode 100644 index df8144457..000000000 --- a/app/src/androidTest/java/org/fdroid/fdroid/TestUtilsOld.java +++ /dev/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; - } -} diff --git a/app/src/test/java/org/fdroid/fdroid/AcceptableMultiRepoUpdaterTest.java b/app/src/test/java/org/fdroid/fdroid/AcceptableMultiRepoUpdaterTest.java new file mode 100644 index 000000000..d159c6018 --- /dev/null +++ b/app/src/test/java/org/fdroid/fdroid/AcceptableMultiRepoUpdaterTest.java @@ -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 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(); + } + } + +} diff --git a/app/src/test/java/org/fdroid/fdroid/MultiRepoUpdaterTest.java b/app/src/test/java/org/fdroid/fdroid/MultiRepoUpdaterTest.java index ac77a566d..79e31254b 100644 --- a/app/src/test/java/org/fdroid/fdroid/MultiRepoUpdaterTest.java +++ b/app/src/test/java/org/fdroid/fdroid/MultiRepoUpdaterTest.java @@ -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 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 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 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 allRepos) { - Repo repo = findRepo(REPO_MAIN, allRepos); - - List 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 allRepos) { - Repo repo = findRepo(REPO_ARCHIVE, allRepos); - - List 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 allRepos) { - Repo repo = findRepo(REPO_CONFLICTING, allRepos); - - List 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 allRepos) { + protected Repo findRepo(@NonNull String name, List 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 apksToCheck, String appId, int[] versionCodes) { + protected void assertApksExist(List 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; diff --git a/app/src/test/java/org/fdroid/fdroid/ProperMultiRepoUpdaterTest.java b/app/src/test/java/org/fdroid/fdroid/ProperMultiRepoUpdaterTest.java new file mode 100644 index 000000000..da7105e42 --- /dev/null +++ b/app/src/test/java/org/fdroid/fdroid/ProperMultiRepoUpdaterTest.java @@ -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 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 allRepos) { + Repo repo = findRepo(REPO_MAIN, allRepos); + + List 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 allRepos) { + Repo repo = findRepo(REPO_ARCHIVE, allRepos); + + List 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 allRepos) { + Repo repo = findRepo(REPO_CONFLICTING, allRepos); + + List 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}); + } + +} diff --git a/app/src/test/java/org/fdroid/fdroid/TestUtils.java b/app/src/test/java/org/fdroid/fdroid/TestUtils.java index 598c60a3b..2ced7a025 100644 --- a/app/src/test/java/org/fdroid/fdroid/TestUtils.java +++ b/app/src/test/java/org/fdroid/fdroid/TestUtils.java @@ -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; diff --git a/app/src/androidTest/java/org/fdroid/fdroid/UtilsTest.java b/app/src/test/java/org/fdroid/fdroid/UtilsTest.java similarity index 97% rename from app/src/androidTest/java/org/fdroid/fdroid/UtilsTest.java rename to app/src/test/java/org/fdroid/fdroid/UtilsTest.java index 3aadf8849..7ec649ca3 100644 --- a/app/src/androidTest/java/org/fdroid/fdroid/UtilsTest.java +++ b/app/src/test/java/org/fdroid/fdroid/UtilsTest.java @@ -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); diff --git a/app/src/test/java/org/fdroid/fdroid/data/ApkProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/ApkProviderTest.java index 02a0e379c..6d3c6811e 100644 --- a/app/src/test/java/org/fdroid/fdroid/data/ApkProviderTest.java +++ b/app/src/test/java/org/fdroid/fdroid/data/ApkProviderTest.java @@ -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(expected = IllegalArgumentException.class) + public void testInsertWithInvalidExtraFieldDescription() { + assertInvalidExtraField(RepoProvider.DataColumns.DESCRIPTION); + } + + @Test(expected = IllegalArgumentException.class) + public void testInsertWithInvalidExtraFieldAddress() { + assertInvalidExtraField(RepoProvider.DataColumns.ADDRESS); + } + + @Test(expected = IllegalArgumentException.class) + public void testInsertWithInvalidExtraFieldFingerprint() { + assertInvalidExtraField(RepoProvider.DataColumns.FINGERPRINT); + } + + @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"); + ProviderTestUtils.insertApk(contentResolver, "org.fdroid.fdroid", 10, invalidRepo); + } + @Test - public void testInsertWithExtraFields() { + public void testInsertWithValidExtraFields() { assertResultCount(0, queryAllApks()); - String[] repoFields = new String[] { - RepoProvider.DataColumns.DESCRIPTION, - RepoProvider.DataColumns.ADDRESS, - RepoProvider.DataColumns.FINGERPRINT, - RepoProvider.DataColumns.NAME, - RepoProvider.DataColumns.SIGNING_CERT, - }; - - for (String field : repoFields) { - 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(); - } - 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); } } diff --git a/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java index 3aa382521..779ca10f4 100644 --- a/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java +++ b/app/src/test/java/org/fdroid/fdroid/data/AppProviderTest.java @@ -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, diff --git a/app/src/test/java/org/fdroid/fdroid/data/InstalledAppProviderTest.java b/app/src/test/java/org/fdroid/fdroid/data/InstalledAppProviderTest.java index 1d537de18..5afc4cfc2 100644 --- a/app/src/test/java/org/fdroid/fdroid/data/InstalledAppProviderTest.java +++ b/app/src/test/java/org/fdroid/fdroid/data/InstalledAppProviderTest.java @@ -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 diff --git a/app/src/test/java/org/fdroid/fdroid/data/ProviderUriTests.java b/app/src/test/java/org/fdroid/fdroid/data/ProviderUriTests.java index 9fa7d9d9a..2e75977ea 100644 --- a/app/src/test/java/org/fdroid/fdroid/data/ProviderUriTests.java +++ b/app/src/test/java/org/fdroid/fdroid/data/ProviderUriTests.java @@ -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 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(); - } + + // 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); } } diff --git a/app/src/androidTest/assets/README.md b/app/src/test/resources/README.md similarity index 100% rename from app/src/androidTest/assets/README.md rename to app/src/test/resources/README.md diff --git a/app/src/androidTest/assets/masterKeyIndex.jar b/app/src/test/resources/masterKeyIndex.jar similarity index 100% rename from app/src/androidTest/assets/masterKeyIndex.jar rename to app/src/test/resources/masterKeyIndex.jar diff --git a/app/src/test/resources/simpleIndex.jar b/app/src/test/resources/simpleIndex.jar new file mode 100644 index 0000000000000000000000000000000000000000..1c173ceb37eb2898f6dbb0df4a9dc849d943c919 GIT binary patch literal 2412 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 literal 0 HcmV?d00001 diff --git a/app/src/androidTest/assets/simpleIndexWithCorruptedCertificate.jar b/app/src/test/resources/simpleIndexWithCorruptedCertificate.jar similarity index 100% rename from app/src/androidTest/assets/simpleIndexWithCorruptedCertificate.jar rename to app/src/test/resources/simpleIndexWithCorruptedCertificate.jar diff --git a/app/src/androidTest/assets/simpleIndexWithCorruptedEverything.jar b/app/src/test/resources/simpleIndexWithCorruptedEverything.jar similarity index 100% rename from app/src/androidTest/assets/simpleIndexWithCorruptedEverything.jar rename to app/src/test/resources/simpleIndexWithCorruptedEverything.jar diff --git a/app/src/androidTest/assets/simpleIndexWithCorruptedManifest.jar b/app/src/test/resources/simpleIndexWithCorruptedManifest.jar similarity index 100% rename from app/src/androidTest/assets/simpleIndexWithCorruptedManifest.jar rename to app/src/test/resources/simpleIndexWithCorruptedManifest.jar diff --git a/app/src/androidTest/assets/simpleIndexWithCorruptedSignature.jar b/app/src/test/resources/simpleIndexWithCorruptedSignature.jar similarity index 100% rename from app/src/androidTest/assets/simpleIndexWithCorruptedSignature.jar rename to app/src/test/resources/simpleIndexWithCorruptedSignature.jar diff --git a/app/src/androidTest/assets/simpleIndexWithoutSignature.jar b/app/src/test/resources/simpleIndexWithoutSignature.jar similarity index 100% rename from app/src/androidTest/assets/simpleIndexWithoutSignature.jar rename to app/src/test/resources/simpleIndexWithoutSignature.jar diff --git a/config/pmd/rules-main.xml b/config/pmd/rules-main.xml new file mode 100644 index 000000000..5b33b45d8 --- /dev/null +++ b/config/pmd/rules-main.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/config/pmd/rules-test.xml b/config/pmd/rules-test.xml new file mode 100644 index 000000000..0889f5bcf --- /dev/null +++ b/config/pmd/rules-test.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/config/pmd/rules.xml b/config/pmd/rules.xml index 3e4600f4e..e9a161577 100644 --- a/config/pmd/rules.xml +++ b/config/pmd/rules.xml @@ -12,7 +12,6 @@ -