tor-browser

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

test_errorhandler_sync_checkServerError.js (7994B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 const { Service } = ChromeUtils.importESModule(
      5  "resource://services-sync/service.sys.mjs"
      6 );
      7 const { Status } = ChromeUtils.importESModule(
      8  "resource://services-sync/status.sys.mjs"
      9 );
     10 const { FakeCryptoService } = ChromeUtils.importESModule(
     11  "resource://testing-common/services/sync/fakeservices.sys.mjs"
     12 );
     13 
     14 var engineManager = Service.engineManager;
     15 
     16 function CatapultEngine() {
     17  SyncEngine.call(this, "Catapult", Service);
     18 }
     19 CatapultEngine.prototype = {
     20  exception: null, // tests fill this in
     21  async _sync() {
     22    throw this.exception;
     23  },
     24 };
     25 Object.setPrototypeOf(CatapultEngine.prototype, SyncEngine.prototype);
     26 
     27 async function sync_httpd_setup() {
     28  let collectionsHelper = track_collections_helper();
     29  let upd = collectionsHelper.with_updated_collection;
     30 
     31  let catapultEngine = engineManager.get("catapult");
     32  let syncID = await catapultEngine.resetLocalSyncID();
     33  let engines = { catapult: { version: catapultEngine.version, syncID } };
     34 
     35  // Track these using the collections helper, which keeps modified times
     36  // up-to-date.
     37  let clientsColl = new ServerCollection({}, true);
     38  let keysWBO = new ServerWBO("keys");
     39  let globalWBO = new ServerWBO("global", {
     40    storageVersion: STORAGE_VERSION,
     41    syncID: Utils.makeGUID(),
     42    engines,
     43  });
     44 
     45  let handlers = {
     46    "/1.1/johndoe/info/collections": collectionsHelper.handler,
     47    "/1.1/johndoe/storage/meta/global": upd("meta", globalWBO.handler()),
     48    "/1.1/johndoe/storage/clients": upd("clients", clientsColl.handler()),
     49    "/1.1/johndoe/storage/crypto/keys": upd("crypto", keysWBO.handler()),
     50  };
     51  return httpd_setup(handlers);
     52 }
     53 
     54 async function setUp(server) {
     55  await configureIdentity({ username: "johndoe" }, server);
     56  new FakeCryptoService();
     57  syncTestLogging();
     58 }
     59 
     60 async function generateAndUploadKeys(server) {
     61  await generateNewKeys(Service.collectionKeys);
     62  let serverKeys = Service.collectionKeys.asWBO("crypto", "keys");
     63  await serverKeys.encrypt(Service.identity.syncKeyBundle);
     64  let res = Service.resource(
     65    server.baseURI + "/1.1/johndoe/storage/crypto/keys"
     66  );
     67  return (await serverKeys.upload(res)).success;
     68 }
     69 
     70 add_task(async function setup() {
     71  await engineManager.clear();
     72  validate_all_future_pings();
     73  await engineManager.register(CatapultEngine);
     74 });
     75 
     76 add_task(async function test_backoff500() {
     77  enableValidationPrefs();
     78 
     79  _("Test: HTTP 500 sets backoff status.");
     80  let server = await sync_httpd_setup();
     81  await setUp(server);
     82 
     83  let engine = engineManager.get("catapult");
     84  engine.enabled = true;
     85  engine.exception = { status: 500 };
     86 
     87  try {
     88    Assert.ok(!Status.enforceBackoff);
     89 
     90    // Forcibly create and upload keys here -- otherwise we don't get to the 500!
     91    Assert.ok(await generateAndUploadKeys(server));
     92 
     93    await Service.login();
     94    await Service.sync();
     95    Assert.ok(Status.enforceBackoff);
     96    Assert.equal(Status.sync, SYNC_SUCCEEDED);
     97    Assert.equal(Status.service, SYNC_FAILED_PARTIAL);
     98  } finally {
     99    Status.resetBackoff();
    100    await Service.startOver();
    101  }
    102  await promiseStopServer(server);
    103 });
    104 
    105 add_task(async function test_backoff503() {
    106  enableValidationPrefs();
    107 
    108  _(
    109    "Test: HTTP 503 with Retry-After header leads to backoff notification and sets backoff status."
    110  );
    111  let server = await sync_httpd_setup();
    112  await setUp(server);
    113 
    114  const BACKOFF = 42;
    115  let engine = engineManager.get("catapult");
    116  engine.enabled = true;
    117  engine.exception = { status: 503, headers: { "retry-after": BACKOFF } };
    118 
    119  let backoffInterval;
    120  Svc.Obs.add("weave:service:backoff:interval", function (subject) {
    121    backoffInterval = subject;
    122  });
    123 
    124  try {
    125    Assert.ok(!Status.enforceBackoff);
    126 
    127    Assert.ok(await generateAndUploadKeys(server));
    128 
    129    await Service.login();
    130    await Service.sync();
    131 
    132    Assert.ok(Status.enforceBackoff);
    133    Assert.equal(backoffInterval, BACKOFF);
    134    Assert.equal(Status.service, SYNC_FAILED_PARTIAL);
    135    Assert.equal(Status.sync, SERVER_MAINTENANCE);
    136  } finally {
    137    Status.resetBackoff();
    138    Status.resetSync();
    139    await Service.startOver();
    140  }
    141  await promiseStopServer(server);
    142 });
    143 
    144 add_task(async function test_overQuota() {
    145  enableValidationPrefs();
    146 
    147  _("Test: HTTP 400 with body error code 14 means over quota.");
    148  let server = await sync_httpd_setup();
    149  await setUp(server);
    150 
    151  let engine = engineManager.get("catapult");
    152  engine.enabled = true;
    153  engine.exception = {
    154    status: 400,
    155    toString() {
    156      return "14";
    157    },
    158  };
    159 
    160  try {
    161    Assert.equal(Status.sync, SYNC_SUCCEEDED);
    162 
    163    Assert.ok(await generateAndUploadKeys(server));
    164 
    165    await Service.login();
    166    await Service.sync();
    167 
    168    Assert.equal(Status.sync, OVER_QUOTA);
    169    Assert.equal(Status.service, SYNC_FAILED_PARTIAL);
    170  } finally {
    171    Status.resetSync();
    172    await Service.startOver();
    173  }
    174  await promiseStopServer(server);
    175 });
    176 
    177 add_task(async function test_service_networkError() {
    178  enableValidationPrefs();
    179 
    180  _(
    181    "Test: Connection refused error from Service.sync() leads to the right status code."
    182  );
    183  let server = await sync_httpd_setup();
    184  await setUp(server);
    185  await promiseStopServer(server);
    186  // Provoke connection refused.
    187  Service.clusterURL = "http://localhost:12345/";
    188 
    189  try {
    190    Assert.equal(Status.sync, SYNC_SUCCEEDED);
    191 
    192    Service._loggedIn = true;
    193    await Service.sync();
    194 
    195    Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
    196    Assert.equal(Status.service, SYNC_FAILED);
    197  } finally {
    198    Status.resetSync();
    199    await Service.startOver();
    200  }
    201 });
    202 
    203 add_task(async function test_service_offline() {
    204  enableValidationPrefs();
    205 
    206  _(
    207    "Test: Wanting to sync in offline mode leads to the right status code but does not increment the ignorable error count."
    208  );
    209  let server = await sync_httpd_setup();
    210  await setUp(server);
    211 
    212  await promiseStopServer(server);
    213  Services.io.offline = true;
    214  Services.prefs.setBoolPref("network.dns.offline-localhost", false);
    215 
    216  try {
    217    Assert.equal(Status.sync, SYNC_SUCCEEDED);
    218 
    219    Service._loggedIn = true;
    220    await Service.sync();
    221 
    222    Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
    223    Assert.equal(Status.service, SYNC_FAILED);
    224  } finally {
    225    Status.resetSync();
    226    await Service.startOver();
    227  }
    228  Services.io.offline = false;
    229  Services.prefs.clearUserPref("network.dns.offline-localhost");
    230 });
    231 
    232 add_task(async function test_engine_networkError() {
    233  enableValidationPrefs();
    234 
    235  _(
    236    "Test: Network related exceptions from engine.sync() lead to the right status code."
    237  );
    238  let server = await sync_httpd_setup();
    239  await setUp(server);
    240 
    241  let engine = engineManager.get("catapult");
    242  engine.enabled = true;
    243  engine.exception = Components.Exception(
    244    "NS_ERROR_UNKNOWN_HOST",
    245    Cr.NS_ERROR_UNKNOWN_HOST
    246  );
    247 
    248  try {
    249    Assert.equal(Status.sync, SYNC_SUCCEEDED);
    250 
    251    Assert.ok(await generateAndUploadKeys(server));
    252 
    253    await Service.login();
    254    await Service.sync();
    255 
    256    Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
    257    Assert.equal(Status.service, SYNC_FAILED_PARTIAL);
    258  } finally {
    259    Status.resetSync();
    260    await Service.startOver();
    261  }
    262  await promiseStopServer(server);
    263 });
    264 
    265 add_task(async function test_resource_timeout() {
    266  enableValidationPrefs();
    267 
    268  let server = await sync_httpd_setup();
    269  await setUp(server);
    270 
    271  let engine = engineManager.get("catapult");
    272  engine.enabled = true;
    273  // Resource throws this when it encounters a timeout.
    274  engine.exception = Components.Exception(
    275    "Aborting due to channel inactivity.",
    276    Cr.NS_ERROR_NET_TIMEOUT
    277  );
    278 
    279  try {
    280    Assert.equal(Status.sync, SYNC_SUCCEEDED);
    281 
    282    Assert.ok(await generateAndUploadKeys(server));
    283 
    284    await Service.login();
    285    await Service.sync();
    286 
    287    Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
    288    Assert.equal(Status.service, SYNC_FAILED_PARTIAL);
    289  } finally {
    290    Status.resetSync();
    291    await Service.startOver();
    292  }
    293  await promiseStopServer(server);
    294 });