Merge branch 'more-tests-and-bug-fixes' into 'master'

More tests and bug fixes

I pulled a few commits out of the !248 saga, and added a bug fix or two.  It would be easier if this was merged before !248 

ping @mvdan @pserwylo 

See merge request !255
This commit is contained in:
Daniel Martí 2016-04-11 16:48:42 +00:00
commit 5fd591bbe8
13 changed files with 147 additions and 111 deletions

View File

@ -30,6 +30,10 @@ dependencies {
compile 'io.reactivex:rxandroid:0.23.0'
testCompile 'junit:junit:4.12'
androidTestCompile 'com.android.support:support-annotations:23.2.1'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
}
if (!hasProperty('sourceDeps')) {
@ -147,6 +151,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_7
}
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
testOptions {
// prevent tests from dying on android.util.Log calls
unitTests.returnDefaultValues = true

View File

@ -1,14 +0,0 @@
package org.fdroid.fdroid;
import android.annotation.TargetApi;
import android.os.Build;
import android.test.ActivityInstrumentationTestCase2;
@TargetApi(Build.VERSION_CODES.CUPCAKE)
public class FDroidTest extends ActivityInstrumentationTestCase2<FDroid> {
public FDroidTest() {
super("org.fdroid.fdroid", FDroid.class);
}
}

View File

@ -1,17 +1,32 @@
package org.fdroid.fdroid;
import android.app.Instrumentation;
import android.os.Build;
import android.test.InstrumentationTestCase;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import org.fdroid.fdroid.compat.FileCompatForTest;
import org.fdroid.fdroid.data.SanitizedFile;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.UUID;
@SuppressWarnings("PMD") // TODO port this to JUnit 4 semantics
public class FileCompatTest extends InstrumentationTestCase {
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* This test needs to run on the emulator, even though it technically could
* run as a plain JUnit test, because it is testing the specifics of
* Android's symlink handling.
*/
@RunWith(AndroidJUnit4.class)
public class FileCompatTest {
private static final String TAG = "FileCompatTest";
@ -19,14 +34,17 @@ public class FileCompatTest extends InstrumentationTestCase {
private SanitizedFile sourceFile;
private SanitizedFile destFile;
@Before
public void setUp() {
dir = TestUtils.getWriteableDir(getInstrumentation());
sourceFile = SanitizedFile.knownSanitized(TestUtils.copyAssetToDir(getInstrumentation().getContext(), "simpleIndex.jar", dir));
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
dir = TestUtils.getWriteableDir(instrumentation);
sourceFile = SanitizedFile.knownSanitized(TestUtils.copyAssetToDir(instrumentation.getContext(), "simpleIndex.jar", dir));
destFile = new SanitizedFile(dir, "dest-" + UUID.randomUUID() + ".testproduct");
assertFalse(destFile.exists());
assertTrue(sourceFile.getAbsolutePath() + " should exist.", sourceFile.exists());
}
@After
public void tearDown() {
if (!sourceFile.delete()) {
System.out.println("Can't delete " + sourceFile.getAbsolutePath() + ".");
@ -37,11 +55,13 @@ public class FileCompatTest extends InstrumentationTestCase {
}
}
@Test
public void testSymlinkRuntime() {
FileCompatForTest.symlinkRuntimeTest(sourceFile, destFile);
assertTrue(destFile.getAbsolutePath() + " should exist after symlinking", destFile.exists());
}
@Test
public void testSymlinkLibcore() {
if (Build.VERSION.SDK_INT >= 19) {
@ -52,6 +72,7 @@ public class FileCompatTest extends InstrumentationTestCase {
}
}
@Test
public void testSymlinkOs() {
if (Build.VERSION.SDK_INT >= 21) {

View File

@ -1,16 +1,23 @@
package org.fdroid.fdroid;
import android.app.Instrumentation;
import android.content.Context;
import android.test.InstrumentationTestCase;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.fdroid.fdroid.RepoUpdater.UpdateException;
import org.fdroid.fdroid.data.Repo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.File;
@SuppressWarnings("PMD") // TODO port this to JUnit 4 semantics
public class RepoUpdaterTest extends InstrumentationTestCase {
import static org.junit.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class RepoUpdaterTest {
private static final String TAG = "RepoUpdaterTest";
private Context context;
@ -19,15 +26,17 @@ public class RepoUpdaterTest extends InstrumentationTestCase {
String simpleIndexPubkey = "308201ee30820157a0030201020204300d845b300d06092a864886f70d01010b0500302a3110300e060355040b1307462d44726f6964311630140603550403130d70616c6174736368696e6b656e301e170d3134303432373030303633315a170d3431303931323030303633315a302a3110300e060355040b1307462d44726f6964311630140603550403130d70616c6174736368696e6b656e30819f300d06092a864886f70d010101050003818d0030818902818100a439472e4b6d01141bfc94ecfe131c7c728fdda670bb14c57ca60bd1c38a8b8bc0879d22a0a2d0bc0d6fdd4cb98d1d607c2caefbe250a0bd0322aedeb365caf9b236992fac13e6675d3184a6c7c6f07f73410209e399a9da8d5d7512bbd870508eebacff8b57c3852457419434d34701ccbf692267cbc3f42f1c5d1e23762d790203010001a321301f301d0603551d0e041604140b1840691dab909746fde4bfe28207d1cae15786300d06092a864886f70d01010b05000381810062424c928ffd1b6fd419b44daafef01ca982e09341f7077fb865905087aeac882534b3bd679b51fdfb98892cef38b63131c567ed26c9d5d9163afc775ac98ad88c405d211d6187bde0b0d236381cc574ba06ef9080721a92ae5a103a7301b2c397eecc141cc850dd3e123813ebc41c59d31ddbcb6e984168280c53272f6a442b";
@Override
protected void setUp() {
context = getInstrumentation().getContext();
testFilesDir = TestUtils.getWriteableDir(getInstrumentation());
@Before
public void setUp() {
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
context = instrumentation.getContext();
testFilesDir = TestUtils.getWriteableDir(instrumentation);
Repo repo = new Repo();
repo.pubkey = this.simpleIndexPubkey;
repoUpdater = new RepoUpdater(context, repo);
}
@Test
public void testExtractIndexFromJar() {
if (!testFilesDir.canWrite()) {
return;
@ -43,20 +52,17 @@ public class RepoUpdaterTest extends InstrumentationTestCase {
}
}
public void testExtractIndexFromJarWithoutSignatureJar() {
@Test(expected = UpdateException.class)
public void testExtractIndexFromJarWithoutSignatureJar() throws UpdateException {
if (!testFilesDir.canWrite()) {
return;
}
// this is supposed to fail
try {
File jarFile = TestUtils.copyAssetToDir(context, "simpleIndexWithoutSignature.jar", testFilesDir);
repoUpdater.processDownloadedFile(jarFile);
fail();
} catch (UpdateException e) {
// success!
}
}
@Test
public void testExtractIndexFromJarWithCorruptedManifestJar() {
if (!testFilesDir.canWrite()) {
return;
@ -74,6 +80,7 @@ public class RepoUpdaterTest extends InstrumentationTestCase {
}
}
@Test
public void testExtractIndexFromJarWithCorruptedSignature() {
if (!testFilesDir.canWrite()) {
return;
@ -91,6 +98,7 @@ public class RepoUpdaterTest extends InstrumentationTestCase {
}
}
@Test
public void testExtractIndexFromJarWithCorruptedCertificate() {
if (!testFilesDir.canWrite()) {
return;
@ -108,6 +116,7 @@ public class RepoUpdaterTest extends InstrumentationTestCase {
}
}
@Test
public void testExtractIndexFromJarWithCorruptedEverything() {
if (!testFilesDir.canWrite()) {
return;
@ -125,6 +134,7 @@ public class RepoUpdaterTest extends InstrumentationTestCase {
}
}
@Test
public void testExtractIndexFromMasterKeyIndexJar() {
if (!testFilesDir.canWrite()) {
return;
@ -133,8 +143,10 @@ public class RepoUpdaterTest extends InstrumentationTestCase {
try {
File jarFile = TestUtils.copyAssetToDir(context, "masterKeyIndex.jar", testFilesDir);
repoUpdater.processDownloadedFile(jarFile);
fail();
} catch (UpdateException | SecurityException e) {
fail(); //NOPMD
} catch (UpdateException e) {
// success!
} catch (SecurityException e) {
// success!
}
}

View File

@ -2,7 +2,7 @@
package org.fdroid.fdroid;
import android.support.annotation.NonNull;
import android.test.AndroidTestCase;
import android.support.test.runner.AndroidJUnit4;
import android.text.TextUtils;
import android.util.Log;
@ -10,6 +10,8 @@ import org.fdroid.fdroid.data.Apk;
import org.fdroid.fdroid.data.App;
import org.fdroid.fdroid.data.Repo;
import org.fdroid.fdroid.mock.MockRepo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
@ -24,20 +26,18 @@ import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
@SuppressWarnings("PMD") // TODO port this to JUnit 4 semantics
public class RepoXMLHandlerTest extends AndroidTestCase {
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
@RunWith(AndroidJUnit4.class)
public class RepoXMLHandlerTest {
private static final String TAG = "RepoXMLHandlerTest";
private static final String FAKE_PUBKEY = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345";
public RepoXMLHandlerTest() {
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Test
public void testSimpleIndex() {
Repo expectedRepo = new Repo();
expectedRepo.name = "F-Droid";
@ -47,6 +47,7 @@ public class RepoXMLHandlerTest extends AndroidTestCase {
handlerTestSuite(expectedRepo, actualDetails, 0, 0, -1, 12);
}
@Test
public void testSmallRepo() {
Repo expectedRepo = new Repo();
expectedRepo.name = "Android-Nexus-7-20139453 on UNSET";
@ -70,6 +71,7 @@ public class RepoXMLHandlerTest extends AndroidTestCase {
});
}
@Test
public void testMediumRepo() {
Repo expectedRepo = new Repo();
expectedRepo.name = "Guardian Project Official Releases";
@ -96,6 +98,7 @@ public class RepoXMLHandlerTest extends AndroidTestCase {
});
}
@Test
public void testLargeRepo() {
Repo expectedRepo = new Repo();
expectedRepo.name = "F-Droid";

View File

@ -1,10 +1,19 @@
package org.fdroid.fdroid;
import android.test.AndroidTestCase;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
@SuppressWarnings("PMD") // TODO port this to JUnit 4 semantics
public class UtilsTest extends AndroidTestCase {
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
public class UtilsTest {
String fdroidFingerprint = "43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB";
String fdroidPubkey = "3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef";
@ -34,57 +43,60 @@ public class UtilsTest extends AndroidTestCase {
String fingerprintLongByOneFingerprint = "59050C8155DCA377F23D5A15B77D37134000CDBD8B42FBFBE0E3F38096E68CECE";
String fingerprintLongByOnePubkey = "308203c5308202ada00302010202047b7cf549300d06092a864886f70d01010b0500308192310b30090603550406130255533111300f060355040813084e657720596f726b3111300f060355040713084e657720596f726b311d301b060355040a131454686520477561726469616e2050726f6a656374311f301d060355040b1316477561726469616e20462d44726f6964204275696c64311d301b06035504031314677561726469616e70726f6a6563742e696e666f301e170d3132313032393130323530305a170d3430303331363130323530305a308192310b30090603550406130255533111300f060355040813084e657720596f726b3111300f060355040713084e657720596f726b311d301b060355040a131454686520477561726469616e2050726f6a656374311f301d060355040b1316477561726469616e20462d44726f6964204275696c64311d301b06035504031314677561726469616e70726f6a6563742e696e666f30820122300d06092a864886f70d01010105000382010f003082010a0282010100b7f1f635fa3fce1a8042aaa960c2dc557e4ad2c082e5787488cba587fd26207cf59507919fc4dcebda5c8c0959d14146d0445593aa6c29dc639570b71712451fd5c231b0c9f5f0bec380503a1c2a3bc00048bc5db682915afa54d1ecf67b45e1e05c0934b3037a33d3a565899131f27a72c03a5de93df17a2376cc3107f03ee9d124c474dfab30d4053e8f39f292e2dcb6cc131bce12a0c5fc307985195d256bf1d7a2703d67c14bf18ed6b772bb847370b20335810e337c064fef7e2795a524c664a853cd46accb8494f865164dabfb698fa8318236432758bc40d52db00d5ce07fe2210dc06cd95298b4f09e6c9b7b7af61c1d62ea43ea36a2331e7b2d4e250203010001a321301f301d0603551d0e0416041404d763e981cf3a295b94a790d8536a783097232b300d06092a864886f70d01010b05000382010100654e6484ff032c54fed1d96d3c8e731302be9dbd7bb4fe635f2dac05b69f3ecbb5acb7c9fe405e2a066567a8f5c2beb8b199b5a4d5bb1b435cf02df026d4fb4edd9d8849078f085b00950083052d57467d65c6eebd98f037cff9b148d621cf8819c4f7dc1459bf8fc5c7d76f901495a7caf35d1e5c106e1d50610c4920c3c1b50adcfbd4ad83ce7353cdea7d856bba0419c224f89a2f3ebc203d20eb6247711ad2b55fd4737936dc42ced7a047cbbd24012079204a2883b6d55d5d5b66d9fd82fb51fca9a5db5fad9af8564cb380ff30ae8263dbbf01b46e01313f53279673daa3f893380285646b244359203e7eecde94ae141b7dfa8e6499bb8e7e0b25ab85";
@Test
public void testFormatFingerprint() {
String badResult = Utils.formatFingerprint(getContext(), "");
Context context = InstrumentationRegistry.getTargetContext();
String badResult = Utils.formatFingerprint(context, "");
// real fingerprints
String formatted;
formatted = Utils.formatFingerprint(getContext(), fdroidFingerprint);
formatted = Utils.formatFingerprint(context, fdroidFingerprint);
assertFalse(formatted.equals(badResult));
assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+"));
formatted = Utils.formatFingerprint(getContext(), gpRepoFingerprint);
formatted = Utils.formatFingerprint(context, gpRepoFingerprint);
assertFalse(formatted.equals(badResult));
assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+"));
formatted = Utils.formatFingerprint(getContext(), gpTest1Fingerprint);
formatted = Utils.formatFingerprint(context, gpTest1Fingerprint);
assertFalse(formatted.equals(badResult));
assertTrue(formatted.matches("[A-Z0-9][A-Z0-9] [A-Z0-9 ]+"));
// random garbage
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "234k2lk3jljwlk4j2lk3jlkmqwekljrlkj34lk2jlk2j34lkjl2k3j4lk2j34lja"));
Utils.formatFingerprint(context, "234k2lk3jljwlk4j2lk3jlkmqwekljrlkj34lk2jlk2j34lkjl2k3j4lk2j34lja"));
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "g000000000000000000000000000000000000000000000000000000000000000"));
Utils.formatFingerprint(context, "g000000000000000000000000000000000000000000000000000000000000000"));
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "98273498723948728934789237489273p1928731982731982739182739817238"));
Utils.formatFingerprint(context, "98273498723948728934789237489273p1928731982731982739182739817238"));
// too short
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C5"));
Utils.formatFingerprint(context, "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C5"));
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "C63AED1"));
Utils.formatFingerprint(context, "C63AED1"));
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "f"));
Utils.formatFingerprint(context, "f"));
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), ""));
Utils.formatFingerprint(context, ""));
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), null));
Utils.formatFingerprint(context, null));
// real digits but too long
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB"));
Utils.formatFingerprint(context, "43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB43238D512C1E5EB2D6569F4A3AFBF5523418B82E0A3ED1552770ABB9A9C9CCAB"));
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C50F"));
Utils.formatFingerprint(context, "C63AED1AC79D37C7B0474472AC6EFA6C3AB2B11A767A4F42CF360FA5496E3C50F"));
assertEquals(
badResult,
Utils.formatFingerprint(getContext(), "3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef"));
Utils.formatFingerprint(context, "3082035e30820246a00302010202044c49cd00300d06092a864886f70d01010505003071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b73301e170d3130303732333137313032345a170d3337313230383137313032345a3071310b300906035504061302554b3110300e06035504081307556e6b6e6f776e3111300f0603550407130857657468657262793110300e060355040a1307556e6b6e6f776e3110300e060355040b1307556e6b6e6f776e311930170603550403131043696172616e2047756c746e69656b7330820122300d06092a864886f70d01010105000382010f003082010a028201010096d075e47c014e7822c89fd67f795d23203e2a8843f53ba4e6b1bf5f2fd0e225938267cfcae7fbf4fe596346afbaf4070fdb91f66fbcdf2348a3d92430502824f80517b156fab00809bdc8e631bfa9afd42d9045ab5fd6d28d9e140afc1300917b19b7c6c4df4a494cf1f7cb4a63c80d734265d735af9e4f09455f427aa65a53563f87b336ca2c19d244fcbba617ba0b19e56ed34afe0b253ab91e2fdb1271f1b9e3c3232027ed8862a112f0706e234cf236914b939bcf959821ecb2a6c18057e070de3428046d94b175e1d89bd795e535499a091f5bc65a79d539a8d43891ec504058acb28c08393b5718b57600a211e803f4a634e5c57f25b9b8c4422c6fd90203010001300d06092a864886f70d0101050500038201010008e4ef699e9807677ff56753da73efb2390d5ae2c17e4db691d5df7a7b60fc071ae509c5414be7d5da74df2811e83d3668c4a0b1abc84b9fa7d96b4cdf30bba68517ad2a93e233b042972ac0553a4801c9ebe07bf57ebe9a3b3d6d663965260e50f3b8f46db0531761e60340a2bddc3426098397fda54044a17e5244549f9869b460ca5e6e216b6f6a2db0580b480ca2afe6ec6b46eedacfa4aa45038809ece0c5978653d6c85f678e7f5a2156d1bedd8117751e64a4b0dcd140f3040b021821a8d93aed8d01ba36db6c82372211fed714d9a32607038cdfd565bd529ffc637212aaa2c224ef22b603eccefb5bf1e085c191d4b24fe742b17ab3f55d4e6f05ef"));
}
@Test
public void testCalcFingerprintString() {
// these should pass
assertEquals(fdroidFingerprint, Utils.calcFingerprint(fdroidPubkey));
@ -124,7 +136,5 @@ public class UtilsTest extends AndroidTestCase {
}
}
public void testCalcFingerprintCertificate() {
// TODO write tests that work with a Certificate
}
}

View File

@ -247,7 +247,7 @@ public class AppDetails extends AppCompatActivity implements ProgressListener, A
if (!Preferences.get().expertMode()) {
holder.api.setVisibility(View.GONE);
} else if (apk.minSdkVersion > 0 && apk.maxSdkVersion > 0) {
} else if (apk.minSdkVersion > 0 && apk.maxSdkVersion < Apk.SDK_VERSION_MAX_VALUE) {
holder.api.setText(getString(R.string.minsdk_up_to_maxsdk,
Utils.getAndroidVersionName(apk.minSdkVersion),
Utils.getAndroidVersionName(apk.maxSdkVersion)));

View File

@ -49,6 +49,7 @@ import org.acra.ReportingInteractionMode;
import org.acra.annotation.ReportsCrashes;
import org.apache.commons.net.util.SubnetUtils;
import org.fdroid.fdroid.Preferences.ChangeListener;
import org.fdroid.fdroid.Preferences.Theme;
import org.fdroid.fdroid.compat.PRNGFixes;
import org.fdroid.fdroid.data.AppProvider;
import org.fdroid.fdroid.data.InstalledAppCacheUpdater;
@ -96,19 +97,10 @@ public class FDroidApp extends Application {
enableSpongyCastle();
}
public enum Theme {
light,
dark,
night,
lightWithDarkActionBar, // Obsolete
}
private static Theme curTheme = Theme.light;
public void reloadTheme() {
curTheme = Theme.valueOf(PreferenceManager
.getDefaultSharedPreferences(getBaseContext())
.getString(Preferences.PREF_THEME, Preferences.DEFAULT_THEME));
curTheme = Preferences.get().getTheme();
}
public void applyTheme(Activity activity) {
@ -194,6 +186,7 @@ public class FDroidApp extends Application {
// Perhaps the constructor is a better place, but then again,
// it is more deterministic as to when this gets called...
Preferences.setup(this);
curTheme = Preferences.get().getTheme();
// Apply the Google PRNG fixes to properly seed SecureRandom
PRNGFixes.apply();
@ -241,9 +234,6 @@ public class FDroidApp extends Application {
// been installed, but this causes problems for proprietary gapps
// users since the introduction of verification (on pre-4.2 Android),
// because the install intent says it's finished when it hasn't.
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
curTheme = Theme.valueOf(prefs.getString(Preferences.PREF_THEME, Preferences.DEFAULT_THEME));
Utils.deleteFiles(Utils.getApkDownloadDir(this), null, ".apk");
if (!Preferences.get().shouldCacheApks()) {
Utils.deleteFiles(Utils.getApkCacheDir(this), null, ".apk");

View File

@ -85,6 +85,13 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
private static final boolean DEFAULT_FIRST_TIME = true;
private static final boolean DEFAULT_POST_PRIVILEGED_INSTALL = false;
public enum Theme {
light,
dark,
night,
lightWithDarkActionBar, // Obsolete
}
private boolean filterAppsRequiringRoot = DEFAULT_ROOTED;
private final Map<String, Boolean> initialized = new HashMap<>();
@ -155,6 +162,10 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
return preferences.getBoolean(PREF_EXPERT, DEFAULT_EXPERT);
}
public Theme getTheme() {
return Theme.valueOf(preferences.getString(Preferences.PREF_THEME, Preferences.DEFAULT_THEME));
}
public boolean isLocalRepoHttpsEnabled() {
return false; // disabled until it works well
}

View File

@ -31,6 +31,7 @@ import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Process;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
@ -338,6 +339,7 @@ public class UpdateService extends IntentService implements ProgressListener {
@Override
protected void onHandleIntent(Intent intent) {
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
final long startTime = System.currentTimeMillis();
String address = intent.getStringExtra(EXTRA_ADDRESS);

View File

@ -11,6 +11,9 @@ import java.util.Date;
public class Apk extends ValueObject implements Comparable<Apk> {
// Using only byte-range keeps it only 8-bits in the SQLite database
public static final int SDK_VERSION_MAX_VALUE = Byte.MAX_VALUE;
public String packageName;
public String version;
public int vercode;
@ -19,7 +22,7 @@ public class Apk extends ValueObject implements Comparable<Apk> {
public String hash;
public String hashType;
public int minSdkVersion; // 0 if unknown
public int maxSdkVersion = Byte.MAX_VALUE; // "infinity" if not set
public int maxSdkVersion = SDK_VERSION_MAX_VALUE; // "infinity" if not set
public Date added;
public Utils.CommaSeparatedList permissions; // null if empty or
// unknown

View File

@ -1,7 +1,5 @@
package org.fdroid.fdroid.net;
import android.util.Log;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import org.fdroid.fdroid.FDroidApp;
@ -18,7 +16,6 @@ import java.net.MalformedURLException;
import java.net.URL;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLHandshakeException;
import info.guardianproject.netcipher.NetCipher;
@ -72,25 +69,18 @@ public class HttpDownloader extends Downloader {
return new BufferedInputStream(connection.getInputStream());
}
// Get a remote file. Returns the HTTP response code.
// If 'etag' is not null, it's passed to the server as an If-None-Match
// header, in which case expect a 304 response if nothing changed.
// In the event of a 200 response ONLY, 'retag' (which should be passed
// empty) may contain an etag value for the response, or it may be left
// empty if none was available.
/**
* Get a remote file, checking the HTTP response code. If 'etag' is not
* {@code null}, it's passed to the server as an If-None-Match header, in
* which case expect a 304 response if nothing changed. In the event of a
* 200 response ONLY, 'retag' (which should be passed empty) may contain
* an etag value for the response, or it may be left empty if none was
* available.
*/
@Override
public void download() throws IOException, InterruptedException {
try {
setupConnection();
doDownload();
} catch (SSLHandshakeException e) {
// TODO this should be handled better, it is not internationalised here
throw new IOException(
"A problem occurred while establishing an SSL " +
"connection. If this problem persists, AND you have a " +
"very old device, you could try using http instead of " +
"https for the repo URL." + Log.getStackTraceString(e));
}
}
private boolean isSwapUrl() {

View File

@ -32,11 +32,11 @@ public class HttpDownloaderTest {
for (String urlString : urls) {
URL url = new URL(urlString);
File destFile = File.createTempFile("dl-", "");
destFile.deleteOnExit(); // this probably does nothing, but maybe...
HttpDownloader httpDownloader = new HttpDownloader(url, destFile);
httpDownloader.download();
assertTrue(destFile.exists());
assertTrue(destFile.canRead());
destFile.deleteOnExit();
}
}
@ -46,7 +46,6 @@ public class HttpDownloaderTest {
receivedProgress = false;
URL url = new URL(urlString);
File destFile = File.createTempFile("dl-", "");
destFile.deleteOnExit(); // this probably does nothing, but maybe...
HttpDownloader httpDownloader = new HttpDownloader(url, destFile);
httpDownloader.setListener(new Downloader.DownloaderProgressListener() {
@Override
@ -58,6 +57,7 @@ public class HttpDownloaderTest {
assertTrue(destFile.exists());
assertTrue(destFile.canRead());
assertTrue(receivedProgress);
destFile.deleteOnExit();
}
}
@ -65,39 +65,38 @@ public class HttpDownloaderTest {
public void downloadHttpBasicAuth() throws IOException, InterruptedException {
URL url = new URL("https://httpbin.org/basic-auth/myusername/supersecretpassword");
File destFile = File.createTempFile("dl-", "");
destFile.deleteOnExit(); // this probably does nothing, but maybe...
HttpDownloader httpDownloader = new HttpDownloader(url, destFile, "myusername", "supersecretpassword");
httpDownloader.download();
assertTrue(destFile.exists());
assertTrue(destFile.canRead());
destFile.deleteOnExit();
}
@Test(expected = IOException.class)
public void downloadHttpBasicAuthWrongPassword() throws IOException, InterruptedException {
URL url = new URL("https://httpbin.org/basic-auth/myusername/supersecretpassword");
File destFile = File.createTempFile("dl-", "");
destFile.deleteOnExit(); // this probably does nothing, but maybe...
HttpDownloader httpDownloader = new HttpDownloader(url, destFile, "myusername", "wrongpassword");
httpDownloader.download();
assertFalse(destFile.exists());
destFile.deleteOnExit();
}
@Test(expected = IOException.class)
public void downloadHttpBasicAuthWrongUsername() throws IOException, InterruptedException {
URL url = new URL("https://httpbin.org/basic-auth/myusername/supersecretpassword");
File destFile = File.createTempFile("dl-", "");
destFile.deleteOnExit(); // this probably does nothing, but maybe...
HttpDownloader httpDownloader = new HttpDownloader(url, destFile, "wrongusername", "supersecretpassword");
httpDownloader.download();
assertFalse(destFile.exists());
destFile.deleteOnExit();
}
@Test
public void downloadThenCancel() throws IOException, InterruptedException {
final CountDownLatch latch = new CountDownLatch(5);
final CountDownLatch latch = new CountDownLatch(2);
URL url = new URL("https://f-droid.org/repo/index.jar");
File destFile = File.createTempFile("dl-", "");
destFile.deleteOnExit(); // this probably does nothing, but maybe...
final HttpDownloader httpDownloader = new HttpDownloader(url, destFile);
httpDownloader.setListener(new Downloader.DownloaderProgressListener() {
@Override
@ -121,8 +120,9 @@ public class HttpDownloaderTest {
}
}
}.start();
latch.await(100, TimeUnit.SECONDS); // either 5 progress reports or 100 seconds
latch.await(100, TimeUnit.SECONDS); // either 2 progress reports or 100 seconds
httpDownloader.cancelDownload();
assertTrue(receivedProgress);
destFile.deleteOnExit();
}
}