diff --git a/app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java b/app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java index a8de65bb9..e14344b2c 100644 --- a/app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java +++ b/app/src/main/java/org/fdroid/fdroid/IndexV1Updater.java @@ -6,7 +6,6 @@ import android.net.Uri; import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; - import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.core.JsonFactory; @@ -15,7 +14,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.InjectableValues; import com.fasterxml.jackson.databind.ObjectMapper; - import org.apache.commons.io.FileUtils; import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.App; @@ -138,14 +136,21 @@ public class IndexV1Updater extends RepoUpdater { /** * Parses the index and feeds it to the database via {@link Repo}, {@link App}, - * and {@link Apk} instances. + * and {@link Apk} instances. This uses {@link RepoPersister} to add the apps + * and packages to the database in {@link RepoPersister#saveToDb(App, List)} + * to write the {@link Repo}, and commit the whole thing in + * {@link RepoPersister#commit(ContentValues)}. One confusing thing about this + * whole process is that {@link RepoPersister} needs to first create and entry + * in the database, then fetch the ID from the database to populate + * {@link Repo#id}. That has to happen first, then the rest of the {@code Repo} + * data must be added later. * * @param indexInputStream {@link InputStream} to {@code index-v1.json} - * @param cacheTag the {@code etag} value from HTTP headers + * @param etag the {@code etag} value from HTTP headers * @throws IOException * @throws UpdateException */ - public void processIndexV1(InputStream indexInputStream, JarEntry indexEntry, String cacheTag) + public void processIndexV1(InputStream indexInputStream, JarEntry indexEntry, String etag) throws IOException, UpdateException { Utils.Profiler profiler = new Utils.Profiler(TAG); profiler.log("Starting to process index-v1.json"); @@ -200,6 +205,7 @@ public class IndexV1Updater extends RepoUpdater { // timestamp is absolutely required repo.timestamp = timestamp; // below are optional, can be null + repo.lastetag = etag; repo.name = getStringRepoValue(repoMap, "name"); repo.icon = getStringRepoValue(repoMap, "icon"); repo.description = getStringRepoValue(repoMap, "description"); @@ -234,15 +240,32 @@ public class IndexV1Updater extends RepoUpdater { repoPersister.saveToDb(app, apks); } } - profiler.log("Saved to database, but only a temporary table. Now persisting to database..."); - notifyCommittingToDb(); - ContentValues values = prepareRepoDetailsForSaving(repo.name, - repo.description, repo.maxage, repo.version, repo.timestamp, repo.icon, - repo.mirrors, cacheTag); - repoPersister.commit(values); + ContentValues contentValues = new ContentValues(); + contentValues.put(Schema.RepoTable.Cols.LAST_UPDATED, Utils.formatTime(new Date(), "")); + contentValues.put(Schema.RepoTable.Cols.TIMESTAMP, repo.timestamp); + contentValues.put(Schema.RepoTable.Cols.LAST_ETAG, repo.lastetag); + if (repo.version != Repo.INT_UNSET_VALUE) { + contentValues.put(Schema.RepoTable.Cols.VERSION, repo.version); + } + if (repo.maxage != Repo.INT_UNSET_VALUE) { + contentValues.put(Schema.RepoTable.Cols.MAX_AGE, repo.maxage); + } + if (repo.description != null) { + contentValues.put(Schema.RepoTable.Cols.DESCRIPTION, repo.description); + } + if (repo.name != null) { + contentValues.put(Schema.RepoTable.Cols.NAME, repo.name); + } + if (repo.icon != null) { + contentValues.put(Schema.RepoTable.Cols.ICON, repo.icon); + } + if (repo.mirrors != null && repo.mirrors.length > 0) { + contentValues.put(Schema.RepoTable.Cols.MIRRORS, Utils.serializeCommaSeparatedString(repo.mirrors)); + } + repoPersister.commit(contentValues); profiler.log("Persited to database."); @@ -266,10 +289,12 @@ public class IndexV1Updater extends RepoUpdater { return null; } + @SuppressWarnings("unchecked") private String[] getStringArrayRepoValue(Map repoMap, String key) { Object value = repoMap.get(key); - if (value != null && value instanceof String[]) { - return (String[]) value; + if (value != null && value instanceof ArrayList) { + ArrayList list = (ArrayList) value; + return list.toArray(new String[list.size()]); } return null; } diff --git a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java index b63424f70..f77548e33 100644 --- a/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java +++ b/app/src/main/java/org/fdroid/fdroid/RepoUpdater.java @@ -30,7 +30,6 @@ import android.content.pm.PackageManager; import android.support.annotation.NonNull; import android.text.TextUtils; import android.util.Log; - import org.fdroid.fdroid.data.Apk; import org.fdroid.fdroid.data.ApkProvider; import org.fdroid.fdroid.data.App; @@ -48,6 +47,9 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -62,10 +64,6 @@ import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - // TODO move to org.fdroid.fdroid.updater // TODO reduce visibility of methods once in .updater package (.e.g tests need it public now) @@ -297,11 +295,12 @@ public class RepoUpdater { /** * Update tracking data for the repo represented by this instance (index version, etag, - * description, human-readable name, etc. + * description, human-readable name, etc. This is not reused in {@link IndexV1Updater} + * because its too tied up into the old parsing flow in this class. */ - ContentValues prepareRepoDetailsForSaving(String name, String description, int maxAge, - int version, long timestamp, String icon, - String[] mirrors, String cacheTag) { + private ContentValues prepareRepoDetailsForSaving(String name, String description, int maxAge, + int version, long timestamp, String icon, + String[] mirrors, String cacheTag) { ContentValues values = new ContentValues(); values.put(RepoTable.Cols.LAST_UPDATED, Utils.formatTime(new Date(), "")); diff --git a/app/src/main/java/org/fdroid/fdroid/data/RepoProvider.java b/app/src/main/java/org/fdroid/fdroid/data/RepoProvider.java index 6bcc7311a..849bee1b1 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/RepoProvider.java +++ b/app/src/main/java/org/fdroid/fdroid/data/RepoProvider.java @@ -151,6 +151,13 @@ public class RepoProvider extends FDroidProvider { return repo; } + /** + * Updates the repo metadata in the database. All data comes from the + * index file except {@link Repo#id}, which is generated by the database. + * That makes for an two cycle workflow, where first this must be called + * to fetch the {@code Repo.id} from the database, then it is called a + * second time to actually set the repo metadata. + */ public static void update(Context context, Repo repo, ContentValues values) { ContentResolver resolver = context.getContentResolver(); diff --git a/app/src/test/java/org/fdroid/fdroid/updater/FDroidRepoUpdateTest.java b/app/src/test/java/org/fdroid/fdroid/updater/FDroidRepoUpdateTest.java index f72b9a8b5..9cca0faaf 100644 --- a/app/src/test/java/org/fdroid/fdroid/updater/FDroidRepoUpdateTest.java +++ b/app/src/test/java/org/fdroid/fdroid/updater/FDroidRepoUpdateTest.java @@ -29,18 +29,24 @@ public class FDroidRepoUpdateTest extends MultiRepoUpdaterTest { assertEmpty(); updateEarlier(); updateLater(); + updateV1Later(); } protected void updateEarlier() throws RepoUpdater.UpdateException { Utils.debugLog(TAG, "Updating earlier version of F-Droid repo"); - updateRepo(createUpdater(REPO_FDROID, REPO_FDROID_URI, context, REPO_FDROID_PUB_KEY), + updateRepo(createRepoUpdater(REPO_FDROID, REPO_FDROID_URI, context, REPO_FDROID_PUB_KEY), "index.fdroid.2016-10-30.jar"); } protected void updateLater() throws RepoUpdater.UpdateException { Utils.debugLog(TAG, "Updating later version of F-Droid repo"); - updateRepo(createUpdater(REPO_FDROID, REPO_FDROID_URI, context, REPO_FDROID_PUB_KEY), + updateRepo(createRepoUpdater(REPO_FDROID, REPO_FDROID_URI, context, REPO_FDROID_PUB_KEY), "index.fdroid.2016-11-10.jar"); } + protected void updateV1Later() throws RepoUpdater.UpdateException { + Utils.debugLog(TAG, "Updating later version of F-Droid index-v1"); + updateRepo(createIndexV1Updater(REPO_FDROID, REPO_FDROID_URI, context, REPO_FDROID_PUB_KEY), + "index-v1.fdroid.2017-07-07.jar"); + } } diff --git a/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java b/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java index 10675b127..41df377df 100644 --- a/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java +++ b/app/src/test/java/org/fdroid/fdroid/updater/IndexV1UpdaterTest.java @@ -17,9 +17,12 @@ import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.RepoUpdater; import org.fdroid.fdroid.TestUtils; import org.fdroid.fdroid.data.Apk; +import org.fdroid.fdroid.data.ApkProvider; import org.fdroid.fdroid.data.App; +import org.fdroid.fdroid.data.AppProvider; import org.fdroid.fdroid.data.FDroidProviderTest; import org.fdroid.fdroid.data.Repo; +import org.fdroid.fdroid.data.RepoProvider; import org.fdroid.fdroid.data.RepoPushRequest; import org.fdroid.fdroid.mock.RepoDetails; import org.junit.After; @@ -48,6 +51,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @Config(constants = BuildConfig.class, sdk = 24) @@ -71,6 +75,12 @@ public class IndexV1UpdaterTest extends FDroidProviderTest { @Test public void testIndexV1Processing() throws IOException, RepoUpdater.UpdateException { + List repos = RepoProvider.Helper.all(context); + for (Repo repo : repos) { + RepoProvider.Helper.remove(context, repo.getId()); + } + assertEquals("No repos present", 0, RepoProvider.Helper.all(context).size()); + assertEquals("No apps present", 0, AppProvider.Helper.all(context.getContentResolver()).size()); Repo repo = MultiRepoUpdaterTest.createRepo("Testy", TESTY_JAR, context, TESTY_CERT); repo.timestamp = 1481222110; IndexV1Updater updater = new IndexV1Updater(context, repo); @@ -80,6 +90,37 @@ public class IndexV1UpdaterTest extends FDroidProviderTest { InputStream indexInputStream = jarFile.getInputStream(indexEntry); updater.processIndexV1(indexInputStream, indexEntry, "fakeEtag"); IOUtils.closeQuietly(indexInputStream); + List apps = AppProvider.Helper.all(context.getContentResolver()); + assertEquals("53 apps present", 53, apps.size()); + + String[] packages = { + "fake.app.one", + "org.adaway", + "This_does_not_exist", + }; + for (String id : packages) { + assertEquals("No apks for " + id, 0, ApkProvider.Helper.findByPackageName(context, id).size()); + } + + for (App app : apps) { + assertTrue("Some apks for " + app.packageName, + ApkProvider.Helper.findByPackageName(context, app.packageName).size() > 0); + } + + repos = RepoProvider.Helper.all(context); + assertEquals("One repo", 1, repos.size()); + Repo repoFromDb = repos.get(0); + assertEquals("repo.timestamp should be set", 1481222111, repoFromDb.timestamp); + assertEquals("repo.address should be the same", repo.address, repoFromDb.address); + assertEquals("repo.name should be set", "non-public test repo", repoFromDb.name); + assertEquals("repo.maxage should be set", 0, repoFromDb.maxage); + assertEquals("repo.version should be set", 18, repoFromDb.version); + assertEquals("repo.icon should be set", "fdroid-icon.png", repoFromDb.icon); + String description = "This is a repository of apps to be used with F-Droid. Applications in this repository are either official binaries built by the original application developers, or are binaries built from source by the admin of f-droid.org using the tools on https://gitlab.com/u/fdroid. "; // NOCHECKSTYLE LineLength + assertEquals("repo.description should be set", description, repoFromDb.description); + assertEquals("repo.mirrors should have items", 2, repo.mirrors.length); + assertEquals("repo.mirrors first URL", "http://frkcchxlcvnb4m5a.onion/fdroid/repo", repo.mirrors[0]); + assertEquals("repo.mirrors second URL", "http://testy.at.or.at/fdroid/repo", repo.mirrors[1]); } @Test(expected = RepoUpdater.SigningException.class) diff --git a/app/src/test/java/org/fdroid/fdroid/updater/MultiRepoUpdaterTest.java b/app/src/test/java/org/fdroid/fdroid/updater/MultiRepoUpdaterTest.java index e457b217a..be5d81fe9 100644 --- a/app/src/test/java/org/fdroid/fdroid/updater/MultiRepoUpdaterTest.java +++ b/app/src/test/java/org/fdroid/fdroid/updater/MultiRepoUpdaterTest.java @@ -5,7 +5,7 @@ import android.content.ContentValues; import android.content.Context; import android.support.annotation.NonNull; import android.text.TextUtils; - +import org.fdroid.fdroid.IndexV1Updater; import org.fdroid.fdroid.Preferences; import org.fdroid.fdroid.RepoUpdater; import org.fdroid.fdroid.RepoUpdater.UpdateException; @@ -21,11 +21,16 @@ import org.junit.After; import org.junit.Before; import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; public abstract class MultiRepoUpdaterTest extends FDroidProviderTest { @SuppressWarnings("unused") @@ -41,36 +46,36 @@ public abstract class MultiRepoUpdaterTest extends FDroidProviderTest { private static final String PUB_KEY = "3082050b308202f3a003020102020420d8f212300d06092a864886f70d01010b050030363110300e0603" + - "55040b1307462d44726f69643122302006035504031319657073696c6f6e2e70657465722e7365727779" + - "6c6f2e636f6d301e170d3135303931323233313632315a170d3433303132383233313632315a30363110" + - "300e060355040b1307462d44726f69643122302006035504031319657073696c6f6e2e70657465722e73" + - "657277796c6f2e636f6d30820222300d06092a864886f70d01010105000382020f003082020a02820201" + - "00b21fe72b84ce721967851364bd20511088d117bc3034e4bb4d3c1a06af2a308fdffdaf63b12e0926b9" + - "0545134b9ff570646cbcad89d9e86dcc8eb9977dd394240c75bccf5e8ddc3c5ef91b4f16eca5f36c36f1" + - "92463ff2c9257d3053b7c9ecdd1661bd01ec3fe70ee34a7e6b92ddba04f258a32d0cfb1b0ce85d047180" + - "97fc4bdfb54541b430dfcfc1c84458f9eb5627e0ec5341d561c3f15f228379a1282d241329198f31a7ac" + - "cd51ab2bbb881a1da55001123483512f77275f8990c872601198065b4e0137ddd1482e4fdefc73b857d4" + - "be324ca96c268ceb725398f8cc38a0dc6aa2c277f8686724e8c7ff3f320a05791fccacc6caa956cf23a9" + - "de2dc7070b262c0e35d90d17e90773bb11e875e79a8dfd958e359d5d5ad903a7cbc2955102502bd0134c" + - "a1ff7a0bbbbb57302e4a251e40724dcaa8ad024f4b3a71b8fceaac664c0dcc1995a1c4cf42676edad8bc" + - "b03ba255ab796677f18fff2298e1aaa5b134254b44d08a4d934c9859af7bbaf078c37b7f628db0e2cffb" + - "0493a669d5f4770d35d71284550ce06d6f6811cd2a31585085716257a4ba08ad968b0a2bf88f34ca2f2c" + - "73af1c042ab147597faccfb6516ef4468cfa0c5ab3c8120eaa7bac1080e4d2310f717db20815d0e1ee26" + - "bd4e47eed8d790892017ae9595365992efa1b7fd1bc1963f018264b2b3749b8f7b1907bb0843f1e7fc2d" + - "3f3b02284cd4bae0ab0203010001a321301f301d0603551d0e0416041456110e4fed863ab1df9448bfd9" + - "e10a8bc32ffe08300d06092a864886f70d01010b050003820201008082572ae930ebc55ecf1110f4bb72" + - "ad2a952c8ac6e65bd933706beb4a310e23deabb8ef6a7e93eea8217ab1f3f57b1f477f95f1d62eccb563" + - "67a4d70dfa6fcd2aace2bb00b90af39412a9441a9fae2396ff8b93de1df3d9837c599b1f80b7d75285cb" + - "df4539d7dd9612f54b45ca59bc3041c9b92fac12753fac154d12f31df360079ab69a2d20db9f6a7277a8" + - "259035e93de95e8cbc80351bc83dd24256183ea5e3e1db2a51ea314cdbc120c064b77e2eb3a731530511" + - "1e1dabed6996eb339b7cb948d05c1a84d63094b4a4c6d11389b2a7b5f2d7ecc9a149dda6c33705ef2249" + - "58afdfa1d98cf646dcf8857cd8342b1e07d62cb4313f35ad209046a4a42ff73f38cc740b1e695eeda49d" + - "5ea0384ad32f9e3ae54f6a48a558dbc7cccabd4e2b2286dc9c804c840bd02b9937841a0e48db00be9e3c" + - "d7120cf0f8648ce4ed63923f0352a2a7b3b97fc55ba67a7a218b8c0b3cda4a45861280a622e0a59cc9fb" + - "ca1117568126c581afa4408b0f5c50293c212c406b8ab8f50aad5ed0f038cfca580ef3aba7df25464d9e" + - "495ffb629922cfb511d45e6294c045041132452f1ed0f20ac3ab4792f610de1734e4c8b71d743c4b0101" + - "98f848e0dbfce5a0f2da0198c47e6935a47fda12c518ef45adfb66ddf5aebaab13948a66c004b8592d22" + - "e8af60597c4ae2977977cf61dc715a572e241ae717cafdb4f71781943945ac52e0f50b"; + "55040b1307462d44726f69643122302006035504031319657073696c6f6e2e70657465722e7365727779" + + "6c6f2e636f6d301e170d3135303931323233313632315a170d3433303132383233313632315a30363110" + + "300e060355040b1307462d44726f69643122302006035504031319657073696c6f6e2e70657465722e73" + + "657277796c6f2e636f6d30820222300d06092a864886f70d01010105000382020f003082020a02820201" + + "00b21fe72b84ce721967851364bd20511088d117bc3034e4bb4d3c1a06af2a308fdffdaf63b12e0926b9" + + "0545134b9ff570646cbcad89d9e86dcc8eb9977dd394240c75bccf5e8ddc3c5ef91b4f16eca5f36c36f1" + + "92463ff2c9257d3053b7c9ecdd1661bd01ec3fe70ee34a7e6b92ddba04f258a32d0cfb1b0ce85d047180" + + "97fc4bdfb54541b430dfcfc1c84458f9eb5627e0ec5341d561c3f15f228379a1282d241329198f31a7ac" + + "cd51ab2bbb881a1da55001123483512f77275f8990c872601198065b4e0137ddd1482e4fdefc73b857d4" + + "be324ca96c268ceb725398f8cc38a0dc6aa2c277f8686724e8c7ff3f320a05791fccacc6caa956cf23a9" + + "de2dc7070b262c0e35d90d17e90773bb11e875e79a8dfd958e359d5d5ad903a7cbc2955102502bd0134c" + + "a1ff7a0bbbbb57302e4a251e40724dcaa8ad024f4b3a71b8fceaac664c0dcc1995a1c4cf42676edad8bc" + + "b03ba255ab796677f18fff2298e1aaa5b134254b44d08a4d934c9859af7bbaf078c37b7f628db0e2cffb" + + "0493a669d5f4770d35d71284550ce06d6f6811cd2a31585085716257a4ba08ad968b0a2bf88f34ca2f2c" + + "73af1c042ab147597faccfb6516ef4468cfa0c5ab3c8120eaa7bac1080e4d2310f717db20815d0e1ee26" + + "bd4e47eed8d790892017ae9595365992efa1b7fd1bc1963f018264b2b3749b8f7b1907bb0843f1e7fc2d" + + "3f3b02284cd4bae0ab0203010001a321301f301d0603551d0e0416041456110e4fed863ab1df9448bfd9" + + "e10a8bc32ffe08300d06092a864886f70d01010b050003820201008082572ae930ebc55ecf1110f4bb72" + + "ad2a952c8ac6e65bd933706beb4a310e23deabb8ef6a7e93eea8217ab1f3f57b1f477f95f1d62eccb563" + + "67a4d70dfa6fcd2aace2bb00b90af39412a9441a9fae2396ff8b93de1df3d9837c599b1f80b7d75285cb" + + "df4539d7dd9612f54b45ca59bc3041c9b92fac12753fac154d12f31df360079ab69a2d20db9f6a7277a8" + + "259035e93de95e8cbc80351bc83dd24256183ea5e3e1db2a51ea314cdbc120c064b77e2eb3a731530511" + + "1e1dabed6996eb339b7cb948d05c1a84d63094b4a4c6d11389b2a7b5f2d7ecc9a149dda6c33705ef2249" + + "58afdfa1d98cf646dcf8857cd8342b1e07d62cb4313f35ad209046a4a42ff73f38cc740b1e695eeda49d" + + "5ea0384ad32f9e3ae54f6a48a558dbc7cccabd4e2b2286dc9c804c840bd02b9937841a0e48db00be9e3c" + + "d7120cf0f8648ce4ed63923f0352a2a7b3b97fc55ba67a7a218b8c0b3cda4a45861280a622e0a59cc9fb" + + "ca1117568126c581afa4408b0f5c50293c212c406b8ab8f50aad5ed0f038cfca580ef3aba7df25464d9e" + + "495ffb629922cfb511d45e6294c045041132452f1ed0f20ac3ab4792f610de1734e4c8b71d743c4b0101" + + "98f848e0dbfce5a0f2da0198c47e6935a47fda12c518ef45adfb66ddf5aebaab13948a66c004b8592d22" + + "e8af60597c4ae2977977cf61dc715a572e241ae717cafdb4f71781943945ac52e0f50b"; @Before public final void setupMultiRepo() throws Exception { @@ -145,9 +150,9 @@ public abstract class MultiRepoUpdaterTest extends FDroidProviderTest { assertEquals("No apps present", 0, AppProvider.Helper.all(context.getContentResolver()).size()); String[] packages = { - "com.uberspot.a2048", - "org.adaway", - "siir.es.adbWireless", + "com.uberspot.a2048", + "org.adaway", + "siir.es.adbWireless", }; for (String id : packages) { @@ -177,30 +182,44 @@ public abstract class MultiRepoUpdaterTest extends FDroidProviderTest { return RepoProvider.Helper.findByAddress(context, repo.address); } - protected RepoUpdater createUpdater(String name, String uri, Context context) { + protected RepoUpdater createRepoUpdater(String name, String uri, Context context) { return new RepoUpdater(context, createRepo(name, uri, context)); } - protected RepoUpdater createUpdater(String name, String uri, Context context, String signingCert) { + protected RepoUpdater createRepoUpdater(String name, String uri, Context context, String signingCert) { return new RepoUpdater(context, createRepo(name, uri, context, signingCert)); } + protected IndexV1Updater createIndexV1Updater(String name, String uri, Context context, String signingCert) { + return new IndexV1Updater(context, createRepo(name, uri, context, signingCert)); + } + protected void updateConflicting() throws UpdateException { - updateRepo(createUpdater(REPO_CONFLICTING, REPO_CONFLICTING_URI, context), "multiRepo.conflicting.jar"); + updateRepo(createRepoUpdater(REPO_CONFLICTING, REPO_CONFLICTING_URI, context), "multiRepo.conflicting.jar"); } protected void updateMain() throws UpdateException { - updateRepo(createUpdater(REPO_MAIN, REPO_MAIN_URI, context), "multiRepo.normal.jar"); + updateRepo(createRepoUpdater(REPO_MAIN, REPO_MAIN_URI, context), "multiRepo.normal.jar"); } protected void updateArchive() throws UpdateException { - updateRepo(createUpdater(REPO_ARCHIVE, REPO_ARCHIVE_URI, context), "multiRepo.archive.jar"); + updateRepo(createRepoUpdater(REPO_ARCHIVE, REPO_ARCHIVE_URI, context), "multiRepo.archive.jar"); } protected void updateRepo(RepoUpdater updater, String indexJarPath) throws UpdateException { File indexJar = TestUtils.copyResourceToTempFile(indexJarPath); try { - updater.processDownloadedFile(indexJar); + if (updater instanceof IndexV1Updater) { + JarFile jarFile = new JarFile(indexJar); + JarEntry indexEntry = (JarEntry) jarFile.getEntry(IndexV1Updater.DATA_FILE_NAME); + InputStream indexInputStream = jarFile.getInputStream(indexEntry); + ((IndexV1Updater) updater).processIndexV1(indexInputStream, indexEntry, null); + } else { + updater.processDownloadedFile(indexJar); + } + } catch (IOException e) { + e.printStackTrace(); + fail(); } finally { if (indexJar != null && indexJar.exists()) { indexJar.delete(); diff --git a/app/src/test/resources/index-v1.fdroid.2017-07-07.jar b/app/src/test/resources/index-v1.fdroid.2017-07-07.jar new file mode 100644 index 000000000..b14dea1f3 Binary files /dev/null and b/app/src/test/resources/index-v1.fdroid.2017-07-07.jar differ