diff options
Diffstat (limited to 'toolkit/components/glean/xpcshell')
-rw-r--r-- | toolkit/components/glean/xpcshell/test_Glean.js | 221 | ||||
-rw-r--r-- | toolkit/components/glean/xpcshell/xpcshell.ini | 4 |
2 files changed, 225 insertions, 0 deletions
diff --git a/toolkit/components/glean/xpcshell/test_Glean.js b/toolkit/components/glean/xpcshell/test_Glean.js new file mode 100644 index 0000000000..de273634a3 --- /dev/null +++ b/toolkit/components/glean/xpcshell/test_Glean.js @@ -0,0 +1,221 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/* FIXME: Remove these global markers. + * FOG doesn't follow the stricter naming patterns as expected by tool configuration yet. + * See https://searchfox.org/mozilla-central/source/.eslintrc.js#24 + * Reorganizing the directory structure will take this into account. + */ +/* global add_task, Assert, do_get_profile */ +"use strict"; + +Cu.importGlobalProperties(["Glean", "GleanPings"]); +const { MockRegistrar } = ChromeUtils.import( + "resource://testing-common/MockRegistrar.jsm" +); +const { ObjectUtils } = ChromeUtils.import( + "resource://gre/modules/ObjectUtils.jsm" +); +const { setTimeout } = ChromeUtils.import("resource://gre/modules/Timer.jsm"); + +/** + * Mock the SysInfo object used to read System data in Gecko. + */ +var SysInfo = { + overrides: {}, + + /** + * Checks if overrides are present and return them. + * + * @returns the overridden value or undefined if not present. + */ + _getOverridden(name) { + if (name in this.overrides) { + return this.overrides[name]; + } + + return undefined; + }, + + // To support nsIPropertyBag. + getProperty(name) { + let override = this._getOverridden(name); + return override !== undefined + ? override + : this._genuine.QueryInterface(Ci.nsIPropertyBag).getProperty(name); + }, + + // To support nsIPropertyBag2. + get(name) { + let override = this._getOverridden(name); + return override !== undefined + ? override + : this._genuine.QueryInterface(Ci.nsIPropertyBag2).get(name); + }, + + // To support nsIPropertyBag2. + getPropertyAsACString(name) { + return this.get(name); + }, + + QueryInterface: ChromeUtils.generateQI(["nsIPropertyBag2", "nsISystemInfo"]), +}; + +function sleep(ms) { + /* eslint-disable mozilla/no-arbitrary-setTimeout */ + return new Promise(resolve => setTimeout(resolve, ms)); +} + +add_task(function test_setup() { + // FOG needs a profile directory to put its data in. + do_get_profile(); + + // Mock SysInfo. + SysInfo.overrides = { + version: "1.2.3", + arc: "x64", + }; + MockRegistrar.register("@mozilla.org/system-info;1", SysInfo); + + // We need to initialize it once, otherwise operations will be stuck in the pre-init queue. + let FOG = Cc["@mozilla.org/toolkit/glean;1"].createInstance(Ci.nsIFOG); + FOG.initializeFOG(); +}); + +add_task(function test_osversion_is_set() { + Assert.equal( + "1.2.3", + Glean.fogValidation.osVersion.testGetValue("fog-validation") + ); +}); + +add_task(function test_fog_counter_works() { + Glean.testOnly.badCode.add(31); + Assert.equal(31, Glean.testOnly.badCode.testGetValue("test-ping")); +}); + +add_task(async function test_fog_string_works() { + const value = "a cheesy string!"; + Glean.testOnly.cheesyString.set(value); + + Assert.equal(value, Glean.testOnly.cheesyString.testGetValue("test-ping")); +}); + +add_task(async function test_fog_string_list_works() { + const value = "a cheesy string!"; + const value2 = "a cheesier string!"; + const value3 = "the cheeziest of strings."; + + const cheeseList = [value, value2]; + Glean.testOnly.cheesyStringList.set(cheeseList); + + let val = Glean.testOnly.cheesyStringList.testGetValue(); + // Note: This is incredibly fragile and will break if we ever rearrange items + // in the string list. + Assert.deepEqual(cheeseList, val); + + Glean.testOnly.cheesyStringList.add(value3); + Assert.ok(Glean.testOnly.cheesyStringList.testGetValue().includes(value3)); +}); + +add_task(async function test_fog_timespan_works() { + // We start, briefly sleep and then stop. + // That guarantees some time to measure. + Glean.testOnly.canWeTimeIt.start(); + await sleep(10); + Glean.testOnly.canWeTimeIt.stop(); + + Assert.ok(Glean.testOnly.canWeTimeIt.testGetValue("test-ping") > 0); +}); + +add_task(async function test_fog_uuid_works() { + const kTestUuid = "decafdec-afde-cafd-ecaf-decafdecafde"; + Glean.testOnly.whatIdIt.set(kTestUuid); + Assert.equal(kTestUuid, Glean.testOnly.whatIdIt.testGetValue("test-ping")); + + Glean.testOnly.whatIdIt.generateAndSet(); + // Since we generate v4 UUIDs, and the first character of the third group + // isn't 4, this won't ever collide with kTestUuid. + Assert.notEqual(kTestUuid, Glean.testOnly.whatIdIt.testGetValue("test-ping")); +}); + +// Enable test after bug 1677448 is fixed. +add_task({ skip_if: () => true }, function test_fog_datetime_works() { + const value = new Date("2020-06-11T12:00:00"); + + Glean.testOnly.whatADate.set(value.getTime() * 1000); + + const received = Glean.testOnly.whatADate.testGetValue("test-ping"); + Assert.ok(received.startsWith("2020-06-11T12:00:00")); +}); + +add_task(function test_fog_boolean_works() { + Glean.testOnly.canWeFlagIt.set(false); + Assert.equal(false, Glean.testOnly.canWeFlagIt.testGetValue("test-ping")); + // While you're here, might as well test that the ping name's optional. + Assert.equal(false, Glean.testOnly.canWeFlagIt.testGetValue()); +}); + +add_task(async function test_fog_event_works() { + Glean.testOnlyIpc.noExtraEvent.record(); + // FIXME(bug 1678567): Check that the value was recorded when we can. + // Assert.ok(Glean.testOnlyIpc.noExtraEvent.testGetValue("store1")); + + let extra = { extra1: "can set extras", extra2: "passing more data" }; + Glean.testOnlyIpc.anEvent.record(extra); + // FIXME(bug 1678567): Check that the value was recorded when we can. + // Assert.ok(Glean.testOnlyIpc.anEvent.testGetValue("store1")); +}); + +add_task(async function test_fog_memory_distribution_works() { + Glean.testOnly.doYouRemember.accumulate(7); + Glean.testOnly.doYouRemember.accumulate(17); + + let data = Glean.testOnly.doYouRemember.testGetValue("test-ping"); + // `data.sum` is in bytes, but the metric is in MB. + Assert.equal(24 * 1024 * 1024, data.sum, "Sum's correct"); + for (let [bucket, count] of Object.entries(data.values)) { + Assert.ok( + count == 0 || (count == 1 && (bucket == 17520006 || bucket == 7053950)), + "Only two buckets have a sample" + ); + } +}); + +add_task(function test_fog_custom_pings() { + Assert.ok("onePingOnly" in GleanPings); + // Don't bother sending it, we'll test that in the integration suite. + // See also bug 1681742. +}); + +add_task(async function test_fog_timing_distribution_works() { + let t1 = Glean.testOnly.whatTimeIsIt.start(); + let t2 = Glean.testOnly.whatTimeIsIt.start(); + + await sleep(5); + + let t3 = Glean.testOnly.whatTimeIsIt.start(); + Glean.testOnly.whatTimeIsIt.cancel(t1); + + await sleep(5); + + Glean.testOnly.whatTimeIsIt.stopAndAccumulate(t2); // 10ms + Glean.testOnly.whatTimeIsIt.stopAndAccumulate(t3); // 5ms + + let data = Glean.testOnly.whatTimeIsIt.testGetValue(); + const NANOS_IN_MILLIS = 1e6; + + // Variance in timing makes getting the sum impossible to know. + Assert.greater(data.sum, 15 * NANOS_IN_MILLIS, "Total time elapsed: > 15ms"); + + // No guarantees from timers means no guarantees on buckets. + // But we can guarantee it's only two samples. + Assert.equal( + 2, + Object.entries(data.values).reduce( + (acc, [bucket, count]) => acc + count, + 0 + ), + "Only two buckets with samples" + ); +}); diff --git a/toolkit/components/glean/xpcshell/xpcshell.ini b/toolkit/components/glean/xpcshell/xpcshell.ini new file mode 100644 index 0000000000..8bc1f67948 --- /dev/null +++ b/toolkit/components/glean/xpcshell/xpcshell.ini @@ -0,0 +1,4 @@ +[DEFAULT] +firefox-appdir = browser + +[test_Glean.js] |