michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: package org.mozilla.gecko.background.healthreport; michael@0: michael@0: import java.io.File; michael@0: import java.io.IOException; michael@0: michael@0: import org.json.JSONException; michael@0: import org.json.JSONObject; michael@0: import org.mozilla.gecko.background.helpers.FakeProfileTestCase; michael@0: michael@0: public class TestProfileInformationCache extends FakeProfileTestCase { michael@0: michael@0: public final void testInitState() throws IOException { michael@0: MockProfileInformationCache cache = new MockProfileInformationCache(this.fakeProfileDirectory.getAbsolutePath()); michael@0: assertFalse(cache.isInitialized()); michael@0: assertFalse(cache.needsWrite()); michael@0: michael@0: try { michael@0: cache.isBlocklistEnabled(); michael@0: fail("Should throw fetching isBlocklistEnabled."); michael@0: } catch (IllegalStateException e) { michael@0: // Great! michael@0: } michael@0: michael@0: cache.beginInitialization(); michael@0: assertFalse(cache.isInitialized()); michael@0: assertTrue(cache.needsWrite()); michael@0: michael@0: try { michael@0: cache.isBlocklistEnabled(); michael@0: fail("Should throw fetching isBlocklistEnabled."); michael@0: } catch (IllegalStateException e) { michael@0: // Great! michael@0: } michael@0: michael@0: cache.completeInitialization(); michael@0: assertTrue(cache.isInitialized()); michael@0: assertFalse(cache.needsWrite()); michael@0: } michael@0: michael@0: public final MockProfileInformationCache makeCache(final String suffix) { michael@0: File subdir = new File(this.fakeProfileDirectory.getAbsolutePath() + File.separator + suffix); michael@0: subdir.mkdir(); michael@0: return new MockProfileInformationCache(subdir.getAbsolutePath()); michael@0: } michael@0: michael@0: public final void testPersisting() throws IOException { michael@0: MockProfileInformationCache cache = makeCache("testPersisting"); michael@0: // We start with no file. michael@0: assertFalse(cache.getFile().exists()); michael@0: michael@0: // Partially populate. Note that this doesn't happen in live code, but michael@0: // apparently we can end up with null add-ons JSON on disk, so this michael@0: // reproduces that scenario. michael@0: cache.beginInitialization(); michael@0: cache.setBlocklistEnabled(true); michael@0: cache.setTelemetryEnabled(true); michael@0: cache.setProfileCreationTime(1234L); michael@0: cache.completeInitialization(); michael@0: michael@0: assertTrue(cache.getFile().exists()); michael@0: michael@0: // But reading this from disk won't work, because we were only partially michael@0: // initialized. We want to start over. michael@0: cache = makeCache("testPersisting"); michael@0: assertFalse(cache.isInitialized()); michael@0: assertFalse(cache.restoreUnlessInitialized()); michael@0: assertFalse(cache.isInitialized()); michael@0: michael@0: // Now fully populate, and try again... michael@0: cache.beginInitialization(); michael@0: cache.setBlocklistEnabled(true); michael@0: cache.setTelemetryEnabled(true); michael@0: cache.setProfileCreationTime(1234L); michael@0: cache.setJSONForAddons(new JSONObject()); michael@0: cache.completeInitialization(); michael@0: assertTrue(cache.getFile().exists()); michael@0: michael@0: // ... and this time we succeed. michael@0: cache = makeCache("testPersisting"); michael@0: assertFalse(cache.isInitialized()); michael@0: assertTrue(cache.restoreUnlessInitialized()); michael@0: assertTrue(cache.isInitialized()); michael@0: assertTrue(cache.isBlocklistEnabled()); michael@0: assertTrue(cache.isTelemetryEnabled()); michael@0: assertEquals(1234L, cache.getProfileCreationTime()); michael@0: michael@0: // Mutate. michael@0: cache.beginInitialization(); michael@0: assertFalse(cache.isInitialized()); michael@0: cache.setBlocklistEnabled(false); michael@0: cache.setProfileCreationTime(2345L); michael@0: cache.completeInitialization(); michael@0: assertTrue(cache.isInitialized()); michael@0: michael@0: cache = makeCache("testPersisting"); michael@0: assertFalse(cache.isInitialized()); michael@0: assertTrue(cache.restoreUnlessInitialized()); michael@0: michael@0: assertTrue(cache.isInitialized()); michael@0: assertFalse(cache.isBlocklistEnabled()); michael@0: assertTrue(cache.isTelemetryEnabled()); michael@0: assertEquals(2345L, cache.getProfileCreationTime()); michael@0: } michael@0: michael@0: public final void testVersioning() throws JSONException, IOException { michael@0: MockProfileInformationCache cache = makeCache("testVersioning"); michael@0: final int currentVersion = ProfileInformationCache.FORMAT_VERSION; michael@0: final JSONObject json = cache.toJSON(); michael@0: assertEquals(currentVersion, json.getInt("version")); michael@0: michael@0: // Initialize enough that we can re-load it. michael@0: cache.beginInitialization(); michael@0: cache.setJSONForAddons(new JSONObject()); michael@0: cache.completeInitialization(); michael@0: cache.writeJSON(json); michael@0: assertTrue(cache.restoreUnlessInitialized()); michael@0: cache.beginInitialization(); // So that we'll need to read again. michael@0: json.put("version", currentVersion + 1); michael@0: cache.writeJSON(json); michael@0: michael@0: // We can't restore a future version. michael@0: assertFalse(cache.restoreUnlessInitialized()); michael@0: } michael@0: michael@0: public void testRestoreInvalidJSON() throws Exception { michael@0: final MockProfileInformationCache cache = makeCache("invalid"); michael@0: michael@0: final JSONObject invalidJSON = new JSONObject(); michael@0: invalidJSON.put("blocklist", true); michael@0: invalidJSON.put("telemetry", false); michael@0: invalidJSON.put("profileCreated", 1234567L); michael@0: cache.writeJSON(invalidJSON); michael@0: assertFalse(cache.restoreUnlessInitialized()); michael@0: } michael@0: michael@0: private JSONObject getValidCacheJSON() throws Exception { michael@0: final JSONObject json = new JSONObject(); michael@0: json.put("blocklist", true); michael@0: json.put("telemetry", false); michael@0: json.put("profileCreated", 1234567L); michael@0: json.put("addons", new JSONObject()); michael@0: json.put("version", ProfileInformationCache.FORMAT_VERSION); michael@0: return json; michael@0: } michael@0: michael@0: public void testRestoreImplicitV1() throws Exception { michael@0: assertTrue(ProfileInformationCache.FORMAT_VERSION > 1); michael@0: michael@0: final MockProfileInformationCache cache = makeCache("implicitV1"); michael@0: final JSONObject json = getValidCacheJSON(); michael@0: json.remove("version"); michael@0: cache.writeJSON(json); michael@0: // Can't restore v1 (which is implicitly set) since it is not the current version. michael@0: assertFalse(cache.restoreUnlessInitialized()); michael@0: } michael@0: michael@0: public void testRestoreOldVersion() throws Exception { michael@0: final int oldVersion = 1; michael@0: assertTrue(ProfileInformationCache.FORMAT_VERSION > oldVersion); michael@0: michael@0: final MockProfileInformationCache cache = makeCache("oldVersion"); michael@0: final JSONObject json = getValidCacheJSON(); michael@0: json.put("version", oldVersion); michael@0: cache.writeJSON(json); michael@0: assertFalse(cache.restoreUnlessInitialized()); michael@0: } michael@0: michael@0: public void testRestoreCurrentVersion() throws Exception { michael@0: final MockProfileInformationCache cache = makeCache("currentVersion"); michael@0: final JSONObject json = getValidCacheJSON(); michael@0: cache.writeJSON(json); michael@0: cache.beginInitialization(); michael@0: cache.setTelemetryEnabled(true); michael@0: cache.completeInitialization(); michael@0: assertEquals(ProfileInformationCache.FORMAT_VERSION, cache.readJSON().getInt("version")); michael@0: } michael@0: }