tor-browser

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

test_throttle.js (4128B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 /* eslint-disable mozilla/use-chromeutils-generateqi */
      7 
      8 const { NetworkThrottleManager } = ChromeUtils.importESModule(
      9  "resource://devtools/shared/network-observer/NetworkThrottleManager.sys.mjs"
     10 );
     11 const nsIScriptableInputStream = Ci.nsIScriptableInputStream;
     12 
     13 class TestStreamListener {
     14  constructor() {
     15    this.state = "initial";
     16  }
     17  onStartRequest() {
     18    this.setState("start");
     19  }
     20 
     21  onStopRequest() {
     22    this.setState("stop");
     23  }
     24 
     25  onDataAvailable(request, inputStream, offset, count) {
     26    const sin = Cc["@mozilla.org/scriptableinputstream;1"].createInstance(
     27      nsIScriptableInputStream
     28    );
     29    sin.init(inputStream);
     30    this.data = sin.read(count);
     31    this.setState("data");
     32  }
     33 
     34  setState(state) {
     35    this.state = state;
     36    if (this._deferred) {
     37      this._deferred.resolve(state);
     38      this._deferred = null;
     39    }
     40  }
     41 
     42  onStateChanged() {
     43    if (!this._deferred) {
     44      let resolve, reject;
     45      const promise = new Promise(function (res, rej) {
     46        resolve = res;
     47        reject = rej;
     48      });
     49      this._deferred = { resolve, reject, promise };
     50    }
     51    return this._deferred.promise;
     52  }
     53 }
     54 
     55 class TestChannel {
     56  constructor() {
     57    this.state = "initial";
     58    this.testListener = new TestStreamListener();
     59    this._throttleQueue = null;
     60  }
     61  QueryInterface() {
     62    return this;
     63  }
     64 
     65  get throttleQueue() {
     66    return this._throttleQueue;
     67  }
     68 
     69  set throttleQueue(q) {
     70    this._throttleQueue = q;
     71    this.state = "throttled";
     72  }
     73 
     74  setNewListener(listener) {
     75    this.listener = listener;
     76    this.state = "listener";
     77    return this.testListener;
     78  }
     79 }
     80 
     81 add_task(async function () {
     82  const throttler = new NetworkThrottleManager({
     83    latencyMean: 1,
     84    latencyMax: 1,
     85    downloadBPSMean: 500,
     86    downloadBPSMax: 500,
     87    uploadBPSMean: 500,
     88    uploadBPSMax: 500,
     89  });
     90 
     91  const uploadChannel = new TestChannel();
     92  throttler.manageUpload(uploadChannel);
     93  equal(
     94    uploadChannel.state,
     95    "throttled",
     96    "NetworkThrottleManager set throttleQueue"
     97  );
     98 
     99  const downloadChannel = new TestChannel();
    100  const testListener = downloadChannel.testListener;
    101 
    102  const listener = throttler.manage(downloadChannel);
    103  equal(
    104    downloadChannel.state,
    105    "listener",
    106    "NetworkThrottleManager called setNewListener"
    107  );
    108 
    109  equal(testListener.state, "initial", "test listener in initial state");
    110 
    111  // This method must be passed through immediately.
    112  listener.onStartRequest(null);
    113  equal(testListener.state, "start", "test listener started");
    114 
    115  const TEST_INPUT = "hi bob";
    116 
    117  const testStream = Cc["@mozilla.org/storagestream;1"].createInstance(
    118    Ci.nsIStorageStream
    119  );
    120  testStream.init(512, 512);
    121  const out = testStream.getOutputStream(0);
    122  out.write(TEST_INPUT, TEST_INPUT.length);
    123  out.close();
    124  const testInputStream = testStream.newInputStream(0);
    125 
    126  const activityDistributor = Cc[
    127    "@mozilla.org/network/http-activity-distributor;1"
    128  ].getService(Ci.nsIHttpActivityDistributor);
    129  let activitySeen = false;
    130  listener.addActivityCallback(
    131    () => {
    132      activitySeen = true;
    133    },
    134    null,
    135    null,
    136    null,
    137    activityDistributor.ACTIVITY_SUBTYPE_RESPONSE_COMPLETE,
    138    null,
    139    TEST_INPUT.length,
    140    null
    141  );
    142 
    143  // onDataAvailable is required to immediately read the data.
    144  listener.onDataAvailable(null, testInputStream, 0, 6);
    145  equal(testInputStream.available(), 0, "no more data should be available");
    146  equal(
    147    testListener.state,
    148    "start",
    149    "test listener should not have received data"
    150  );
    151  equal(activitySeen, false, "activity not distributed yet");
    152 
    153  let newState = await testListener.onStateChanged();
    154  equal(newState, "data", "test listener received data");
    155  equal(testListener.data, TEST_INPUT, "test listener received all the data");
    156  equal(activitySeen, true, "activity has been distributed");
    157 
    158  const onChange = testListener.onStateChanged();
    159  listener.onStopRequest(null, null);
    160  newState = await onChange;
    161  equal(newState, "stop", "onStateChanged reported");
    162 });