SettingsImporter { public boolean fromJSON(@NonNull String json) { if (!settingsValidator.isValid(json)) { return false; } generalSharedPrefs.edit().clear().apply(); adminSharedPrefs.edit().clear().apply(); try { JSONObject jsonObject = new JSONObject(json); JSONObject general = jsonObject.getJSONObject("general"); importToPrefs(general, generalSharedPrefs); JSONObject admin = jsonObject.getJSONObject("admin"); importToPrefs(admin, adminSharedPrefs); } catch (JSONException ignored) { } preferenceMigrator.migrate(generalSharedPrefs, adminSharedPrefs); clearUnknownKeys(generalSharedPrefs, generalDefaults); clearUnknownKeys(adminSharedPrefs, adminDefaults); loadDefaults(generalSharedPrefs, generalDefaults); loadDefaults(adminSharedPrefs, adminDefaults); for (Map.Entry<String, ?> entry: generalSharedPrefs.getAll().entrySet()) { settingsChangedHandler.onSettingChanged(entry.getKey(), entry.getValue()); } for (Map.Entry<String, ?> entry: adminSharedPrefs.getAll().entrySet()) { settingsChangedHandler.onSettingChanged(entry.getKey(), entry.getValue()); } return true; } SettingsImporter(SharedPreferences generalSharedPrefs, SharedPreferences adminSharedPrefs, SettingsPreferenceMigrator preferenceMigrator, SettingsValidator settingsValidator, Map<String, Object> generalDefaults, Map<String, Object> adminDefaults, SettingsChangeHandler settingsChangedHandler); boolean fromJSON(@NonNull String json);  }
@Test public void whenJSONSettingsAreInvalid_returnsFalse() throws Exception { when(settingsValidator.isValid(emptySettings())).thenReturn(false); assertThat(importer.fromJSON(emptySettings()), is(false)); }
@Test public void forSettingsKeysNotINJSON_savesDefaults() throws Exception { assertThat(importer.fromJSON(emptySettings()), is(true)); assertPrefs(generalPrefs, "key1", "default", "key2", true ); assertPrefs(adminPrefs, "key1", 5 ); }
@Test public void whenKeysAlreadyExistInPrefs_overridesWithDefaults() throws Exception { initPrefs(generalPrefs, "key1", "existing", "key2", false ); initPrefs(adminPrefs, "key1", 0 ); assertThat(importer.fromJSON(emptySettings()), is(true)); assertPrefs(generalPrefs, "key1", "default", "key2", true ); assertPrefs(adminPrefs, "key1", 5 ); }
@Test public void removesUnknownKeys() throws Exception { JSONObject json = emptySettingsObject() .put("general", new JSONObject() .put("unknown_key", "value")); assertThat(importer.fromJSON(json.toString()), is(true)); assertThat(generalPrefs.contains("unknown_key"), is(false)); }
@Test public void migratesPreferences_beforeLoadingDefaults() throws Exception { SettingsPreferenceMigrator migrator = (SharedPreferences generalSharedPreferences, SharedPreferences adminSharedPreferences) -> { if (generalPrefs.contains("key1")) { throw new RuntimeException("defaults already loaded!"); } }; importer = new SettingsImporter(generalPrefs, adminPrefs, migrator, settingsValidator, generalDefaults, adminDefaults, (key, newValue) -> {}); assertThat(importer.fromJSON(emptySettings()), is(true)); }
@Test public void migratesPreferences_beforeClearingUnknowns() throws Exception { JSONObject json = emptySettingsObject() .put("general", new JSONObject() .put("unknown_key", "value")); SettingsPreferenceMigrator migrator = (SharedPreferences generalSharedPreferences, SharedPreferences adminSharedPreferences) -> { if (!generalPrefs.contains("unknown_key")) { throw new RuntimeException("unknowns already cleared!"); } }; importer = new SettingsImporter(generalPrefs, adminPrefs, migrator, settingsValidator, generalDefaults, adminDefaults, (key, newValue) -> {}); assertThat(importer.fromJSON(json.toString()), is(true)); }
@Test public void afterSettingsImportedAndMigrated_runsSettingsChangeHandlerForEveryKey() throws Exception { RecordingSettingsChangeHandler handler = new RecordingSettingsChangeHandler(); importer = new SettingsImporter(generalPrefs, adminPrefs, (SharedPreferences generalSharedPreferences, SharedPreferences adminSharedPreferences) -> {}, settingsValidator, generalDefaults, adminDefaults, handler); assertThat(importer.fromJSON(emptySettings()), is(true)); assertThat(handler.changes, containsInAnyOrder( new Pair<>("key1", "default"), new Pair<>("key2", true), new Pair<>("key1", 5))); }