Bug 1009315 - Part 4: Fix testUITelemetry. r=liuche

This commit is contained in:
Michael Comella 2014-05-30 16:53:35 -07:00
parent b265babdb0
commit a246cd7868
3 changed files with 148 additions and 57 deletions

View File

@ -5,11 +5,17 @@
package org.mozilla.gecko;
import org.mozilla.gecko.mozglue.RobocopTarget;
/**
* Holds data definitions for our UI Telemetry implementation.
*
* Note that enum values of "_TEST*" are reserved for testing and
* should not be changed without changing the associated tests.
*
* See mobile/android/base/docs/index.rst for a full dictionary.
*/
@RobocopTarget
public interface TelemetryContract {
/**
@ -64,6 +70,12 @@ public interface TelemetryContract {
// Stop holding a resource (reader, bookmark, etc) for viewing later.
// Note: Only used in JavaScript for now, but here for completeness.
UNSAVE("unsave.1"),
// VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
_TEST1("_test_event_1.1"),
_TEST2("_test_event_2.1"),
_TEST3("_test_event_3.1"),
_TEST4("_test_event_4.1"),
;
private final String string;
@ -124,6 +136,10 @@ public interface TelemetryContract {
// Action triggered from a suggestion provided to the user.
SUGGESTION("suggestion"),
// VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
_TEST1("_test_method_1"),
_TEST2("_test_method_2"),
;
private final String string;
@ -164,6 +180,10 @@ public interface TelemetryContract {
// Started when a Reader viewer becomes active in the foreground.
// Note: Only used in JavaScript for now, but here for completeness.
READER("reader.1"),
// VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
_TEST_STARTED_TWICE("_test_session_started_twice.1"),
_TEST_STOPPED_TWICE("_test_session_stopped_twice.1"),
;
private final String string;
@ -190,6 +210,11 @@ public interface TelemetryContract {
// No reason is specified.
NONE(null),
// VALUES BELOW THIS LINE ARE EXCLUSIVE TO TESTING.
_TEST1("_test_reason_1"),
_TEST2("_test_reason_2"),
_TEST_IGNORED("_test_reason_ignored"),
;
private final String string;

View File

@ -3,14 +3,14 @@ package org.mozilla.gecko.tests;
import org.mozilla.gecko.AppConstants;
import org.mozilla.gecko.PrefsHelper;
import org.mozilla.gecko.Telemetry;
import org.mozilla.gecko.TelemetryContract.Event;
import org.mozilla.gecko.TelemetryContract.Method;
import org.mozilla.gecko.TelemetryContract.Reason;
import org.mozilla.gecko.TelemetryContract.Session;
import android.util.Log;
public class testUITelemetry extends JavascriptTest {
// Prefix used to distinguish test events and sessions from
// real ones. Used by the javascript part of the test.
static final String TEST_PREFIX = "TEST-";
public testUITelemetry() {
super("testUITelemetry.js");
}
@ -26,18 +26,24 @@ public class testUITelemetry extends JavascriptTest {
Log.i("GeckoTest", "Adding telemetry events.");
try {
Telemetry.sendUIEvent(TEST_PREFIX + "enone", "method0");
Telemetry.startUISession(TEST_PREFIX + "foo");
Telemetry.sendUIEvent(TEST_PREFIX + "efoo", "method1");
Telemetry.startUISession(TEST_PREFIX + "foo");
Telemetry.sendUIEvent(TEST_PREFIX + "efoo", "method2");
Telemetry.startUISession(TEST_PREFIX + "bar");
Telemetry.sendUIEvent(TEST_PREFIX + "efoobar", "method3", "foobarextras");
Telemetry.stopUISession(TEST_PREFIX + "foo", "reasonfoo");
Telemetry.sendUIEvent(TEST_PREFIX + "ebar", "method4", "barextras");
Telemetry.stopUISession(TEST_PREFIX + "bar", "reasonbar");
Telemetry.stopUISession(TEST_PREFIX + "bar", "reasonbar2");
Telemetry.sendUIEvent(TEST_PREFIX + "enone", "method5");
Telemetry.sendUIEvent(Event._TEST1, Method._TEST1);
Telemetry.startUISession(Session._TEST_STARTED_TWICE);
Telemetry.sendUIEvent(Event._TEST2, Method._TEST1);
// We can only start one session per name, so this call should be ignored.
Telemetry.startUISession(Session._TEST_STARTED_TWICE);
Telemetry.sendUIEvent(Event._TEST2, Method._TEST2);
Telemetry.startUISession(Session._TEST_STOPPED_TWICE);
Telemetry.sendUIEvent(Event._TEST3, Method._TEST1, "foobarextras");
Telemetry.stopUISession(Session._TEST_STARTED_TWICE, Reason._TEST1);
Telemetry.sendUIEvent(Event._TEST4, Method._TEST1, "barextras");
Telemetry.stopUISession(Session._TEST_STOPPED_TWICE, Reason._TEST2);
// This session is already stopped, so this call should be ignored.
Telemetry.stopUISession(Session._TEST_STOPPED_TWICE, Reason._TEST_IGNORED);
Telemetry.sendUIEvent(Event._TEST1, Method._TEST1);
} catch (Exception e) {
Log.e("GeckoTest", "Oops.", e);
}

View File

@ -9,8 +9,19 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/Services.jsm");
const TEST_PREFIX = "TEST-";
const TEST_REGEX = new RegExp("^" + TEST_PREFIX);
const EVENT_TEST1 = "_test_event_1.1";
const EVENT_TEST2 = "_test_event_2.1";
const EVENT_TEST3 = "_test_event_3.1";
const EVENT_TEST4 = "_test_event_4.1";
const METHOD_TEST1 = "_test_method_1";
const METHOD_TEST2 = "_test_method_2";
const REASON_TEST1 = "_test_reason_1";
const REASON_TEST2 = "_test_reason_2";
const SESSION_STARTED_TWICE = "_test_session_started_twice.1";
const SESSION_STOPPED_TWICE = "_test_session_stopped_twice.1";
function do_check_array_eq(a1, a2) {
do_check_eq(a1.length, a2.length);
@ -19,6 +30,31 @@ function do_check_array_eq(a1, a2) {
}
}
/**
* Asserts that the given measurements are equal. Assumes that measurements
* of type "event" have their sessions arrays sorted.
*/
function do_check_measurement_eq(m1, m2) {
do_check_eq(m1.type, m2.type);
switch (m1.type) {
case "event":
do_check_eq(m1.action, m2.action);
do_check_eq(m1.method, m2.method);
do_check_array_eq(m1.sessions, m2.sessions);
do_check_eq(m1.extras, m2.extras);
break;
case "session":
do_check_eq(m1.name, m2.name);
do_check_eq(m1.reason, m2.reason);
break;
default:
do_throw("Unknown event type: " + m1.type);
}
}
function getObserver() {
let bridge = Cc["@mozilla.org/android/bridge;1"]
.getService(Ci.nsIAndroidBridge);
@ -39,49 +75,73 @@ add_test(function test_enabled() {
});
add_test(function test_telemetry_events() {
let expected = expectedArraysToObjs([
["event", EVENT_TEST1, METHOD_TEST1, [], undefined],
["event", EVENT_TEST2, METHOD_TEST1, [SESSION_STARTED_TWICE], undefined],
["event", EVENT_TEST2, METHOD_TEST2, [SESSION_STARTED_TWICE], undefined],
["event", EVENT_TEST3, METHOD_TEST1, [SESSION_STARTED_TWICE, SESSION_STOPPED_TWICE], "foobarextras"],
["session", SESSION_STARTED_TWICE, REASON_TEST1],
["event", EVENT_TEST4, METHOD_TEST1, [SESSION_STOPPED_TWICE], "barextras"],
["session", SESSION_STOPPED_TWICE, REASON_TEST2],
["event", EVENT_TEST1, METHOD_TEST1, [], undefined],
]);
let obs = getObserver();
let measurements = obs.getUIMeasurements().filter(function(m) {
// Only want events and sessions that were generated by
// the Java-side of the test.
return TEST_REGEX.test(m.type == "event" ? m.action : m.name);
let measurements = removeNonTestMeasurements(obs.getUIMeasurements());
measurements.forEach(function (m, i) {
if (m.type === "event") {
m.sessions = removeNonTestSessions(m.sessions);
m.sessions.sort(); // Mutates.
}
do_check_measurement_eq(expected[i], m);
});
let expected = [
["event", TEST_PREFIX + "enone", "method0", [], null],
["event", TEST_PREFIX + "efoo", "method1", [TEST_PREFIX + "foo"], null],
["event", TEST_PREFIX + "efoo", "method2", [TEST_PREFIX + "foo"], null],
["event", TEST_PREFIX + "efoobar", "method3", [TEST_PREFIX + "foo", TEST_PREFIX + "bar"], "foobarextras"],
["session", TEST_PREFIX + "foo", "reasonfoo"],
["event", TEST_PREFIX + "ebar", "method4", [TEST_PREFIX + "bar"], "barextras"],
["session", TEST_PREFIX + "bar", "reasonbar"],
["event", TEST_PREFIX + "enone", "method5", [], null],
];
do_check_eq(expected.length, measurements.length);
for (let i = 0; i < measurements.length; ++i) {
let m = measurements[i];
let type = m.type;
if (type == "event") {
let [type, action, method, sessions, extras] = expected[i];
do_check_eq(m.action, action);
do_check_eq(m.method, method);
// might receive real sessions in addition to the test ones -- remove the real ones
do_check_array_eq(m.sessions.filter(s => TEST_REGEX.test(s)), sessions);
do_check_eq(m.extras, extras);
continue;
}
if (type == "session") {
let [type, name, reason] = expected[i];
do_check_eq(m.name, name);
do_check_eq(m.reason, reason);
continue;
}
}
run_next_test();
});
/**
* Converts the expected value arrays to objects,
* for less typing when initializing the expected arrays.
*/
function expectedArraysToObjs(expectedArrays) {
return expectedArrays.map(function (arr) {
let type = arr[0];
if (type === "event") {
return {
type: type,
action: arr[1],
method: arr[2],
sessions: arr[3].sort(), // Sort, just in case it's not sorted by hand!
extras: arr[4],
};
} else if (type === "session") {
return {
type: type,
name: arr[1],
reason: arr[2],
};
}
});
}
function removeNonTestMeasurements(measurements) {
return measurements.filter(function (measurement) {
if (measurement.type === "event") {
return measurement.action.startsWith("_test_event_");
} else if (measurement.type === "session") {
return measurement.name.startsWith("_test_session_");
}
return false;
});
}
function removeNonTestSessions(sessions) {
return sessions.filter(function (sessionName) {
return sessionName.startsWith("_test_session_");
});
}
run_next_test();