diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 1ef52cd82..d7766f7b0 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -31,19 +31,15 @@ import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.util.FilePickerActivityHelper; import org.schabi.newpipe.util.ZipHelper; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.Map; import java.util.zip.ZipFile; -import java.util.zip.ZipOutputStream; import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; @@ -51,6 +47,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment { private static final int REQUEST_IMPORT_PATH = 8945; private static final int REQUEST_EXPORT_PATH = 30945; + private ContentSettingsManager manager; + private File databasesDir; private File newpipeDb; private File newpipeDbJournal; @@ -131,6 +129,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment { newpipeSettings = new File(homeDir, "/databases/newpipe.settings"); newpipeSettings.delete(); + manager = new ContentSettingsManager(homeDir); + addPreferencesFromResource(R.xml.content_settings); final Preference importDataPreference = findPreference(getString(R.string.import_data)); @@ -212,33 +212,16 @@ public class ContentSettingsFragment extends BasePreferenceFragment { //checkpoint before export NewPipeDatabase.checkpoint(); - try (ZipOutputStream outZip = new ZipOutputStream(new BufferedOutputStream( - new FileOutputStream(path)))) { - ZipHelper.addFileToZip(outZip, newpipeDb.getPath(), "newpipe.db"); + final SharedPreferences preferences = PreferenceManager + .getDefaultSharedPreferences(requireContext()); + manager.exportDatabase(preferences, path); - saveSharedPreferencesToFile(newpipeSettings); - ZipHelper.addFileToZip(outZip, newpipeSettings.getPath(), - "newpipe.settings"); - } - - Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT) - .show(); + Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT).show(); } catch (final Exception e) { onError(e); } } - private void saveSharedPreferencesToFile(final File dst) { - try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream(dst))) { - final SharedPreferences pref - = PreferenceManager.getDefaultSharedPreferences(requireContext()); - output.writeObject(pref.getAll()); - output.flush(); - } catch (final IOException e) { - e.printStackTrace(); - } - } - private void importDatabase(final String filePath) { // check if file is supported try (ZipFile zipFile = new ZipFile(filePath)) { diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt new file mode 100644 index 000000000..b0ea89993 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsManager.kt @@ -0,0 +1,45 @@ +package org.schabi.newpipe.settings + +import android.content.SharedPreferences +import org.schabi.newpipe.util.ZipHelper +import java.io.BufferedOutputStream +import java.io.File +import java.io.FileOutputStream +import java.io.IOException +import java.io.ObjectOutputStream +import java.lang.Exception +import java.util.zip.ZipOutputStream + +class ContentSettingsManager( + private val newpipeDb: File, + private val newpipeSettings: File +) { + + constructor(homeDir: String) : this( + File("$homeDir/databases/newpipe.db"), + File("$homeDir/databases/newpipe.settings") + ) + + /** + * Exports given [SharedPreferences] to the file in given outputPath. + * It also creates the file. + */ + @Throws(Exception::class) + fun exportDatabase(preferences: SharedPreferences, outputPath: String) { + ZipOutputStream(BufferedOutputStream(FileOutputStream(outputPath))) + .use { outZip -> + ZipHelper.addFileToZip(outZip, newpipeDb.path, "newpipe.db") + + try { + ObjectOutputStream(FileOutputStream(newpipeSettings)).use { output -> + output.writeObject(preferences.all) + output.flush() + } + } catch (e: IOException) { + e.printStackTrace() + } + + ZipHelper.addFileToZip(outZip, newpipeSettings.path, "newpipe.settings") + } + } +} diff --git a/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt b/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt new file mode 100644 index 000000000..9809fd5fc --- /dev/null +++ b/app/src/test/java/org/schabi/newpipe/settings/ContentSettingsManagerTest.kt @@ -0,0 +1,72 @@ +package org.schabi.newpipe.settings + +import android.content.SharedPreferences +import org.junit.Assert +import org.junit.Assume +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Suite +import org.mockito.Mockito +import org.mockito.Mockito.`when` +import org.mockito.junit.MockitoJUnitRunner +import org.schabi.newpipe.settings.ContentSettingsManagerTest.ExportTest +import java.io.File +import java.io.ObjectInputStream +import java.util.zip.ZipFile + +@RunWith(Suite::class) +@Suite.SuiteClasses(ExportTest::class) +class ContentSettingsManagerTest { + + @RunWith(MockitoJUnitRunner::class) + class ExportTest { + + private lateinit var preferences: SharedPreferences + private lateinit var newpipeDb: File + private lateinit var newpipeSettings: File + + @Before + fun beforeClass() { + + val dbPath = javaClass.classLoader?.getResource("settings/newpipe.db")?.file + val settingsPath = javaClass.classLoader?.getResource("settings/newpipe.settings")?.path + Assume.assumeNotNull(dbPath) + Assume.assumeNotNull(settingsPath) + + newpipeDb = File(dbPath!!) + newpipeSettings = File(settingsPath!!) + } + + @Before + fun before() { + preferences = Mockito.mock(SharedPreferences::class.java, Mockito.withSettings().stubOnly()) + } + + @Test + fun `The settings must be exported successfully in the correct format`() { + val expectedPreferences = mapOf("such pref" to "much wow") + `when`(preferences.all).thenReturn(expectedPreferences) + + val manager = ContentSettingsManager(newpipeDb, newpipeSettings) + + val output = File.createTempFile("newpipe_", "") + manager.exportDatabase(preferences, output.absolutePath) + + val zipFile = ZipFile(output.absoluteFile) + val entries = zipFile.entries().toList() + Assert.assertEquals(2, entries.size) + + zipFile.getInputStream(entries.first { it.name == "newpipe.db" }).use { actual -> + newpipeDb.inputStream().use { expected -> + Assert.assertEquals(expected.reader().readText(), actual.reader().readText()) + } + } + + zipFile.getInputStream(entries.first { it.name == "newpipe.settings" }).use { actual -> + val actualPreferences = ObjectInputStream(actual).readObject() + Assert.assertEquals(expectedPreferences, actualPreferences) + } + } + } +} diff --git a/app/src/test/resources/settings/newpipe.db b/app/src/test/resources/settings/newpipe.db new file mode 100644 index 000000000..cd3fc4717 --- /dev/null +++ b/app/src/test/resources/settings/newpipe.db @@ -0,0 +1 @@ +such db much wow \ No newline at end of file diff --git a/app/src/test/resources/settings/newpipe.settings b/app/src/test/resources/settings/newpipe.settings new file mode 100644 index 000000000..e69de29bb diff --git a/checkstyle-suppressions.xml b/checkstyle-suppressions.xml index add17d42d..0a5190b29 100644 --- a/checkstyle-suppressions.xml +++ b/checkstyle-suppressions.xml @@ -17,7 +17,7 @@ + lines="227,245"/>