~ubuntu-branches/ubuntu/trusty/enigmail/trusty-security

« back to all changes in this revision

Viewing changes to services/sync/tests/unit/head_helpers.js

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2011-08-12 12:25:06 UTC
  • mfrom: (0.12.4 upstream)
  • Revision ID: package-import@ubuntu.com-20110812122506-zko6c7zfexvyg71q
Tags: 2:1.2.1-0ubuntu1
* New upstream release
* Drop fix_install_rdf_xml_errors.diff - fixed upstream
* Refresh port_to_latest_thunderbird.diff
* Add a proper get-orig-source target which pulls the build system from
  lp:~mozillateam/mozilla-build-system/beta, now that we don't have the old
  build-system.tar.gz from xulrunner

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
Cu.import("resource://services-sync/util.js");
2
 
var btoa;
3
 
 
4
 
// initialize nss
5
 
let ch = Cc["@mozilla.org/security/hash;1"].
6
 
         createInstance(Ci.nsICryptoHash);
7
 
 
8
 
let ds = Cc["@mozilla.org/file/directory_service;1"]
9
 
  .getService(Ci.nsIProperties);
10
 
 
11
 
let provider = {
12
 
  getFile: function(prop, persistent) {
13
 
    persistent.value = true;
14
 
    switch (prop) {
15
 
      case "ExtPrefDL":
16
 
        return [ds.get("CurProcD", Ci.nsIFile)];
17
 
      case "ProfD":
18
 
        return ds.get("CurProcD", Ci.nsIFile);
19
 
      case "UHist":
20
 
        let histFile = ds.get("CurProcD", Ci.nsIFile);
21
 
        histFile.append("history.dat");
22
 
        return histFile;
23
 
      default:
24
 
        throw Cr.NS_ERROR_FAILURE;
25
 
    }
26
 
  },
27
 
  QueryInterface: function(iid) {
28
 
    if (iid.equals(Ci.nsIDirectoryServiceProvider) ||
29
 
        iid.equals(Ci.nsISupports)) {
30
 
      return this;
31
 
    }
32
 
    throw Cr.NS_ERROR_NO_INTERFACE;
33
 
  }
34
 
};
35
 
ds.QueryInterface(Ci.nsIDirectoryService).registerProvider(provider);
36
 
 
37
 
function loadInSandbox(aUri) {
38
 
  var sandbox = Components.utils.Sandbox(this);
39
 
  var request = Components.
40
 
                classes["@mozilla.org/xmlextras/xmlhttprequest;1"].
41
 
                createInstance();
42
 
 
43
 
  request.open("GET", aUri, false);
44
 
  request.overrideMimeType("application/javascript");
45
 
  request.send(null);
46
 
  Components.utils.evalInSandbox(request.responseText, sandbox, "1.8");
47
 
 
48
 
  return sandbox;
49
 
}
50
 
 
51
 
function FakeTimerService() {
52
 
  this.callbackQueue = [];
53
 
 
54
 
  var self = this;
55
 
 
56
 
  this.__proto__ = {
57
 
    makeTimerForCall: function FTS_makeTimerForCall(cb) {
58
 
      // Just add the callback to our queue and we'll call it later, so
59
 
      // as to simulate a real nsITimer.
60
 
      self.callbackQueue.push(cb);
61
 
      return "fake nsITimer";
62
 
    },
63
 
    processCallback: function FTS_processCallbacks() {
64
 
      var cb = self.callbackQueue.pop();
65
 
      if (cb) {
66
 
        cb();
67
 
        return true;
68
 
      }
69
 
      return false;
70
 
    }
71
 
  };
72
 
 
73
 
  Utils.makeTimerForCall = self.makeTimerForCall;
74
 
};
75
 
 
76
 
btoa = Cu.import("resource://services-sync/log4moz.js").btoa;
77
 
function getTestLogger(component) {
78
 
  return Log4Moz.repository.getLogger("Testing");
79
 
}
80
 
 
81
 
function initTestLogging(level) {
82
 
  function LogStats() {
83
 
    this.errorsLogged = 0;
84
 
  }
85
 
  LogStats.prototype = {
86
 
    format: function BF_format(message) {
87
 
      if (message.level == Log4Moz.Level.Error)
88
 
        this.errorsLogged += 1;
89
 
      return message.loggerName + "\t" + message.levelDesc + "\t" +
90
 
        message.message + "\n";
91
 
    }
92
 
  };
93
 
  LogStats.prototype.__proto__ = new Log4Moz.Formatter();
94
 
 
95
 
  var log = Log4Moz.repository.rootLogger;
96
 
  var logStats = new LogStats();
97
 
  var appender = new Log4Moz.DumpAppender(logStats);
98
 
 
99
 
  if (typeof(level) == "undefined")
100
 
    level = "Debug";
101
 
  getTestLogger().level = Log4Moz.Level[level];
102
 
 
103
 
  log.level = Log4Moz.Level.Trace;
104
 
  appender.level = Log4Moz.Level.Trace;
105
 
  // Overwrite any other appenders (e.g. from previous incarnations)
106
 
  log.ownAppenders = [appender];
107
 
  log.updateAppenders();
108
 
 
109
 
  return logStats;
110
 
}
111
 
 
112
 
function FakePrefService(contents) {
113
 
  Cu.import("resource://services-sync/util.js");
114
 
  this.fakeContents = contents;
115
 
  Utils.__prefs = this;
116
 
}
117
 
 
118
 
FakePrefService.prototype = {
119
 
  _getPref: function fake__getPref(pref) {
120
 
    getTestLogger().trace("Getting pref: " + pref);
121
 
    return this.fakeContents[pref];
122
 
  },
123
 
  getCharPref: function fake_getCharPref(pref) {
124
 
    return this._getPref(pref);
125
 
  },
126
 
  getBoolPref: function fake_getBoolPref(pref) {
127
 
    return this._getPref(pref);
128
 
  },
129
 
  getIntPref: function fake_getIntPref(pref) {
130
 
    return this._getPref(pref);
131
 
  },
132
 
  addObserver: function fake_addObserver() {}
133
 
};
134
 
 
135
 
function FakePasswordService(contents) {
136
 
  Cu.import("resource://services-sync/util.js");
137
 
 
138
 
  this.fakeContents = contents;
139
 
  let self = this;
140
 
 
141
 
  Utils.findPassword = function fake_findPassword(realm, username) {
142
 
    getTestLogger().trace("Password requested for " +
143
 
                          realm + ":" + username);
144
 
    if (realm in self.fakeContents && username in self.fakeContents[realm])
145
 
      return self.fakeContents[realm][username];
146
 
    else
147
 
      return null;
148
 
  };
149
 
};
150
 
 
151
 
function FakeFilesystemService(contents) {
152
 
  this.fakeContents = contents;
153
 
  let self = this;
154
 
 
155
 
  Utils.jsonSave = function jsonSave(filePath, that, obj, callback) {
156
 
    let json = typeof obj == "function" ? obj.call(that) : obj;
157
 
    self.fakeContents["weave/" + filePath + ".json"] = JSON.stringify(json);
158
 
    callback.call(that);
159
 
  };
160
 
 
161
 
  Utils.jsonLoad = function jsonLoad(filePath, that, callback) {
162
 
    let obj;
163
 
    let json = self.fakeContents["weave/" + filePath + ".json"];
164
 
    if (json) {
165
 
      obj = JSON.parse(json);
166
 
    }
167
 
    callback.call(that, obj);
168
 
  };
169
 
};
170
 
 
171
 
function FakeGUIDService() {
172
 
  let latestGUID = 0;
173
 
 
174
 
  Utils.makeGUID = function fake_makeGUID() {
175
 
    return "fake-guid-" + latestGUID++;
176
 
  };
177
 
}
178
 
 
179
 
 
180
 
/*
181
 
 * Mock implementation of IWeaveCrypto.  It does not encrypt or
182
 
 * decrypt, just returns the input verbatimly.
183
 
 */
184
 
function FakeCryptoService() {
185
 
  this.counter = 0;
186
 
 
187
 
  delete Svc.Crypto;  // get rid of the getter first
188
 
  Svc.Crypto = this;
189
 
  Utils.sha256HMAC = this.sha256HMAC;
190
 
 
191
 
  Cu.import("resource://services-sync/record.js");
192
 
  CryptoWrapper.prototype.ciphertextHMAC = this.ciphertextHMAC;
193
 
}
194
 
FakeCryptoService.prototype = {
195
 
 
196
 
  sha256HMAC: function Utils_sha256HMAC(message, hasher) {
197
 
     message = message.substr(0, 64);
198
 
     while (message.length < 64) {
199
 
       message += " ";
200
 
     }
201
 
     return message;
202
 
  },
203
 
 
204
 
  ciphertextHMAC: function CryptoWrapper_ciphertextHMAC(keyBundle) {
205
 
    return Utils.sha256HMAC(this.ciphertext);
206
 
  },
207
 
 
208
 
  encrypt: function(aClearText, aSymmetricKey, aIV) {
209
 
    return aClearText;
210
 
  },
211
 
 
212
 
  decrypt: function(aCipherText, aSymmetricKey, aIV) {
213
 
    return aCipherText;
214
 
  },
215
 
 
216
 
  generateRandomKey: function() {
217
 
    return btoa("fake-symmetric-key-" + this.counter++);
218
 
  },
219
 
 
220
 
  generateRandomIV: function() {
221
 
    // A base64-encoded IV is 24 characters long
222
 
    return btoa("fake-fake-fake-random-iv");
223
 
  },
224
 
 
225
 
  expandData : function expandData(data, len) {
226
 
    return data;
227
 
  },
228
 
 
229
 
  deriveKeyFromPassphrase : function (passphrase, salt, keyLength) {
230
 
    return "some derived key string composed of bytes";
231
 
  },
232
 
 
233
 
  generateRandomBytes: function(aByteCount) {
234
 
    return "not-so-random-now-are-we-HA-HA-HA! >:)".slice(aByteCount);
235
 
  },
236
 
};
237
 
 
238
 
 
239
 
function SyncTestingInfrastructure(engineFactory) {
240
 
  let __fakePasswords = {
241
 
    'Mozilla Services Password': {foo: "bar"},
242
 
    'Mozilla Services Encryption Passphrase': {foo: "a-abcde-abcde-abcde-abcde-abcde"}
243
 
  };
244
 
 
245
 
  let __fakePrefs = {
246
 
    "encryption" : "none",
247
 
    "log.logger.service.crypto" : "Debug",
248
 
    "log.logger.service.engine" : "Debug",
249
 
    "log.logger.async" : "Debug",
250
 
    "xmpp.enabled" : false
251
 
  };
252
 
 
253
 
  Cu.import("resource://services-sync/identity.js");
254
 
  Cu.import("resource://services-sync/util.js");
255
 
 
256
 
  ID.set('WeaveID',
257
 
         new Identity('Mozilla Services Encryption Passphrase', 'foo'));
258
 
  ID.set('WeaveCryptoID',
259
 
         new Identity('Mozilla Services Encryption Passphrase', 'foo'));
260
 
 
261
 
  this.fakePasswordService = new FakePasswordService(__fakePasswords);
262
 
  this.fakePrefService = new FakePrefService(__fakePrefs);
263
 
  this.fakeTimerService = new FakeTimerService();
264
 
  this.logStats = initTestLogging();
265
 
  this.fakeFilesystem = new FakeFilesystemService({});
266
 
  this.fakeGUIDService = new FakeGUIDService();
267
 
  this.fakeCryptoService = new FakeCryptoService();
268
 
 
269
 
  this._logger = getTestLogger();
270
 
  this._engineFactory = engineFactory;
271
 
  this._clientStates = [];
272
 
 
273
 
  this.saveClientState = function pushClientState(label) {
274
 
    let state = Utils.deepCopy(this.fakeFilesystem.fakeContents);
275
 
    let currContents = this.fakeFilesystem.fakeContents;
276
 
    this.fakeFilesystem.fakeContents = [];
277
 
    let engine = this._engineFactory();
278
 
    let snapshot = Utils.deepCopy(engine._store.wrap());
279
 
    this._clientStates[label] = {state: state, snapshot: snapshot};
280
 
    this.fakeFilesystem.fakeContents = currContents;
281
 
  };
282
 
 
283
 
  this.restoreClientState = function restoreClientState(label) {
284
 
    let state = this._clientStates[label].state;
285
 
    let snapshot = this._clientStates[label].snapshot;
286
 
 
287
 
    function _restoreState() {
288
 
      let self = yield;
289
 
 
290
 
      this.fakeFilesystem.fakeContents = [];
291
 
      let engine = this._engineFactory();
292
 
      engine._store.wipe();
293
 
      let originalSnapshot = Utils.deepCopy(engine._store.wrap());
294
 
 
295
 
      engine._core.detectUpdates(self.cb, originalSnapshot, snapshot);
296
 
      let commands = yield;
297
 
 
298
 
      engine._store.applyCommands.async(engine._store, self.cb, commands);
299
 
      yield;
300
 
 
301
 
      this.fakeFilesystem.fakeContents = Utils.deepCopy(state);
302
 
    }
303
 
 
304
 
    let self = this;
305
 
 
306
 
    function restoreState(cb) {
307
 
      _restoreState.async(self, cb);
308
 
    }
309
 
 
310
 
    this.runAsyncFunc("restore client state of " + label,
311
 
                      restoreState);
312
 
  };
313
 
 
314
 
  this.__makeCallback = function __makeCallback() {
315
 
    this.__callbackCalled = false;
316
 
    let self = this;
317
 
    return function callback() {
318
 
      self.__callbackCalled = true;
319
 
    };
320
 
  };
321
 
 
322
 
  this.doSync = function doSync(name) {
323
 
    let self = this;
324
 
 
325
 
    function freshEngineSync(cb) {
326
 
      let engine = self._engineFactory();
327
 
      engine.sync(cb);
328
 
    }
329
 
 
330
 
    this.runAsyncFunc(name, freshEngineSync);
331
 
  };
332
 
 
333
 
  this.runAsyncFunc = function runAsyncFunc(name, func) {
334
 
    let logger = this._logger;
335
 
 
336
 
    logger.info("-----------------------------------------");
337
 
    logger.info("Step '" + name + "' starting.");
338
 
    logger.info("-----------------------------------------");
339
 
    func(this.__makeCallback());
340
 
    while (this.fakeTimerService.processCallback()) {}
341
 
    do_check_true(this.__callbackCalled);
342
 
    for (name in Async.outstandingGenerators)
343
 
      logger.warn("Outstanding generator exists: " + name);
344
 
    do_check_eq(this.logStats.errorsLogged, 0);
345
 
    do_check_eq(Async.outstandingGenerators.length, 0);
346
 
    logger.info("Step '" + name + "' succeeded.");
347
 
  };
348
 
 
349
 
  this.resetClientState = function resetClientState() {
350
 
    this.fakeFilesystem.fakeContents = {};
351
 
    let engine = this._engineFactory();
352
 
    engine._store.wipe();
353
 
  };
354
 
}
355
 
 
356
 
 
357
 
/*
358
 
 * Ensure exceptions from inside callbacks leads to test failures.
359
 
 */
360
 
function ensureThrows(func) {
361
 
  return function() {
362
 
    try {
363
 
      func.apply(this, arguments);
364
 
    } catch (ex) {
365
 
      do_throw(ex);
366
 
    }
367
 
  };
368
 
}
369
 
 
370
 
function asyncChainTests() {
371
 
  return Utils.asyncChain.apply(this, Array.map(arguments, ensureThrows));
372
 
}
373
 
 
374
 
 
375
 
/**
376
 
 * Print some debug message to the console. All arguments will be printed,
377
 
 * separated by spaces.
378
 
 *
379
 
 * @param [arg0, arg1, arg2, ...]
380
 
 *        Any number of arguments to print out
381
 
 * @usage _("Hello World") -> prints "Hello World"
382
 
 * @usage _(1, 2, 3) -> prints "1 2 3"
383
 
 */
384
 
let _ = function(some, debug, text, to) print(Array.slice(arguments).join(" "));
385
 
 
386
 
_("Setting the identity for passphrase");
387
 
Cu.import("resource://services-sync/identity.js");
388
 
 
389
 
 
390
 
/*
391
 
 * Test setup helpers.
392
 
 */
393
 
 
394
 
// Turn WBO cleartext into "encrypted" payload as it goes over the wire
395
 
function encryptPayload(cleartext) {
396
 
  if (typeof cleartext == "object") {
397
 
    cleartext = JSON.stringify(cleartext);
398
 
  }
399
 
 
400
 
  return {ciphertext: cleartext, // ciphertext == cleartext with fake crypto
401
 
          IV: "irrelevant",
402
 
          hmac: Utils.sha256HMAC(cleartext, Utils.makeHMACKey(""))};
403
 
}
404