/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ const CATEGORY = "telemetry.test"; const MAIN_ONLY = `${CATEGORY}.main_only`; const SYNC_ONLY = `${CATEGORY}.sync_only`; const MULTIPLE_STORES = `${CATEGORY}.multiple_stores`; const MULTIPLE_STORES_STRING = `${CATEGORY}.multiple_stores_string`; const MULTIPLE_STORES_BOOL = `${CATEGORY}.multiple_stores_bool`; const MULTIPLE_STORES_KEYED = `${CATEGORY}.multiple_stores_keyed`; function getParentSnapshot(store, keyed = false, clear = false) { return keyed ? Telemetry.getSnapshotForKeyedScalars(store, clear).parent : Telemetry.getSnapshotForScalars(store, clear).parent; } add_task(async function test_multistore_basics() { Telemetry.clearScalars(); const expectedUint = 3785; const expectedBool = true; const expectedString = "some value"; const expectedKey = "some key"; Telemetry.scalarSet(MAIN_ONLY, expectedUint); Telemetry.scalarSet(SYNC_ONLY, expectedUint); Telemetry.scalarSet(MULTIPLE_STORES, expectedUint); Telemetry.scalarSet(MULTIPLE_STORES_STRING, expectedString); Telemetry.scalarSet(MULTIPLE_STORES_BOOL, expectedBool); Telemetry.keyedScalarSet(MULTIPLE_STORES_KEYED, expectedKey, expectedUint); const mainScalars = getParentSnapshot("main"); const syncScalars = getParentSnapshot("sync"); const mainKeyedScalars = getParentSnapshot("main", true /* keyed */); const syncKeyedScalars = getParentSnapshot("sync", true /* keyed */); Assert.ok( MAIN_ONLY in mainScalars, `Main-store scalar ${MAIN_ONLY} must be in main snapshot.` ); Assert.ok( !(MAIN_ONLY in syncScalars), `Main-store scalar ${MAIN_ONLY} must not be in sync snapshot.` ); Assert.equal( mainScalars[MAIN_ONLY], expectedUint, `Main-store scalar ${MAIN_ONLY} must have correct value.` ); Assert.ok( SYNC_ONLY in syncScalars, `Sync-store scalar ${SYNC_ONLY} must be in sync snapshot.` ); Assert.ok( !(SYNC_ONLY in mainScalars), `Sync-store scalar ${SYNC_ONLY} must not be in main snapshot.` ); Assert.equal( syncScalars[SYNC_ONLY], expectedUint, `Sync-store scalar ${SYNC_ONLY} must have correct value.` ); Assert.ok( MULTIPLE_STORES in mainScalars && MULTIPLE_STORES in syncScalars, `Multi-store scalar ${MULTIPLE_STORES} must be in both main and sync snapshots.` ); Assert.equal( mainScalars[MULTIPLE_STORES], expectedUint, `Multi-store scalar ${MULTIPLE_STORES} must have correct value in main store.` ); Assert.equal( syncScalars[MULTIPLE_STORES], expectedUint, `Multi-store scalar ${MULTIPLE_STORES} must have correct value in sync store.` ); Assert.ok( MULTIPLE_STORES_STRING in mainScalars && MULTIPLE_STORES_STRING in syncScalars, `Multi-store scalar ${MULTIPLE_STORES_STRING} must be in both main and sync snapshots.` ); Assert.equal( mainScalars[MULTIPLE_STORES_STRING], expectedString, `Multi-store scalar ${MULTIPLE_STORES_STRING} must have correct value in main store.` ); Assert.equal( syncScalars[MULTIPLE_STORES_STRING], expectedString, `Multi-store scalar ${MULTIPLE_STORES_STRING} must have correct value in sync store.` ); Assert.ok( MULTIPLE_STORES_BOOL in mainScalars && MULTIPLE_STORES_BOOL in syncScalars, `Multi-store scalar ${MULTIPLE_STORES_BOOL} must be in both main and sync snapshots.` ); Assert.equal( mainScalars[MULTIPLE_STORES_BOOL], expectedBool, `Multi-store scalar ${MULTIPLE_STORES_BOOL} must have correct value in main store.` ); Assert.equal( syncScalars[MULTIPLE_STORES_BOOL], expectedBool, `Multi-store scalar ${MULTIPLE_STORES_BOOL} must have correct value in sync store.` ); Assert.ok( MULTIPLE_STORES_KEYED in mainKeyedScalars && MULTIPLE_STORES_KEYED in syncKeyedScalars, `Multi-store scalar ${MULTIPLE_STORES_KEYED} must be in both main and sync snapshots.` ); Assert.ok( expectedKey in mainKeyedScalars[MULTIPLE_STORES_KEYED] && expectedKey in syncKeyedScalars[MULTIPLE_STORES_KEYED], `Multi-store scalar ${MULTIPLE_STORES_KEYED} must have key ${expectedKey} in both snapshots.` ); Assert.equal( mainKeyedScalars[MULTIPLE_STORES_KEYED][expectedKey], expectedUint, `Multi-store scalar ${MULTIPLE_STORES_KEYED} must have correct value in main store.` ); Assert.equal( syncKeyedScalars[MULTIPLE_STORES_KEYED][expectedKey], expectedUint, `Multi-store scalar ${MULTIPLE_STORES_KEYED} must have correct value in sync store.` ); }); add_task(async function test_multistore_uint() { Telemetry.clearScalars(); // Uint scalars are the only kind with an implicit default value of 0. // They shouldn't report any value until set, but if you Add or SetMaximum // they pretend that they have been set to 0 for the purposes of that operation. function assertNotIn() { let mainScalars = getParentSnapshot("main"); let syncScalars = getParentSnapshot("sync"); if (!mainScalars && !syncScalars) { Assert.ok(true, "No scalars at all"); } else { Assert.ok( !(MULTIPLE_STORES in mainScalars) && !(MULTIPLE_STORES in syncScalars), `Multi-store scalar ${MULTIPLE_STORES} must not have an initial value in either store.` ); } } assertNotIn(); // Test that Add operates on implicit 0. Telemetry.scalarAdd(MULTIPLE_STORES, 1); function assertBothEqual(val, clear = false) { let mainScalars = getParentSnapshot("main", false, clear); let syncScalars = getParentSnapshot("sync", false, clear); Assert.ok( MULTIPLE_STORES in mainScalars && MULTIPLE_STORES in syncScalars, `Multi-store scalar ${MULTIPLE_STORES} must be in both main and sync snapshots.` ); Assert.equal( mainScalars[MULTIPLE_STORES], val, `Multi-store scalar ${MULTIPLE_STORES} must have the correct value in main store.` ); Assert.equal( syncScalars[MULTIPLE_STORES], val, `Multi-store scalar ${MULTIPLE_STORES} must have the correct value in sync store.` ); } assertBothEqual(1, true /* clear */); assertNotIn(); // Test that SetMaximum operates on implicit 0. Telemetry.scalarSetMaximum(MULTIPLE_STORES, 1337); assertBothEqual(1337); // Test that Add works, since we're in the neighbourhood. Telemetry.scalarAdd(MULTIPLE_STORES, 1); assertBothEqual(1338, true /* clear */); assertNotIn(); // Test that clearing individual stores works // and that afterwards the values are managed independently. Telemetry.scalarAdd(MULTIPLE_STORES, 1234); assertBothEqual(1234); let syncScalars = getParentSnapshot( "sync", false /* keyed */, true /* clear */ ); Assert.equal( syncScalars[MULTIPLE_STORES], 1234, `Multi-store scalar ${MULTIPLE_STORES} must be present in a second snapshot.` ); syncScalars = getParentSnapshot("sync"); Assert.equal( syncScalars, undefined, `Multi-store scalar ${MULTIPLE_STORES} must not be present after clearing.` ); let mainScalars = getParentSnapshot("main"); Assert.equal( mainScalars[MULTIPLE_STORES], 1234, `Multi-store scalar ${MULTIPLE_STORES} must maintain value in main store after sync store is cleared.` ); Telemetry.scalarSetMaximum(MULTIPLE_STORES, 1); syncScalars = getParentSnapshot("sync"); Assert.equal( syncScalars[MULTIPLE_STORES], 1, `Multi-store scalar ${MULTIPLE_STORES} must return to using implicit 0 for setMax operation.` ); mainScalars = getParentSnapshot("main"); Assert.equal( mainScalars[MULTIPLE_STORES], 1234, `Multi-store scalar ${MULTIPLE_STORES} must retain old value.` ); Telemetry.scalarAdd(MULTIPLE_STORES, 1); syncScalars = getParentSnapshot("sync"); Assert.equal( syncScalars[MULTIPLE_STORES], 2, `Multi-store scalar ${MULTIPLE_STORES} must manage independently for add operations.` ); mainScalars = getParentSnapshot("main"); Assert.equal( mainScalars[MULTIPLE_STORES], 1235, `Multi-store scalar ${MULTIPLE_STORES} must add properly.` ); Telemetry.scalarSet(MULTIPLE_STORES, 9876); assertBothEqual(9876); }); add_task(async function test_empty_absence() { // Current semantics are we don't snapshot empty things. // So no {parent: {}, ...}. Instead {...}. Telemetry.clearScalars(); Telemetry.scalarSet(MULTIPLE_STORES, 1); let snapshot = getParentSnapshot("main", false /* keyed */, true /* clear */); Assert.ok( MULTIPLE_STORES in snapshot, `${MULTIPLE_STORES} must be in the snapshot.` ); Assert.equal( snapshot[MULTIPLE_STORES], 1, `${MULTIPLE_STORES} must have the correct value.` ); snapshot = getParentSnapshot("main", false /* keyed */, true /* clear */); Assert.equal( snapshot, undefined, `Parent snapshot must be empty if no data.` ); snapshot = getParentSnapshot("sync", false /* keyed */, true /* clear */); Assert.ok( MULTIPLE_STORES in snapshot, `${MULTIPLE_STORES} must be in the sync snapshot.` ); Assert.equal( snapshot[MULTIPLE_STORES], 1, `${MULTIPLE_STORES} must have the correct value in the sync snapshot.` ); }); add_task(async function test_empty_absence_keyed() { // Current semantics are we don't snapshot empty things. // So no {parent: {}, ...}. Instead {...}. // And for Keyed Scalars, no {parent: { keyed_scalar: {} }, ...}. Just {...}. Telemetry.clearScalars(); const key = "just a key, y'know"; Telemetry.keyedScalarSet(MULTIPLE_STORES_KEYED, key, 1); let snapshot = getParentSnapshot("main", true /* keyed */, true /* clear */); Assert.ok( MULTIPLE_STORES_KEYED in snapshot, `${MULTIPLE_STORES_KEYED} must be in the snapshot.` ); Assert.ok( key in snapshot[MULTIPLE_STORES_KEYED], `${MULTIPLE_STORES_KEYED} must have the stored key.` ); Assert.equal( snapshot[MULTIPLE_STORES_KEYED][key], 1, `${MULTIPLE_STORES_KEYED}[${key}] should have the correct value.` ); snapshot = getParentSnapshot("main", true /* keyed */); Assert.equal( snapshot, undefined, `Parent snapshot should be empty if no data.` ); snapshot = getParentSnapshot("sync", true /* keyed */); Assert.ok( MULTIPLE_STORES_KEYED in snapshot, `${MULTIPLE_STORES_KEYED} must be in the sync snapshot.` ); Assert.ok( key in snapshot[MULTIPLE_STORES_KEYED], `${MULTIPLE_STORES_KEYED} must have the stored key.` ); Assert.equal( snapshot[MULTIPLE_STORES_KEYED][key], 1, `${MULTIPLE_STORES_KEYED}[${key}] should have the correct value.` ); }); add_task(async function test_multistore_default_values() { Telemetry.clearScalars(); const expectedUint = 3785; const expectedKey = "some key"; Telemetry.scalarSet(MAIN_ONLY, expectedUint); Telemetry.scalarSet(SYNC_ONLY, expectedUint); Telemetry.scalarSet(MULTIPLE_STORES, expectedUint); Telemetry.keyedScalarSet(MULTIPLE_STORES_KEYED, expectedKey, expectedUint); let mainScalars; let mainKeyedScalars; // Getting snapshot and NOT clearing (using default values for optional parameters) mainScalars = Telemetry.getSnapshotForScalars().parent; mainKeyedScalars = Telemetry.getSnapshotForKeyedScalars().parent; Assert.equal( mainScalars[MAIN_ONLY], expectedUint, `Main-store scalar ${MAIN_ONLY} must have correct value.` ); Assert.ok( !(SYNC_ONLY in mainScalars), `Sync-store scalar ${SYNC_ONLY} must not be in main snapshot.` ); Assert.equal( mainScalars[MULTIPLE_STORES], expectedUint, `Multi-store scalar ${MULTIPLE_STORES} must have correct value in main store.` ); Assert.equal( mainKeyedScalars[MULTIPLE_STORES_KEYED][expectedKey], expectedUint, `Multi-store scalar ${MULTIPLE_STORES_KEYED} must have correct value in main store.` ); // Getting snapshot and clearing mainScalars = Telemetry.getSnapshotForScalars("main", true).parent; mainKeyedScalars = Telemetry.getSnapshotForKeyedScalars("main", true).parent; Assert.equal( mainScalars[MAIN_ONLY], expectedUint, `Main-store scalar ${MAIN_ONLY} must have correct value.` ); Assert.ok( !(SYNC_ONLY in mainScalars), `Sync-store scalar ${SYNC_ONLY} must not be in main snapshot.` ); Assert.equal( mainScalars[MULTIPLE_STORES], expectedUint, `Multi-store scalar ${MULTIPLE_STORES} must have correct value in main store.` ); Assert.equal( mainKeyedScalars[MULTIPLE_STORES_KEYED][expectedKey], expectedUint, `Multi-store scalar ${MULTIPLE_STORES_KEYED} must have correct value in main store.` ); // Getting snapshot (with default values), should be empty now mainScalars = Telemetry.getSnapshotForScalars().parent || {}; mainKeyedScalars = Telemetry.getSnapshotForKeyedScalars().parent || {}; Assert.ok( !(MAIN_ONLY in mainScalars), `Main-store scalar ${MAIN_ONLY} must not be in main snapshot.` ); Assert.ok( !(MULTIPLE_STORES in mainScalars), `Multi-store scalar ${MULTIPLE_STORES} must not be in main snapshot.` ); Assert.ok( !(MULTIPLE_STORES_KEYED in mainKeyedScalars), `Multi-store scalar ${MULTIPLE_STORES_KEYED} must not be in main snapshot.` ); });