mirror of
				https://github.com/TeamNewPipe/NewPipe
				synced 2025-10-31 07:13:00 +00:00 
			
		
		
		
	Extract export database logic into own class
- Separate it from the UI. - Add happy path unit test.
This commit is contained in:
		| @@ -30,19 +30,15 @@ import org.schabi.newpipe.report.UserAction; | |||||||
| import org.schabi.newpipe.util.FilePickerActivityHelper; | import org.schabi.newpipe.util.FilePickerActivityHelper; | ||||||
| import org.schabi.newpipe.util.ZipHelper; | import org.schabi.newpipe.util.ZipHelper; | ||||||
|  |  | ||||||
| import java.io.BufferedOutputStream; |  | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.FileInputStream; | import java.io.FileInputStream; | ||||||
| import java.io.FileOutputStream; |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.ObjectInputStream; | import java.io.ObjectInputStream; | ||||||
| import java.io.ObjectOutputStream; |  | ||||||
| import java.text.SimpleDateFormat; | import java.text.SimpleDateFormat; | ||||||
| import java.util.Date; | import java.util.Date; | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| import java.util.Map; | import java.util.Map; | ||||||
| import java.util.zip.ZipFile; | import java.util.zip.ZipFile; | ||||||
| import java.util.zip.ZipOutputStream; |  | ||||||
|  |  | ||||||
| import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; | import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage; | ||||||
|  |  | ||||||
| @@ -50,6 +46,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment { | |||||||
|     private static final int REQUEST_IMPORT_PATH = 8945; |     private static final int REQUEST_IMPORT_PATH = 8945; | ||||||
|     private static final int REQUEST_EXPORT_PATH = 30945; |     private static final int REQUEST_EXPORT_PATH = 30945; | ||||||
|  |  | ||||||
|  |     private ContentSettingsManager manager; | ||||||
|  |  | ||||||
|     private File databasesDir; |     private File databasesDir; | ||||||
|     private File newpipeDb; |     private File newpipeDb; | ||||||
|     private File newpipeDbJournal; |     private File newpipeDbJournal; | ||||||
| @@ -131,6 +129,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment { | |||||||
|         newpipeSettings = new File(homeDir + "/databases/newpipe.settings"); |         newpipeSettings = new File(homeDir + "/databases/newpipe.settings"); | ||||||
|         newpipeSettings.delete(); |         newpipeSettings.delete(); | ||||||
|  |  | ||||||
|  |         manager = new ContentSettingsManager(homeDir); | ||||||
|  |  | ||||||
|         addPreferencesFromResource(R.xml.content_settings); |         addPreferencesFromResource(R.xml.content_settings); | ||||||
|  |  | ||||||
|         final Preference importDataPreference = findPreference(getString(R.string.import_data)); |         final Preference importDataPreference = findPreference(getString(R.string.import_data)); | ||||||
| @@ -212,33 +212,16 @@ public class ContentSettingsFragment extends BasePreferenceFragment { | |||||||
|             //checkpoint before export |             //checkpoint before export | ||||||
|             NewPipeDatabase.checkpoint(); |             NewPipeDatabase.checkpoint(); | ||||||
|  |  | ||||||
|             try (ZipOutputStream outZip = new ZipOutputStream(new BufferedOutputStream( |             final SharedPreferences preferences = PreferenceManager | ||||||
|                             new FileOutputStream(path)))) { |                 .getDefaultSharedPreferences(requireContext()); | ||||||
|                 ZipHelper.addFileToZip(outZip, newpipeDb.getPath(), "newpipe.db"); |             manager.exportDatabase(preferences, path); | ||||||
|  |  | ||||||
|                 saveSharedPreferencesToFile(newpipeSettings); |             Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT).show(); | ||||||
|                 ZipHelper.addFileToZip(outZip, newpipeSettings.getPath(), |  | ||||||
|                         "newpipe.settings"); |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT) |  | ||||||
|                     .show(); |  | ||||||
|         } catch (final Exception e) { |         } catch (final Exception e) { | ||||||
|             onError(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) { |     private void importDatabase(final String filePath) { | ||||||
|         // check if file is supported |         // check if file is supported | ||||||
|         try (ZipFile zipFile = new ZipFile(filePath)) { |         try (ZipFile zipFile = new ZipFile(filePath)) { | ||||||
|   | |||||||
| @@ -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") | ||||||
|  |             } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								app/src/test/resources/settings/newpipe.db
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								app/src/test/resources/settings/newpipe.db
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | such db much wow | ||||||
							
								
								
									
										0
									
								
								app/src/test/resources/settings/newpipe.settings
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/src/test/resources/settings/newpipe.settings
									
									
									
									
									
										Normal file
									
								
							| @@ -17,7 +17,7 @@ | |||||||
|  |  | ||||||
|   <suppress checks="EmptyBlock" |   <suppress checks="EmptyBlock" | ||||||
|       files="ContentSettingsFragment.java" |       files="ContentSettingsFragment.java" | ||||||
|       lines="244,245"/> |       lines="227,245"/> | ||||||
|  |  | ||||||
|   <!-- org.schabi.newpipe.streams --> |   <!-- org.schabi.newpipe.streams --> | ||||||
|   <suppress checks="LineLength" |   <suppress checks="LineLength" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 XiangRongLin
					XiangRongLin