Bug 1249491 - Add health report client ID migration test. r=sebastian,gfritzche
authorMichael Comella <michael.l.comella@gmail.com>
Thu, 24 Mar 2016 16:13:40 -0700
changeset 290800 416d7925fc2df25bb85e26bee3fd78605a312566
parent 290799 1e683499ef1155866eb34b57d01b0e8c0e337fa3
child 290801 5291c136bb0bac166a1dfe96fe2c931e79cf94ce
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssebastian, gfritzche
bugs1249491
milestone48.0a1
Bug 1249491 - Add health report client ID migration test. r=sebastian,gfritzche MozReview-Commit-ID: 9QbkKwEoNwq
mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUnifiedTelemetryClientId.java
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUnifiedTelemetryClientId.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testUnifiedTelemetryClientId.java
@@ -1,25 +1,30 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 package org.mozilla.gecko.tests;
 
 import static org.mozilla.gecko.tests.helpers.AssertionHelper.*;
 
+import org.json.JSONException;
+import org.json.JSONObject;
 import org.mozilla.gecko.GeckoProfile;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.UUID;
 
 public class testUnifiedTelemetryClientId extends JavascriptBridgeTest {
     private static final String TEST_JS = "testUnifiedTelemetryClientId.js";
 
     private static final String CLIENT_ID_PATH = "datareporting/state.json";
+    private static final String FHR_DIR_PATH = "healthreport/";
+    private static final String FHR_CLIENT_ID_PATH = FHR_DIR_PATH + "state.json";
 
     private GeckoProfile profile;
     private File profileDir;
 
     public void setUp() throws Exception {
         super.setUp();
         profile = getTestProfile();
         profileDir = profile.getDir(); // Assumes getDir is tested.
@@ -27,39 +32,44 @@ public class testUnifiedTelemetryClientI
         // In local testing, it's possible to ^C out of the harness and not have tearDown called,
         // hence reset. We can't clear the cache because Gecko is not running yet.
         resetTest(false);
     }
 
     public void tearDown() throws Exception {
         // Don't clear cache because who knows what state Gecko is in.
         resetTest(false);
-        getClientIdFile().delete();
         super.tearDown();
     }
 
     private void resetTest(final boolean resetJSCache) {
         if (resetJSCache) {
             resetJSCache();
         }
         getClientIdFile().delete();
+        getFHRClientIdFile().delete();
+        getFHRClientIdParentDir().delete();
     }
 
     // TODO: If the intent service runs in the background, it could break this test. The service is disabled
     // on non-official builds (e.g. this one) but that may not be the case on TBPL.
     public void testUnifiedTelemetryClientId() throws Exception {
         blockForReadyAndLoadJS(TEST_JS);
         resetJSCache(); // Must be called after Gecko is loaded.
         fAssertTrue("Profile directory exists", profileDir.exists());
 
         // TODO: If these tests weren't so expensive to run in automation,
         // this should be two separate tests to avoid storing state between tests.
         testJavaCreatesClientId();
         resetTest(true);
         testJsCreatesClientId();
+        resetTest(true);
+        testJavaMigratesFromHealthReport();
+        resetTest(true);
+        testJsMigratesFromHealthReport();
 
         getJS().syncCall("endTest");
     }
 
     /**
      * Scenario: Java creates client ID:
      *   * Fennec starts on fresh profile
      *   * Java code creates the client ID in datareporting/state.json
@@ -100,16 +110,75 @@ public class testUnifiedTelemetryClientI
         final String clientIdFromJavaAgain = getClientIdFromJava();
         resetJSCache();
         final String clientIdFromJSFileAgain = getClientIdFromJS();
         fAssertEquals("Same client ID retrieved from JS cache", clientIdFromJS, clientIdFromJSCache);
         fAssertEquals("Same client ID retrieved from JS file", clientIdFromJS, clientIdFromJSFileAgain);
         fAssertEquals("Same client ID retrieved from Java", clientIdFromJS, clientIdFromJavaAgain);
     }
 
+    /**
+     * Scenario: Java migrates client ID from FHR client ID file.
+     *   * FHR file already exists.
+     *   * Fennec starts on fresh profile
+     *   * Java code merges client ID to datareporting/state.json from healthreport/state.json
+     *   * Js accesses client ID from the same file
+     *   * Assert the client IDs are the same
+     */
+    private void testJavaMigratesFromHealthReport() throws Exception {
+        fAssertFalse("Client id file does not exist yet", getClientIdFile().exists());
+        fAssertFalse("Health report file does not exist yet", getFHRClientIdFile().exists());
+
+        final String expectedClientId = UUID.randomUUID().toString();
+        createFHRClientIdFile(expectedClientId);
+
+        final String clientIdFromJava = getClientIdFromJava();
+        fAssertEquals("Health report client ID merged by Java", expectedClientId, clientIdFromJava);
+        final String clientIdFromJS = getClientIdFromJS();
+        fAssertEquals("Merged client ID read by JS", expectedClientId, clientIdFromJS);
+
+        final String clientIdFromJavaAgain = getClientIdFromJava();
+        final String clientIdFromJSCache = getClientIdFromJS();
+        resetJSCache();
+        final String clientIdFromJSFileAgain = getClientIdFromJS();
+        fAssertEquals("Same client ID retrieved from Java", expectedClientId, clientIdFromJavaAgain);
+        fAssertEquals("Same client ID retrieved from JS cache", expectedClientId, clientIdFromJSCache);
+        fAssertEquals("Same client ID retrieved from JS file", expectedClientId, clientIdFromJSFileAgain);
+    }
+
+    /**
+     * Scenario: JS merges client ID from FHR client ID file.
+     *   * FHR file already exists.
+     *   * Fennec starts on a fresh profile
+     *   * Js merges the client ID to datareporting/state.json from healthreport/state.json
+     *   * Java access the client ID from the same file
+     *   * Assert the client IDs are the same
+     */
+    private void testJsMigratesFromHealthReport() throws Exception {
+        fAssertFalse("Client id file does not exist yet", getClientIdFile().exists());
+        fAssertFalse("Health report file does not exist yet", getFHRClientIdFile().exists());
+
+        final String expectedClientId = UUID.randomUUID().toString();
+        createFHRClientIdFile(expectedClientId);
+
+        final String clientIdFromJS = getClientIdFromJS();
+        fAssertEquals("Health report client ID merged by JS", expectedClientId, clientIdFromJS);
+        final String clientIdFromJava = getClientIdFromJava();
+        fAssertEquals("Merged client ID read by Java", expectedClientId, clientIdFromJava);
+
+        final String clientIdFromJavaAgain = getClientIdFromJava();
+        final String clientIdFromJSCache = getClientIdFromJS();
+        resetJSCache();
+        final String clientIdFromJSFileAgain = getClientIdFromJS();
+        fAssertEquals("Same client ID retrieved from Java", expectedClientId, clientIdFromJavaAgain);
+        fAssertEquals("Same client ID retrieved from JS cache", expectedClientId, clientIdFromJSCache);
+        fAssertEquals("Same client ID retrieved from JS file", expectedClientId, clientIdFromJSFileAgain);
+
+    }
+
     private String getClientIdFromJava() throws IOException {
         // This assumes implementation details: it assumes the client ID
         // file is created when Java attempts to retrieve it if it does not exist.
         final String clientId = profile.getClientId();
         fAssertNotNull("Returned client ID is not null", clientId);
         fAssertTrue("Client ID file exists after getClientId call", getClientIdFile().exists());
         return clientId;
     }
@@ -126,9 +195,26 @@ public class testUnifiedTelemetryClientI
         // HACK: the backing JS method is a promise with no return value. Rather than writing a method
         // to handle this (for time reasons), I call the get String method and don't access the return value.
         getBlockingFromJsString("reset");
     }
 
     private File getClientIdFile() {
         return new File(profileDir, CLIENT_ID_PATH);
     }
+
+    private File getFHRClientIdParentDir() {
+        return new File(profileDir, FHR_DIR_PATH);
+    }
+
+    private File getFHRClientIdFile() {
+        return new File(profileDir, FHR_CLIENT_ID_PATH);
+    }
+
+    private void createFHRClientIdFile(final String clientId) throws JSONException {
+        fAssertTrue("FHR directory created", getFHRClientIdParentDir().mkdirs());
+
+        final JSONObject obj = new JSONObject();
+        obj.put("clientID", clientId);
+        profile.writeFile(FHR_CLIENT_ID_PATH, obj.toString());
+        fAssertTrue("FHR client ID file exists after writing", getFHRClientIdFile().exists());
+    }
 }