summaryrefslogtreecommitdiffstats
path: root/toolkit/components/glean/tests/xpcshell/test_GleanIPC.js
blob: 3d665c23b9ea4318eed92fe867189a148ecdde8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

const { AppConstants } = ChromeUtils.importESModule(
  "resource://gre/modules/AppConstants.sys.mjs"
);
const { setTimeout } = ChromeUtils.importESModule(
  "resource://gre/modules/Timer.sys.mjs"
);

function sleep(ms) {
  /* eslint-disable mozilla/no-arbitrary-setTimeout */
  return new Promise(resolve => setTimeout(resolve, ms));
}

add_setup(
  /* on Android FOG is set up through head.js */
  { skip_if: () => !runningInParent || AppConstants.platform == "android" },
  function test_setup() {
    // Give FOG a temp profile to init within.
    do_get_profile();

    // We need to initialize it once, otherwise operations will be stuck in the pre-init queue.
    Services.fog.initializeFOG();
  }
);

const BAD_CODE_COUNT = 42;
const CHEESY_STRING = "a very cheesy string!";
const CHEESIER_STRING = "a much cheesier string!";
const EVENT_EXTRA = { extra1: "so very extra" };
const MEMORIES = [13, 31];
const MEMORY_BUCKETS = ["13509772", "32131834"]; // buckets are strings : |
const COUNTERS_NEAR_THE_SINK = 3;
const COUNTERS_WITH_JUNK_ON_THEM = 5;
const INVALID_COUNTERS = 7;

add_task({ skip_if: () => runningInParent }, async function run_child_stuff() {
  Glean.testOnly.badCode.add(BAD_CODE_COUNT);
  Glean.testOnly.cheesyStringList.add(CHEESY_STRING);
  Glean.testOnly.cheesyStringList.add(CHEESIER_STRING);

  Glean.testOnlyIpc.noExtraEvent.record();
  Glean.testOnlyIpc.anEvent.record(EVENT_EXTRA);

  for (let memory of MEMORIES) {
    Glean.testOnly.doYouRemember.accumulate(memory);
  }

  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

  Glean.testOnlyIpc.aCustomDist.accumulateSamples([3, 4]);

  Glean.testOnly.mabelsKitchenCounters.near_the_sink.add(
    COUNTERS_NEAR_THE_SINK
  );
  Glean.testOnly.mabelsKitchenCounters.with_junk_on_them.add(
    COUNTERS_WITH_JUNK_ON_THEM
  );

  Glean.testOnly.mabelsBathroomCounters["1".repeat(72)].add(INVALID_COUNTERS);

  Glean.testOnlyIpc.irate.addToNumerator(44);
  Glean.testOnlyIpc.irate.addToDenominator(14);
});

add_task(
  { skip_if: () => !runningInParent },
  async function test_child_metrics() {
    await run_test_in_child("test_GleanIPC.js");
    await Services.fog.testFlushAllChildren();

    Assert.equal(Glean.testOnly.badCode.testGetValue(), BAD_CODE_COUNT);

    // Note: this will break if string list ever rearranges its items.
    const cheesyStrings = Glean.testOnly.cheesyStringList.testGetValue();
    Assert.deepEqual(cheesyStrings, [CHEESY_STRING, CHEESIER_STRING]);

    const data = Glean.testOnly.doYouRemember.testGetValue();
    Assert.equal(MEMORIES.reduce((a, b) => a + b, 0) * 1024 * 1024, data.sum);
    for (let [bucket, count] of Object.entries(data.values)) {
      // We could assert instead, but let's skip to save the logspam.
      if (count == 0) {
        continue;
      }
      Assert.ok(count == 1 && MEMORY_BUCKETS.includes(bucket));
    }

    const customData = Glean.testOnlyIpc.aCustomDist.testGetValue("store1");
    Assert.equal(3 + 4, customData.sum, "Sum's correct");
    for (let [bucket, count] of Object.entries(customData.values)) {
      Assert.ok(
        count == 0 || (count == 2 && bucket == 1), // both values in the low bucket
        `Only two buckets have a sample ${bucket} ${count}`
      );
    }

    var events = Glean.testOnlyIpc.noExtraEvent.testGetValue();
    Assert.equal(1, events.length);
    Assert.equal("test_only.ipc", events[0].category);
    Assert.equal("no_extra_event", events[0].name);

    events = Glean.testOnlyIpc.anEvent.testGetValue();
    Assert.equal(1, events.length);
    Assert.equal("test_only.ipc", events[0].category);
    Assert.equal("an_event", events[0].name);
    Assert.deepEqual(EVENT_EXTRA, events[0].extra);

    const NANOS_IN_MILLIS = 1e6;
    const EPSILON = 40000; // bug 1701949
    const times = Glean.testOnly.whatTimeIsIt.testGetValue();
    Assert.greater(times.sum, 15 * NANOS_IN_MILLIS - EPSILON);
    // We can't guarantee any specific time values (thank you clocks),
    // but we can assert there are only two samples.
    Assert.equal(
      2,
      Object.entries(times.values).reduce(
        (acc, [bucket, count]) => acc + count,
        0
      )
    );

    const mabelsCounters = Glean.testOnly.mabelsKitchenCounters;
    Assert.equal(
      mabelsCounters.near_the_sink.testGetValue(),
      COUNTERS_NEAR_THE_SINK
    );
    Assert.equal(
      mabelsCounters.with_junk_on_them.testGetValue(),
      COUNTERS_WITH_JUNK_ON_THEM
    );

    Assert.throws(
      () => Glean.testOnly.mabelsBathroomCounters.__other__.testGetValue(),
      /DataError/,
      "Invalid labels record errors, which throw"
    );

    Assert.deepEqual(
      { numerator: 44, denominator: 14 },
      Glean.testOnlyIpc.irate.testGetValue()
    );
  }
);