summaryrefslogtreecommitdiffstats
path: root/toolkit/components/utils/test/unit/test_Sampling.js
blob: 6f46182cc580f7ee8a0d26c2dba3b6155acd2e1f (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
"use strict";

ChromeUtils.import(
  "resource://gre/modules/components-utils/Sampling.jsm",
  this
);

add_task(async function testStableSample() {
  // Absolute samples
  equal(
    await Sampling.stableSample("test", 1),
    true,
    "stableSample returns true for 100% sample"
  );
  equal(
    await Sampling.stableSample("test", 0),
    false,
    "stableSample returns false for 0% sample"
  );

  // Known samples. The numbers are nonces to make the tests pass
  equal(
    await Sampling.stableSample("test-0", 0.5),
    true,
    "stableSample returns true for known matching sample"
  );
  equal(
    await Sampling.stableSample("test-1", 0.5),
    false,
    "stableSample returns false for known non-matching sample"
  );
});

add_task(async function testBucketSample() {
  // Absolute samples
  equal(
    await Sampling.bucketSample("test", 0, 10, 10),
    true,
    "bucketSample returns true for 100% sample"
  );
  equal(
    await Sampling.bucketSample("test", 0, 0, 10),
    false,
    "bucketSample returns false for 0% sample"
  );

  // Known samples. The numbers are nonces to make the tests pass
  equal(
    await Sampling.bucketSample("test-0", 0, 5, 10),
    true,
    "bucketSample returns true for known matching sample"
  );
  equal(
    await Sampling.bucketSample("test-1", 0, 5, 10),
    false,
    "bucketSample returns false for known non-matching sample"
  );
});

add_task(async function testRatioSample() {
  // Invalid input
  await Assert.rejects(
    Sampling.ratioSample("test", []),
    /ratios must be at least 1 element long/,
    "ratioSample rejects for a list with no ratios"
  );

  // Absolute samples
  equal(
    await Sampling.ratioSample("test", [1]),
    0,
    "ratioSample returns 0 for a list with only 1 ratio"
  );
  equal(
    await Sampling.ratioSample("test", [0, 0, 1, 0]),
    2,
    "ratioSample returns the only non-zero bucket if all other buckets are zero"
  );

  // Known samples. The numbers are nonces to make the tests pass
  equal(
    await Sampling.ratioSample("test-0", [1, 1]),
    0,
    "ratioSample returns the correct index for known matching sample"
  );
  equal(
    await Sampling.ratioSample("test-1", [1, 1]),
    1,
    "ratioSample returns the correct index for known non-matching sample"
  );
});

add_task(async function testFractionToKey() {
  // Test that results are always 12 character hexadecimal strings.
  const expected_regex = /[0-9a-f]{12}/;
  const count = 100;
  let successes = 0;
  for (let i = 0; i < count; i++) {
    const p = Sampling.fractionToKey(Math.random());
    if (expected_regex.test(p)) {
      successes++;
    }
  }
  equal(successes, count, "fractionToKey makes keys the right length");
});

add_task(async function testTruncatedHash() {
  const expected_regex = /[0-9a-f]{12}/;
  const count = 100;
  let successes = 0;
  for (let i = 0; i < count; i++) {
    const h = await Sampling.truncatedHash(Math.random());
    if (expected_regex.test(h)) {
      successes++;
    }
  }
  equal(successes, count, "truncatedHash makes hashes the right length");
});

add_task(async function testBufferToHex() {
  const data = new ArrayBuffer(4);
  const view = new DataView(data);
  view.setUint8(0, 0xff);
  view.setUint8(1, 0x7f);
  view.setUint8(2, 0x3f);
  view.setUint8(3, 0x1f);
  equal(Sampling.bufferToHex(data), "ff7f3f1f");
});