Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  test_GIFFT.js   Sprache: JAVA

 
/* 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"
);
const { TelemetryTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/TelemetryTestUtils.sys.mjs"
);

const Telemetry = Services.telemetry;

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

function scalarValue(aScalarName) {
  let snapshot = Telemetry.getSnapshotForScalars();
  return "parent" in snapshot ? snapshot.parent[aScalarName] : undefined;
}

function keyedScalarValue(aScalarName) {
  let snapshot = Telemetry.getSnapshotForKeyedScalars();
  return "parent" in snapshot ? snapshot.parent[aScalarName] : undefined;
}

add_setup(function test_setup() {
  // FOG needs a profile directory to put its data in.
  do_get_profile();

  Services.prefs.setBoolPref(
    "toolkit.telemetry.testing.overrideProductsCheck",
    true
  );

  // We need to initialize it once, otherwise operations will be stuck in the pre-init queue.
  // On Android FOG is set up through head.js.
  if (AppConstants.platform != "android") {
    Services.fog.initializeFOG();
  }
});

add_task(function test_gifft_counter() {
  Glean.testOnlyIpc.aCounter.add(20);
  Assert.equal(20, Glean.testOnlyIpc.aCounter.testGetValue());
  let telemetryValue = scalarValue("telemetry.test.mirror_for_counter");
  Assert.equal(20, telemetryValue);
  Assert.equal("number"typeof telemetryValue);

  Glean.testOnlyIpc.aCounterForHgram.add(20);
  Assert.equal(20, Glean.testOnlyIpc.aCounterForHgram.testGetValue());
  const data = Telemetry.getHistogramById("TELEMETRY_TEST_COUNT").snapshot();
  const expected = {
    bucket_count: 3,
    histogram_type: 4,
    sum: 20,
    range: [1, 2],
    values: { 0: 1, 1: 0 },
  };
  Assert.deepEqual(data, expected, "histogram successfully mirrored-to.");
});

add_task(function test_gifft_boolean() {
  Glean.testOnlyIpc.aBool.set(false);
  Assert.equal(false, Glean.testOnlyIpc.aBool.testGetValue());
  let telemetryValue = scalarValue("telemetry.test.boolean_kind");
  Assert.equal(false, telemetryValue);
  Assert.equal("boolean"typeof telemetryValue);
});

add_task(function test_gifft_datetime() {
  const dateStr = "2021-03-22T16:06:00";
  const value = new Date(dateStr);
  Glean.testOnlyIpc.aDate.set(value.getTime() * 1000);

  let received = Glean.testOnlyIpc.aDate.testGetValue();
  Assert.equal(value.getTime(), received.getTime());
  Assert.ok(scalarValue("telemetry.test.mirror_for_date").startsWith(dateStr));
});

add_task(function test_gifft_string() {
  const value = "a string!";
  Glean.testOnlyIpc.aString.set(value);

  Assert.equal(value, Glean.testOnlyIpc.aString.testGetValue());
  let telemetryValue = scalarValue("telemetry.test.multiple_stores_string");
  Assert.equal(value, telemetryValue);
  Assert.equal("string"typeof telemetryValue);
});

add_task(function test_gifft_memory_dist() {
  Glean.testOnlyIpc.aMemoryDist.accumulate(7);
  Glean.testOnlyIpc.aMemoryDist.accumulate(17);

  let data = Glean.testOnlyIpc.aMemoryDist.testGetValue();
  // `data.sum` is in bytes, but the metric is in KB.
  Assert.equal(24 * 1024, data.sum, "Sum's correct");
  for (let [bucket, count] of Object.entries(data.values)) {
    Assert.ok(
      count == 0 || (count == 1 && (bucket == 6888 || bucket == 17109)),
      `Only two buckets have a sample ${bucket} ${count}`
    );
  }

  data = Telemetry.getHistogramById("TELEMETRY_TEST_LINEAR").snapshot();
  Telemetry.getHistogramById("TELEMETRY_TEST_LINEAR").clear();
  Assert.equal(24, data.sum, "Histogram's in `memory_unit` units");
  Assert.equal(2, data.values["1"], "Both samples in a low bucket");

  // MemoryDistribution's Accumulate method to takes
  // a platform specific type (size_t).
  // Glean's, however, is i64, and, glean_memory_dist is uint64_t
  // What happens when we give accumulate dubious values?
  // This may occur on some uncommon platforms.
  // Note: there are issues in JS with numbers above 2**53
  Glean.testOnlyIpc.aMemoryDist.accumulate(36893488147419103232);
  let dubiousValue = Object.entries(
    Glean.testOnlyIpc.aMemoryDist.testGetValue().values
  )[0][1];
  Assert.equal(
    dubiousValue,
    1,
    "Greater than 64-Byte number did not accumulate correctly"
  );

  // Values lower than the out-of-range value are not clamped
  // resulting in an exception being thrown from the glean side
  // when the value exceeds the glean maximum allowed value
  Glean.testOnlyIpc.aMemoryDist.accumulate(Math.pow(2, 31));
  Assert.throws(
    () => Glean.testOnlyIpc.aMemoryDist.testGetValue(),
    /DataError/,
    "Did not accumulate correctly"
  );
});

add_task(function test_gifft_custom_dist() {
  Glean.testOnlyIpc.aCustomDist.accumulateSamples([7, 268435458]);

  let data = Glean.testOnlyIpc.aCustomDist.testGetValue();
  Assert.equal(7 + 268435458, data.sum, "Sum's correct");
  for (let [bucket, count] of Object.entries(data.values)) {
    Assert.ok(
      count == 0 || (count == 1 && (bucket == 1 || bucket == 268435456)),
      `Only two buckets have a sample ${bucket} ${count}`
    );
  }

  data = Telemetry.getHistogramById(
    "TELEMETRY_TEST_MIRROR_FOR_CUSTOM"
  ).snapshot();
  Telemetry.getHistogramById("TELEMETRY_TEST_MIRROR_FOR_CUSTOM").clear();
  Assert.equal(7 + 268435458, data.sum, "Sum in histogram is correct");
  Assert.equal(1, data.values["1"], "One sample in the low bucket");
  // Yes, the bucket is off-by-one compared to Glean.
  Assert.equal(1, data.values["268435457"], "One sample in the next bucket");
});

add_task(async function test_gifft_timing_dist() {
  let t1 = Glean.testOnlyIpc.aTimingDist.start();
  // Interleave some other metric's samples. bug 1768636.
  let ot1 = Glean.testOnly.whatTimeIsIt.start();
  let t2 = Glean.testOnlyIpc.aTimingDist.start();
  let ot2 = Glean.testOnly.whatTimeIsIt.start();
  Glean.testOnly.whatTimeIsIt.cancel(ot1);
  Glean.testOnly.whatTimeIsIt.cancel(ot2);

  await sleep(5);

  let t3 = Glean.testOnlyIpc.aTimingDist.start();
  Glean.testOnlyIpc.aTimingDist.cancel(t1);

  await sleep(5);

  Glean.testOnlyIpc.aTimingDist.stopAndAccumulate(t2); // 10ms
  Glean.testOnlyIpc.aTimingDist.stopAndAccumulate(t3); // 5ms

  let data = Glean.testOnlyIpc.aTimingDist.testGetValue();
  const NANOS_IN_MILLIS = 1e6;
  // bug 1701949 - Sleep gets close, but sometimes doesn't wait long enough.
  const EPSILON = 40000;

  // Variance in timing makes getting the sum impossible to know.
  // 10 and 5 input value can be trunacted to 4. + 9. >= 13. from cast
  Assert.greater(data.sum, 13 * NANOS_IN_MILLIS - EPSILON);

  // 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, [, count]) => acc + count, 0),
    "Only two buckets with samples"
  );

  data = Telemetry.getHistogramById("TELEMETRY_TEST_EXPONENTIAL").snapshot();
  Assert.greaterOrEqual(
    data.sum,
    13 * NANOS_IN_MILLIS - EPSILON,
    "Histogram's in nanos"
  );
  Assert.equal(
    2,
    Object.entries(data.values).reduce((acc, [, count]) => acc + count, 0),
    "Only two samples"
  );

  // How about those raw sample APIs?
  Glean.testOnly.whatTimeIsIt.accumulateSingleSample(42);
  Glean.testOnly.whatTimeIsIt.accumulateSamples([255, 2047]);
  data = Glean.testOnly.whatTimeIsIt.testGetValue();
  Assert.equal(
    data.sum,
    (42 + 255 + 2047) * 1000,
    "test.only.what_time_is_it is in microseconds and testGetValue returns you nanos."
  );

  data = Telemetry.getHistogramById(
    "TELEMETRY_TEST_MIRROR_FOR_TIMING"
  ).snapshot();
  Assert.equal(
    data.sum,
    42 + 255 + 2047,
    "Telemetry gives back exactly what's put in."
  );
});

add_task(function test_gifft_string_list_works() {
  const value = "a string!";
  const value2 = "another string!";
  const value3 = "yet another string.";

  // `set` doesn't work in the mirror, so use `add`
  Glean.testOnlyIpc.aStringList.add(value);
  Glean.testOnlyIpc.aStringList.add(value2);
  Glean.testOnlyIpc.aStringList.add(value3);

  let val = Glean.testOnlyIpc.aStringList.testGetValue();
  // Note: This is incredibly fragile and will break if we ever rearrange items
  // in the string list.
  Assert.deepEqual([value, value2, value3], val);

  val = keyedScalarValue("telemetry.test.keyed_boolean_kind");
  // This too may be fragile.
  Assert.deepEqual(
    {
      [value]: true,
      [value2]: true,
      [value3]: true,
    },
    val
  );
});

add_task(function test_gifft_events() {
  Glean.testOnlyIpc.noExtraEvent.record();
  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);

  let extra = {
    value: "a value for Telemetry",
    extra1: "can set extras",
    extra2: "passing more data",
  };
  // Since `value` will be stripped and used for the value in the Legacy Telemetry API, we need
  // a copy without it in order to test with `assertEvents` later.
  let { extra1, extra2 } = extra;
  let telExtra = { extra1, extra2 };
  Glean.testOnlyIpc.anEvent.record(extra);
  // Also test a value of "".
  Glean.testOnlyIpc.anEvent.record({ value: "" });
  events = Glean.testOnlyIpc.anEvent.testGetValue();
  Assert.equal(2, events.length);
  Assert.equal("test_only.ipc", events[0].category);
  Assert.equal("an_event", events[0].name);
  Assert.deepEqual(extra, events[0].extra);

  TelemetryTestUtils.assertEvents(
    [
      ["telemetry.test""not_expired_optout""object1", undefined, undefined],
      ["telemetry.test""mirror_with_extra""object1", extra.value, telExtra],
      ["telemetry.test""mirror_with_extra""object1""", undefined],
    ],
    { category: "telemetry.test" }
  );
});

add_task(function test_gifft_uuid() {
  const kTestUuid = "decafdec-afde-cafd-ecaf-decafdecafde";
  Glean.testOnlyIpc.aUuid.set(kTestUuid);
  Assert.equal(kTestUuid, Glean.testOnlyIpc.aUuid.testGetValue());
  Assert.equal(kTestUuid, scalarValue("telemetry.test.string_kind"));
});

add_task(function test_gifft_labeled_counter() {
  Assert.equal(
    undefined,
    Glean.testOnlyIpc.aLabeledCounter.a_label.testGetValue(),
    "New labels with no values should return undefined"
  );
  Glean.testOnlyIpc.aLabeledCounter.a_label.add(1);
  Glean.testOnlyIpc.aLabeledCounter.another_label.add(2);
  Glean.testOnlyIpc.aLabeledCounter.a_label.add(3);
  Assert.equal(4, Glean.testOnlyIpc.aLabeledCounter.a_label.testGetValue());
  Assert.equal(
    2,
    Glean.testOnlyIpc.aLabeledCounter.another_label.testGetValue()
  );
  // What about invalid/__other__?
  Assert.equal(
    undefined,
    Glean.testOnlyIpc.aLabeledCounter.__other__.testGetValue()
  );
  Glean.testOnlyIpc.aLabeledCounter["1".repeat(72)].add(3);
  Assert.throws(
    () => Glean.testOnlyIpc.aLabeledCounter.__other__.testGetValue(),
    /DataError/,
    "Can't get the value when you're error'd"
  );

  let value = keyedScalarValue(
    "telemetry.test.another_mirror_for_labeled_counter"
  );
  Assert.deepEqual(
    {
      a_label: 4,
      another_label: 2,
      ["1".repeat(72)]: 3,
    },
    value
  );

  // What about a labeled_counter that maps to a boolean hgram?
  Assert.equal(
    undefined,
    Glean.testOnlyIpc.aLabeledCounterForHgram.true.testGetValue()
  );
  Assert.equal(
    undefined,
    Glean.testOnlyIpc.aLabeledCounterForHgram.false.testGetValue()
  );

  Glean.testOnlyIpc.aLabeledCounterForHgram.true.add(1);
  Glean.testOnlyIpc.aLabeledCounterForHgram.true.add(1);
  Glean.testOnlyIpc.aLabeledCounterForHgram.false.add(1);

  Assert.equal(
    2,
    Glean.testOnlyIpc.aLabeledCounterForHgram.true.testGetValue()
  );
  Assert.equal(
    1,
    Glean.testOnlyIpc.aLabeledCounterForHgram.false.testGetValue()
  );

  value = Telemetry.getHistogramById("TELEMETRY_TEST_BOOLEAN");
  Assert.deepEqual(
    {
      bucket_count: 3,
      histogram_type: 2,
      sum: 2,
      range: [1, 2],
      values: { 0: 1, 1: 2, 2: 0 },
    },
    value.snapshot()
  );

  // What about a labeled_counter that maps to a keyed count hgram?
  Assert.equal(
    undefined,
    Glean.testOnlyIpc.aLabeledCounterForKeyedCountHgram.aLabel.testGetValue()
  );
  Assert.equal(
    undefined,
    Glean.testOnlyIpc.aLabeledCounterForKeyedCountHgram.anotherLabel.testGetValue()
  );

  Glean.testOnlyIpc.aLabeledCounterForKeyedCountHgram.aLabel.add(2);
  Glean.testOnlyIpc.aLabeledCounterForKeyedCountHgram.anotherLabel.add(1);

  Assert.equal(
    2,
    Glean.testOnlyIpc.aLabeledCounterForKeyedCountHgram.aLabel.testGetValue()
  );
  Assert.equal(
    1,
    Glean.testOnlyIpc.aLabeledCounterForKeyedCountHgram.anotherLabel.testGetValue()
  );

  value = Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_COUNT");
  Assert.deepEqual(
    {
      aLabel: {
        bucket_count: 3,
        histogram_type: 4,
        sum: 2,
        range: [1, 2],
        values: { 0: 1, 1: 0 },
      },
      anotherLabel: {
        bucket_count: 3,
        histogram_type: 4,
        sum: 1,
        range: [1, 2],
        values: { 0: 1, 1: 0 },
      },
    },
    value.snapshot()
  );

  // What about a labeled_counter that maps to a categorical hgram?
  Assert.equal(
    undefined,
    Glean.testOnlyIpc.aLabeledCounterForCategorical.CommonLabel.testGetValue()
  );
  Assert.equal(
    undefined,
    Glean.testOnlyIpc.aLabeledCounterForCategorical.Label4.testGetValue()
  );

  Glean.testOnlyIpc.aLabeledCounterForCategorical.CommonLabel.add(1);
  Glean.testOnlyIpc.aLabeledCounterForCategorical.Label4.add(1);

  Assert.equal(
    1,
    Glean.testOnlyIpc.aLabeledCounterForCategorical.CommonLabel.testGetValue()
  );
  Assert.equal(
    1,
    Glean.testOnlyIpc.aLabeledCounterForCategorical.Label4.testGetValue()
  );

  value = Telemetry.getHistogramById("TELEMETRY_TEST_CATEGORICAL_OPTOUT");
  Assert.deepEqual(
    {
      bucket_count: 51,
      histogram_type: 5,
      sum: 1,
      range: [1, 50],
      values: { 0: 1, 1: 1, 2: 0 },
    },
    value.snapshot()
  );
});

add_task(async function test_gifft_timespan() {
  // We start, briefly sleep and then stop.
  // That guarantees some time to measure.
  Glean.testOnly.mirrorTime.start();
  await sleep(10);
  Glean.testOnly.mirrorTime.stop();

  const NANOS_IN_MILLIS = 1e6;
  // bug 1931539 - Sleep gets close, but sometimes doesn't wait long enough.
  const EPSILON = 50000;
  Assert.greater(
    Glean.testOnly.mirrorTime.testGetValue(),
    10 * NANOS_IN_MILLIS - EPSILON
  );
  // Mirrored to milliseconds.
  Assert.greaterOrEqual(scalarValue("telemetry.test.mirror_for_timespan"), 9);
});

add_task(async function test_gifft_timespan_raw() {
  Glean.testOnly.mirrorTimeNanos.setRaw(15 /*ns*/);

  Assert.equal(15, Glean.testOnly.mirrorTimeNanos.testGetValue());
  // setRaw, unlike start/stop, mirrors the raw value directly.
  Assert.equal(scalarValue("telemetry.test.mirror_for_timespan_nanos"), 15);
});

add_task(async function test_gifft_labeled_boolean() {
  Assert.equal(
    undefined,
    Glean.testOnly.mirrorsForLabeledBools.a_label.testGetValue(),
    "New labels with no values should return undefined"
  );
  Glean.testOnly.mirrorsForLabeledBools.a_label.set(true);
  Glean.testOnly.mirrorsForLabeledBools.another_label.set(false);
  Assert.equal(
    true,
    Glean.testOnly.mirrorsForLabeledBools.a_label.testGetValue()
  );
  Assert.equal(
    false,
    Glean.testOnly.mirrorsForLabeledBools.another_label.testGetValue()
  );
  // What about invalid/__other__?
  Assert.equal(
    undefined,
    Glean.testOnly.mirrorsForLabeledBools.__other__.testGetValue()
  );
  Glean.testOnly.mirrorsForLabeledBools["1".repeat(72)].set(true);
  Assert.throws(
    () => Glean.testOnly.mirrorsForLabeledBools.__other__.testGetValue(),
    /DataError/,
    "Should throw because of a recording error."
  );

  // In Telemetry there is no invalid label
  let value = keyedScalarValue("telemetry.test.mirror_for_labeled_bool");
  Assert.deepEqual(
    {
      a_label: true,
      another_label: false,
      ["1".repeat(72)]: true,
    },
    value
  );
});

add_task(function test_gifft_boolean() {
  Glean.testOnly.meaningOfLife.set(42);
  Assert.equal(42, Glean.testOnly.meaningOfLife.testGetValue());
  Assert.equal(42, scalarValue("telemetry.test.mirror_for_quantity"));
});

add_task(function test_gifft_rate() {
  Glean.testOnlyIpc.irate.addToNumerator(22);
  Glean.testOnlyIpc.irate.addToDenominator(7);
  Assert.deepEqual(
    { numerator: 22, denominator: 7 },
    Glean.testOnlyIpc.irate.testGetValue()
  );
  Assert.deepEqual(
    { numerator: 22, denominator: 7 },
    keyedScalarValue("telemetry.test.mirror_for_rate")
  );
});

add_task(function test_gifft_numeric_limits() {
  // Glean and Telemetry don't share the same storage sizes or signedness.
  // Check the edges.

  // 0) Reset everything
  Services.fog.testResetFOG();
  Services.telemetry.getSnapshotForHistograms("main"true /* aClearStore */);
  Services.telemetry.getSnapshotForScalars("main"true /* aClearStore */);
  Services.telemetry.getSnapshotForKeyedScalars("main"true /* aClearStore */);

  // 1) Counter: i32 (saturates), mirrored to uint Scalar: u32 (overflows)
  // 1.1) Negative parameters refused.
  Glean.testOnlyIpc.aCounter.add(-20);
  // Unfortunately we can't check what the error was, due to API design.
  // (chutten blames chutten for his shortsightedness)
  Assert.throws(
    () => Glean.testOnlyIpc.aCounter.testGetValue(),
    /DataError/,
    "Can't get the value when you're error'd"
  );
  Assert.equal(undefined, scalarValue("telemetry.test.mirror_for_counter"));
  // Clear the error state
  Services.fog.testResetFOG();

  // 1.2) Values that sum larger than u32::max saturate (counter) and overflow (Scalar)
  // Sums to 2^32 + 1
  Glean.testOnlyIpc.aCounter.add(Math.pow(2, 31) - 1);
  Glean.testOnlyIpc.aCounter.add(1);
  Glean.testOnlyIpc.aCounter.add(Math.pow(2, 31) - 1);
  Glean.testOnlyIpc.aCounter.add(2);
  // Glean doesn't actually throw on saturation (bug 1751469),
  // so we can just check the saturation value.
  Assert.equal(Math.pow(2, 31) - 1, Glean.testOnlyIpc.aCounter.testGetValue());
  // Telemetry will have wrapped around to 1
  Assert.equal(1, scalarValue("telemetry.test.mirror_for_counter"));

  // 2) Quantity: i64 (saturates), mirrored to uint Scalar: u32 (overflows)
  // 2.1) Negative parameters refused.
  Glean.testOnly.meaningOfLife.set(-42);
  // Glean will error on this.
  Assert.throws(
    () => Glean.testOnly.meaningOfLife.testGetValue(),
    /DataError/,
    "Can't get the value when you're error'd"
  );
  // GIFFT doesn't tell Telemetry about the weird value at all.
  Assert.equal(undefined, scalarValue("telemetry.test.mirror_for_quantity"));
  // Clear the error state
  Services.fog.testResetFOG();

  // 2.2) A parameter larger than u32::max is passed to Glean unchanged,
  //      but is clamped to u32::max before being passed to Telemetry.
  Glean.testOnly.meaningOfLife.set(Math.pow(2, 32));
  Assert.equal(Math.pow(2, 32), Glean.testOnly.meaningOfLife.testGetValue());
  Assert.equal(
    Math.pow(2, 32) - 1,
    scalarValue("telemetry.test.mirror_for_quantity")
  );

  // 3) Rate: two i32 (saturates), mirrored to keyed uint Scalar: u32s (overflow)
  // 3.1) Negative parameters refused.
  Glean.testOnlyIpc.irate.addToNumerator(-22);
  Glean.testOnlyIpc.irate.addToDenominator(7);
  Assert.throws(
    () => Glean.testOnlyIpc.irate.testGetValue(),
    /DataError/,
    "Can't get the value when you're error'd"
  );
  Assert.deepEqual(
    { denominator: 7 },
    keyedScalarValue("telemetry.test.mirror_for_rate")
  );
  // Clear the error state
  Services.fog.testResetFOG();
  // Clear the partial Telemetry value
  Services.telemetry.getSnapshotForKeyedScalars("main"true /* aClearStore */);

  // Now the denominator:
  Glean.testOnlyIpc.irate.addToNumerator(22);
  Glean.testOnlyIpc.irate.addToDenominator(-7);
  Assert.throws(
    () => Glean.testOnlyIpc.irate.testGetValue(),
    /DataError/,
    "Can't get the value when you're error'd"
  );
  Assert.deepEqual(
    { numerator: 22 },
    keyedScalarValue("telemetry.test.mirror_for_rate")
  );

  // 4) Timespan
  // ( Can't overflow time without finding a way to get TimeStamp to think
  // we're 2^32 milliseconds later without waiting a month )

  // 5) TimingDistribution
  // ( Can't overflow time with start() and stopAndAccumulate() without
  // waiting for ages. But we _do_ have a test-only raw API...)
  // The max sample for timing_distribution is 600000000000.
  // The type for timing_distribution samples is i64.
  // This means when we explore the edges of GIFFT's limits, we're well past
  // Glean's limits. All we can get out of Glean is errors.
  // (Which is good for data, difficult for tests.)
  // But GIFFT should properly saturate in Telemetry at i32::max,
  // so we shall test that.
  Glean.testOnlyIpc.aTimingDist.testAccumulateRawMillis(Math.pow(2, 31) + 1);
  Glean.testOnlyIpc.aTimingDist.testAccumulateRawMillis(Math.pow(2, 32) + 1);
  Assert.throws(
    () => Glean.testOnlyIpc.aTimingDist.testGetValue(),
    /DataError/,
    "Can't get the value when you're error'd"
  );
  let snapshot = Telemetry.getHistogramById(
    "TELEMETRY_TEST_EXPONENTIAL"
  ).snapshot();
  Assert.equal(
    snapshot.values["2147483646"],
    2,
    "samples > i32::max should end up in the top bucket"
  );
});

add_task(function test_gifft_url() {
  const value = "https://www.example.com";
  Glean.testOnlyIpc.aUrl.set(value);

  Assert.equal(value, Glean.testOnlyIpc.aUrl.testGetValue());
  Assert.equal(value, scalarValue("telemetry.test.mirror_for_url"));
});

add_task(function test_gifft_url_cropped() {
  const value = `https://example.com${"/test".repeat(47)}`;
  Glean.testOnlyIpc.aUrl.set(value);

  Assert.equal(value, Glean.testOnlyIpc.aUrl.testGetValue());
  // We expect the mirrored URL to be truncated at the maximum
  // length supported by string scalars.
  Assert.equal(
    value.substring(0, 50),
    scalarValue("telemetry.test.mirror_for_url")
  );
});

add_task(function test_gifft_labeled_custom_dist() {
  Glean.testOnly.mabelsCustomLabelLengths.rubbermaid.accumulateSamples([
    7, 268435458,
  ]);

  let data = Glean.testOnly.mabelsCustomLabelLengths.rubbermaid.testGetValue();
  Assert.equal(7 + 268435458, data.sum, "Sum's correct");
  for (let [bucket, count] of Object.entries(data.values)) {
    Assert.ok(
      count == 0 || (count == 1 && (bucket == 1 || bucket == 268435456)),
      `Only two buckets have a sample ${bucket} ${count}`
    );
  }

  data = Telemetry.getKeyedHistogramById(
    "TELEMETRY_TEST_KEYED_LINEAR"
  ).snapshot();
  Telemetry.getKeyedHistogramById("TELEMETRY_TEST_KEYED_LINEAR").clear();
  Assert.ok("rubbermaid" in data, "Mirror has key");
  Assert.equal(
    7 + 268435458,
    data.rubbermaid.sum,
    "Sum in histogram is correct"
  );
  Assert.equal(1, data.rubbermaid.values["1"], "One sample in the low bucket");
  Assert.equal(
    1,
    data.rubbermaid.values["250000"],
    "One sample in the high bucket"
  );
});

add_task(function test_gifft_labeled_memory_dist() {
  Glean.testOnly.whatDoYouRemember.childhood.accumulate(7);
  Glean.testOnly.whatDoYouRemember.childhood.accumulate(17);

  let data = Glean.testOnly.whatDoYouRemember.childhood.testGetValue();
  // `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 == 7053950 || bucket == 17520006)),
      `Only two buckets have a sample ${bucket} ${count}`
    );
  }

  data = Telemetry.getKeyedHistogramById(
    "TELEMETRY_TEST_MIRROR_FOR_LABELED_MEMORY"
  ).snapshot();
  Telemetry.getKeyedHistogramById(
    "TELEMETRY_TEST_MIRROR_FOR_LABELED_MEMORY"
  ).clear();
  Assert.ok("childhood" in data, "Key's present");
  Assert.equal(24, data.childhood.sum, "Histogram's in `memory_unit` units");
  Assert.equal(2, data.childhood.values["1"], "Both samples in a low bucket");
});

add_task(async function test_gifft_labeled_timing_dist() {
  let t1 = Glean.testOnly.whereHasTheTimeGone["down the drain"].start();
  let t2 = Glean.testOnly.whereHasTheTimeGone["down the drain"].start();

  await sleep(5);

  let t3 = Glean.testOnly.whereHasTheTimeGone["down the drain"].start();
  Glean.testOnly.whereHasTheTimeGone["down the drain"].cancel(t1);

  await sleep(5);

  Glean.testOnly.whereHasTheTimeGone["down the drain"].stopAndAccumulate(t2); // 10ms
  Glean.testOnly.whereHasTheTimeGone["down the drain"].stopAndAccumulate(t3); // 5ms

  let data =
    Glean.testOnly.whereHasTheTimeGone["down the drain"].testGetValue();
  const NANOS_IN_MILLIS = 1e6;
  // bug 1701949 - Sleep gets close, but sometimes doesn't wait long enough.
  const EPSILON = 40000;

  // Variance in timing makes getting the sum impossible to know.
  // 10 and 5 input value can be trunacted to 4. + 9. >= 13. from cast
  Assert.greater(data.sum, 13 * NANOS_IN_MILLIS - EPSILON);

  // 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, [, count]) => acc + count, 0),
    "Only two buckets with samples"
  );

  data = Telemetry.getKeyedHistogramById(
    "TELEMETRY_TEST_MIRROR_FOR_LABELED_TIMING"
  ).snapshot();
  Assert.ok("down the drain" in data, "Has the key");
  data = data["down the drain"];
  // Suffers from same cast truncation issue of 9.... and 4.... values
  Assert.greaterOrEqual(data.sum, 13, "Histogram's in milliseconds");
  Assert.equal(
    2,
    Object.entries(data.values).reduce((acc, [, count]) => acc + count, 0),
    "Only two samples"
  );

  // Note that `labeled_timing_distribution` does not mirror calls to
  // * accumulateSamples
  // * accumulateSingleSamples
  // See bug 1943453 for more details.
  Glean.testOnly.whereHasTheTimeGone["hourglass sands"].accumulateSamples([
    1, 2, 3,
  ]);
  Glean.testOnly.whereHasTheTimeGone["hourglass sands"].accumulateSingleSample(
    1
  );

  data = Telemetry.getKeyedHistogramById(
    "TELEMETRY_TEST_MIRROR_FOR_LABELED_TIMING"
  ).snapshot();
  Assert.ok(!("hourglass sands" in data), "Doesn't have the key");
});

add_task(async function test_gifft_labeled_quantity() {
  Assert.equal(
    undefined,
    Glean.testOnly.buttonJars.pants.testGetValue(),
    "New labels with no values should return undefined"
  );
  Glean.testOnly.buttonJars.pants.set(42);
  Glean.testOnly.buttonJars.whoseGot.set(1);
  Assert.equal(42, Glean.testOnly.buttonJars.pants.testGetValue());
  Assert.equal(1, Glean.testOnly.buttonJars.whoseGot.testGetValue());
  // What about invalid/__other__?
  Assert.equal(undefined, Glean.testOnly.buttonJars.__other__.testGetValue());
  Glean.testOnly.buttonJars["1".repeat(72)].set(9000);
  Assert.throws(
    () => Glean.testOnly.buttonJars.__other__.testGetValue(),
    /DataError/,
    "Should throw because of a recording error."
  );

  info(JSON.stringify(Telemetry.getSnapshotForKeyedScalars()));
  // In Telemetry there is no invalid label
  let value = keyedScalarValue("telemetry.test.mirror_for_labeled_quantity");
  Assert.deepEqual(
    {
      pants: 42,
      whoseGot: 1,
      ["1".repeat(72)]: 9000,
    },
    value
  );
});

Messung V0.5
C=87 H=88 G=87

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge