tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_MemoriesDriftDetector.js (6766B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      4 */
      5 
      6 do_get_profile();
      7 ("use strict");
      8 
      9 const { MemoriesDriftDetector } = ChromeUtils.importESModule(
     10  "moz-src:///browser/components/aiwindow/models/memories/MemoriesDriftDetector.sys.mjs"
     11 );
     12 const { MemoriesManager } = ChromeUtils.importESModule(
     13  "moz-src:///browser/components/aiwindow/models/memories/MemoriesManager.sys.mjs"
     14 );
     15 
     16 add_task(function test_computeDriftTriggerFromBaseline_no_data() {
     17  const result = MemoriesDriftDetector.computeDriftTriggerFromBaseline(
     18    [],
     19    [],
     20    {}
     21  );
     22 
     23  Assert.ok(!result.triggered, "No data should not trigger");
     24  Assert.equal(result.jsThreshold, 0, "JS threshold should be 0 with no data");
     25  Assert.equal(
     26    result.surpriseThreshold,
     27    0,
     28    "Surprise threshold should be 0 with no data"
     29  );
     30  Assert.deepEqual(
     31    result.triggeredSessionIds,
     32    [],
     33    "No triggered sessions without data"
     34  );
     35 });
     36 
     37 add_task(function test_computeDriftTriggerFromBaseline_triggers_on_delta() {
     38  /** @type {SessionMetric[]} */
     39  const baselineMetrics = [
     40    {
     41      sessionId: "b1",
     42      jsScore: 0.05,
     43      avgSurprisal: 2,
     44      timestampMs: 1,
     45    },
     46    {
     47      sessionId: "b2",
     48      jsScore: 0.08,
     49      avgSurprisal: 2.5,
     50      timestampMs: 2,
     51    },
     52    {
     53      sessionId: "b3",
     54      jsScore: 0.1,
     55      avgSurprisal: 3,
     56      timestampMs: 3,
     57    },
     58  ];
     59 
     60  // Make delta fairly "spiky" so it's above baseline thresholds.
     61  const deltaMetrics = [
     62    {
     63      sessionId: "d1",
     64      jsScore: 0.5,
     65      avgSurprisal: 6,
     66      timestampMs: 4,
     67    },
     68    {
     69      sessionId: "d2",
     70      jsScore: 0.6,
     71      avgSurprisal: 7,
     72      timestampMs: 5,
     73    },
     74  ];
     75 
     76  const result = MemoriesDriftDetector.computeDriftTriggerFromBaseline(
     77    baselineMetrics,
     78    deltaMetrics,
     79    {
     80      triggerQuantile: 0.8,
     81      evalDeltaCount: 2,
     82    }
     83  );
     84 
     85  Assert.greater(result.jsThreshold, 0, "JS baseline threshold should be > 0");
     86  Assert.greater(
     87    result.surpriseThreshold,
     88    0,
     89    "Surprise baseline threshold should be > 0"
     90  );
     91  Assert.ok(result.triggered, "High delta metrics should trigger drift");
     92  Assert.deepEqual(
     93    result.triggeredSessionIds.sort(),
     94    ["d1", "d2"],
     95    "Both delta sessions should be flagged as triggered"
     96  );
     97 });
     98 
     99 add_task(function test_computeDriftTriggerFromBaseline_no_delta() {
    100  const baselineMetrics = [
    101    {
    102      sessionId: "b1",
    103      jsScore: 0.1,
    104      avgSurprisal: 3,
    105      timestampMs: 1,
    106    },
    107  ];
    108 
    109  const deltaMetrics = [];
    110 
    111  const result = MemoriesDriftDetector.computeDriftTriggerFromBaseline(
    112    baselineMetrics,
    113    deltaMetrics,
    114    {}
    115  );
    116 
    117  Assert.ok(!result.triggered, "No delta metrics should not trigger");
    118  Assert.equal(result.jsThreshold, 0, "JS threshold should be 0 with no data");
    119  Assert.equal(
    120    result.surpriseThreshold,
    121    0,
    122    "Surprise threshold should be 0 with no data"
    123  );
    124  Assert.deepEqual(
    125    result.triggeredSessionIds,
    126    [],
    127    "No triggered sessions without delta metrics"
    128  );
    129 });
    130 
    131 add_task(
    132  function test_computeDriftTriggerFromBaseline_respects_evalDeltaCount() {
    133    const baselineMetrics = [
    134      {
    135        sessionId: "b1",
    136        jsScore: 0.05,
    137        avgSurprisal: 2,
    138        timestampMs: 1,
    139      },
    140      {
    141        sessionId: "b2",
    142        jsScore: 0.08,
    143        avgSurprisal: 2.5,
    144        timestampMs: 2,
    145      },
    146    ];
    147 
    148    // First delta is "spiky", later ones are normal-ish.
    149    const deltaMetrics = [
    150      {
    151        sessionId: "d1",
    152        jsScore: 0.7,
    153        avgSurprisal: 8,
    154        timestampMs: 3,
    155      },
    156      {
    157        sessionId: "d2",
    158        jsScore: 0.06,
    159        avgSurprisal: 2.1,
    160        timestampMs: 4,
    161      },
    162      {
    163        sessionId: "d3",
    164        jsScore: 0.07,
    165        avgSurprisal: 2.2,
    166        timestampMs: 5,
    167      },
    168    ];
    169 
    170    const result = MemoriesDriftDetector.computeDriftTriggerFromBaseline(
    171      baselineMetrics,
    172      // only d2 and d3 should be evaluated (setting evalDeltaCount = 2)
    173      deltaMetrics,
    174      {
    175        triggerQuantile: 0.8,
    176        evalDeltaCount: 2,
    177      }
    178    );
    179 
    180    Assert.ok(
    181      !result.triggered,
    182      "When only the last 2 non-spiky deltas are evaluated, drift should not trigger"
    183    );
    184    Assert.deepEqual(
    185      result.triggeredSessionIds,
    186      [],
    187      "No delta sessions should be flagged when only low scores are considered"
    188    );
    189  }
    190 );
    191 
    192 add_task(function test_computeDriftTriggerFromBaseline_non_spiky_no_trigger() {
    193  const baselineMetrics = [
    194    {
    195      sessionId: "b1",
    196      jsScore: 0.1,
    197      avgSurprisal: 3,
    198      timestampMs: 1,
    199    },
    200    {
    201      sessionId: "b2",
    202      jsScore: 0.12,
    203      avgSurprisal: 3.2,
    204      timestampMs: 2,
    205    },
    206    {
    207      sessionId: "b3",
    208      jsScore: 0.11,
    209      avgSurprisal: 3.1,
    210      timestampMs: 3,
    211    },
    212  ];
    213 
    214  const deltaMetrics = [
    215    {
    216      sessionId: "d1",
    217      jsScore: 0.105,
    218      avgSurprisal: 3.05,
    219      timestampMs: 4,
    220    },
    221    {
    222      sessionId: "d2",
    223      jsScore: 0.115,
    224      avgSurprisal: 3.1,
    225      timestampMs: 5,
    226    },
    227  ];
    228 
    229  const result = MemoriesDriftDetector.computeDriftTriggerFromBaseline(
    230    baselineMetrics,
    231    deltaMetrics,
    232    {
    233      triggerQuantile: 0.9,
    234      evalDeltaCount: 2,
    235    }
    236  );
    237 
    238  Assert.ok(
    239    !result.triggered,
    240    "Delta sessions similar to baseline should not trigger drift"
    241  );
    242  Assert.deepEqual(
    243    result.triggeredSessionIds,
    244    [],
    245    "No sessions should be flagged when deltas match baseline distribution"
    246  );
    247 });
    248 
    249 add_task(async function test_computeHistoryDriftAndTrigger_no_prior_memory() {
    250  const originalGetLastHistoryMemoryTimestamp =
    251    MemoriesManager.getLastHistoryMemoryTimestamp;
    252 
    253  // Force "no previous memory" so computeHistoryDriftSessionMetrics bails out.
    254  MemoriesManager.getLastHistoryMemoryTimestamp = async () => null;
    255 
    256  const result = await MemoriesDriftDetector.computeHistoryDriftAndTrigger({});
    257 
    258  dump(`no_prior_memory result = ${JSON.stringify(result)}\n`);
    259 
    260  Assert.ok(
    261    Array.isArray(result.baselineMetrics),
    262    "baselineMetrics should be an array"
    263  );
    264  Assert.ok(
    265    Array.isArray(result.deltaMetrics),
    266    "deltaMetrics should be an array"
    267  );
    268  Assert.equal(
    269    result.baselineMetrics.length,
    270    0,
    271    "No baseline metrics when there is no prior memory timestamp"
    272  );
    273  Assert.equal(
    274    result.deltaMetrics.length,
    275    0,
    276    "No delta metrics when there is no prior memory timestamp"
    277  );
    278  Assert.ok(
    279    !result.trigger.triggered,
    280    "Trigger should be false when there is no prior memory"
    281  );
    282 
    283  // Restore original implementation.
    284  MemoriesManager.getLastHistoryMemoryTimestamp =
    285    originalGetLastHistoryMemoryTimestamp;
    286 });