diff options
Diffstat (limited to 'b2g/components/test/unit')
-rw-r--r-- | b2g/components/test/unit/data/test_logger_file | bin | 0 -> 4037 bytes | |||
-rw-r--r-- | b2g/components/test/unit/head_identity.js | 159 | ||||
-rw-r--r-- | b2g/components/test/unit/head_logshake_gonk.js | 58 | ||||
-rw-r--r-- | b2g/components/test/unit/test_aboutserviceworkers.js | 142 | ||||
-rw-r--r-- | b2g/components/test/unit/test_bug793310.js | 39 | ||||
-rw-r--r-- | b2g/components/test/unit/test_bug832946.js | 18 | ||||
-rw-r--r-- | b2g/components/test/unit/test_fxaccounts.js | 212 | ||||
-rw-r--r-- | b2g/components/test/unit/test_logcapture.js | 13 | ||||
-rw-r--r-- | b2g/components/test/unit/test_logcapture_gonk.js | 70 | ||||
-rw-r--r-- | b2g/components/test/unit/test_logparser.js | 75 | ||||
-rw-r--r-- | b2g/components/test/unit/test_logshake.js | 218 | ||||
-rw-r--r-- | b2g/components/test/unit/test_logshake_gonk.js | 61 | ||||
-rw-r--r-- | b2g/components/test/unit/test_logshake_gonk_compression.js | 76 | ||||
-rw-r--r-- | b2g/components/test/unit/test_logshake_readLog_gonk.js | 65 | ||||
-rw-r--r-- | b2g/components/test/unit/test_signintowebsite.js | 322 | ||||
-rw-r--r-- | b2g/components/test/unit/xpcshell.ini | 49 |
16 files changed, 1577 insertions, 0 deletions
diff --git a/b2g/components/test/unit/data/test_logger_file b/b2g/components/test/unit/data/test_logger_file Binary files differnew file mode 100644 index 000000000..b1ed7f10a --- /dev/null +++ b/b2g/components/test/unit/data/test_logger_file diff --git a/b2g/components/test/unit/head_identity.js b/b2g/components/test/unit/head_identity.js new file mode 100644 index 000000000..604a77284 --- /dev/null +++ b/b2g/components/test/unit/head_identity.js @@ -0,0 +1,159 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +var Ci = Components.interfaces; +var Cu = Components.utils; + +// The following boilerplate makes sure that XPCOM calls +// that use the profile directory work. + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "MinimalIDService", + "resource://gre/modules/identity/MinimalIdentity.jsm", + "IdentityService"); + +XPCOMUtils.defineLazyModuleGetter(this, + "Logger", + "resource://gre/modules/identity/LogUtils.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, + "uuidGenerator", + "@mozilla.org/uuid-generator;1", + "nsIUUIDGenerator"); + +const TEST_URL = "https://myfavoriteflan.com"; +const TEST_USER = "uumellmahaye1969@hotmail.com"; +const TEST_PRIVKEY = "i-am-a-secret"; +const TEST_CERT = "i~like~pie"; + +// The following are utility functions for Identity testing + +function log(...aMessageArgs) { + Logger.log.apply(Logger, ["test"].concat(aMessageArgs)); +} + +function partial(fn) { + let args = Array.prototype.slice.call(arguments, 1); + return function() { + return fn.apply(this, args.concat(Array.prototype.slice.call(arguments))); + }; +} + +function uuid() { + return uuidGenerator.generateUUID().toString(); +} + +// create a mock "doc" object, which the Identity Service +// uses as a pointer back into the doc object +function mockDoc(aParams, aDoFunc) { + let mockedDoc = {}; + mockedDoc.id = uuid(); + + // Properties of aParams may include loggedInUser + Object.keys(aParams).forEach(function(param) { + mockedDoc[param] = aParams[param]; + }); + + // the origin is set inside nsDOMIdentity by looking at the + // document.nodePrincipal.origin. Here we, we must satisfy + // ourselves with pretending. + mockedDoc.origin = "https://jedp.gov"; + + mockedDoc['do'] = aDoFunc; + mockedDoc.doReady = partial(aDoFunc, 'ready'); + mockedDoc.doLogin = partial(aDoFunc, 'login'); + mockedDoc.doLogout = partial(aDoFunc, 'logout'); + mockedDoc.doError = partial(aDoFunc, 'error'); + mockedDoc.doCancel = partial(aDoFunc, 'cancel'); + mockedDoc.doCoffee = partial(aDoFunc, 'coffee'); + + return mockedDoc; +} + +// create a mock "pipe" object that would normally communicate +// messages up to gaia (either the trusty ui or the hidden iframe), +// and convey messages back down from gaia to the controller through +// the message callback. + +// The mock receiving pipe simulates gaia which, after receiving messages +// through the pipe, will call back with instructions to invoke +// certain methods. It mocks what comes back from the other end of +// the pipe. +function mockReceivingPipe() { + let MockedPipe = { + communicate: function(aRpOptions, aGaiaOptions, aMessageCallback) { + switch (aGaiaOptions.message) { + case "identity-delegate-watch": + aMessageCallback({json: {method: "ready"}}); + break; + case "identity-delegate-request": + aMessageCallback({json: {method: "login", assertion: TEST_CERT}}); + break; + case "identity-delegate-logout": + aMessageCallback({json: {method: "logout"}}); + break; + default: + throw("what the what?? " + aGaiaOptions.message); + break; + } + } + }; + return MockedPipe; +} + +// The mock sending pipe lets us test what's actually getting put in the +// pipe. +function mockSendingPipe(aMessageCallback) { + let MockedPipe = { + communicate: function(aRpOptions, aGaiaOptions, aDummyCallback) { + aMessageCallback(aRpOptions, aGaiaOptions); + } + }; + return MockedPipe; +} + +// mimicking callback funtionality for ease of testing +// this observer auto-removes itself after the observe function +// is called, so this is meant to observe only ONE event. +function makeObserver(aObserveTopic, aObserveFunc) { + let observer = { + // nsISupports provides type management in C++ + // nsIObserver is to be an observer + QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports, Ci.nsIObserver]), + + observe: function (aSubject, aTopic, aData) { + if (aTopic == aObserveTopic) { + Services.obs.removeObserver(observer, aObserveTopic); + aObserveFunc(aSubject, aTopic, aData); + } + } + }; + + Services.obs.addObserver(observer, aObserveTopic, false); +} + +// a hook to set up the ID service with an identity with keypair and all +// when ready, invoke callback with the identity. It's there if we need it. +function setup_test_identity(identity, cert, cb) { + cb(); +} + +// takes a list of functions and returns a function that +// when called the first time, calls the first func, +// then the next time the second, etc. +function call_sequentially() { + let numCalls = 0; + let funcs = arguments; + + return function() { + if (!funcs[numCalls]) { + let argString = Array.prototype.slice.call(arguments).join(","); + do_throw("Too many calls: " + argString); + return; + } + funcs[numCalls].apply(funcs[numCalls],arguments); + numCalls += 1; + }; +} diff --git a/b2g/components/test/unit/head_logshake_gonk.js b/b2g/components/test/unit/head_logshake_gonk.js new file mode 100644 index 000000000..e94234f1f --- /dev/null +++ b/b2g/components/test/unit/head_logshake_gonk.js @@ -0,0 +1,58 @@ +/** + * Boostrap LogShake's tests that need gonk support. + * This is creating a fake sdcard for LogShake tests and importing LogShake and + * osfile + */ + +/* jshint moz: true */ +/* global Components, LogCapture, LogShake, ok, add_test, run_next_test, dump, + do_get_profile, OS, volumeService, equal, XPCOMUtils */ +/* exported setup_logshake_mocks */ + +/* disable use strict warning */ +/* jshint -W097 */ + +"use strict"; + +var Cu = Components.utils; +var Ci = Components.interfaces; +var Cc = Components.classes; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/osfile.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "volumeService", + "@mozilla.org/telephony/volume-service;1", + "nsIVolumeService"); + +var sdcard; + +function setup_logshake_mocks() { + do_get_profile(); + setup_fs(); +} + +function setup_fs() { + OS.File.makeDir("/data/local/tmp/sdcard/", {from: "/data"}).then(function() { + setup_sdcard(); + }); +} + +function setup_sdcard() { + let volName = "sdcard"; + let mountPoint = "/data/local/tmp/sdcard"; + volumeService.createFakeVolume(volName, mountPoint); + + let vol = volumeService.getVolumeByName(volName); + ok(vol, "volume shouldn't be null"); + equal(volName, vol.name, "name"); + equal(Ci.nsIVolume.STATE_MOUNTED, vol.state, "state"); + + ensure_sdcard(); +} + +function ensure_sdcard() { + sdcard = volumeService.getVolumeByName("sdcard").mountPoint; + ok(sdcard, "Should have a valid sdcard mountpoint"); + run_next_test(); +} diff --git a/b2g/components/test/unit/test_aboutserviceworkers.js b/b2g/components/test/unit/test_aboutserviceworkers.js new file mode 100644 index 000000000..d1a7d41aa --- /dev/null +++ b/b2g/components/test/unit/test_aboutserviceworkers.js @@ -0,0 +1,142 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +var {utils: Cu} = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); + +XPCOMUtils.defineLazyModuleGetter(this, "AboutServiceWorkers", + "resource://gre/modules/AboutServiceWorkers.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "gServiceWorkerManager", + "@mozilla.org/serviceworkers/manager;1", + "nsIServiceWorkerManager"); + +const CHROME_MSG = "mozAboutServiceWorkersChromeEvent"; + +const ORIGINAL_SENDRESULT = AboutServiceWorkers.sendResult; +const ORIGINAL_SENDERROR = AboutServiceWorkers.sendError; + +do_get_profile(); + +var mockSendResult = (aId, aResult) => { + let msg = { + id: aId, + result: aResult + }; + Services.obs.notifyObservers({wrappedJSObject: msg}, CHROME_MSG, null); +}; + +var mockSendError = (aId, aError) => { + let msg = { + id: aId, + result: aError + }; + Services.obs.notifyObservers({wrappedJSObject: msg}, CHROME_MSG, null); +}; + +function attachMocks() { + AboutServiceWorkers.sendResult = mockSendResult; + AboutServiceWorkers.sendError = mockSendError; +} + +function restoreMocks() { + AboutServiceWorkers.sendResult = ORIGINAL_SENDRESULT; + AboutServiceWorkers.sendError = ORIGINAL_SENDERROR; +} + +do_register_cleanup(restoreMocks); + +function run_test() { + run_next_test(); +} + +/** + * "init" tests + */ +[ +// Pref disabled, no registrations +{ + prefEnabled: false, + expectedMessage: { + id: Date.now(), + result: { + enabled: false, + registrations: [] + } + } +}, +// Pref enabled, no registrations +{ + prefEnabled: true, + expectedMessage: { + id: Date.now(), + result: { + enabled: true, + registrations: [] + } + } +}].forEach(test => { + add_test(function() { + Services.prefs.setBoolPref("dom.serviceWorkers.enabled", test.prefEnabled); + + let id = test.expectedMessage.id; + + function onMessage(subject, topic, data) { + let message = subject.wrappedJSObject; + let expected = test.expectedMessage; + + do_check_true(message.id, "Message should have id"); + do_check_eq(message.id, test.expectedMessage.id, + "Id should be the expected one"); + do_check_eq(message.result.enabled, expected.result.enabled, + "Pref should be disabled"); + do_check_true(message.result.registrations, "Registrations should exist"); + do_check_eq(message.result.registrations.length, + expected.result.registrations.length, + "Registrations length should be the expected one"); + + Services.obs.removeObserver(onMessage, CHROME_MSG); + + run_next_test(); + } + + Services.obs.addObserver(onMessage, CHROME_MSG, false); + + attachMocks(); + + AboutServiceWorkers.handleEvent({ detail: { + id: id, + name: "init" + }}); + }); +}); + +/** + * ServiceWorkerManager tests. + */ + +// We cannot register a sw via ServiceWorkerManager cause chrome +// registrations are not allowed. +// All we can do for now is to test the interface of the swm. +add_test(function test_swm() { + do_check_true(gServiceWorkerManager, "SWM exists"); + do_check_true(gServiceWorkerManager.getAllRegistrations, + "SWM.getAllRegistrations exists"); + do_check_true(typeof gServiceWorkerManager.getAllRegistrations == "function", + "SWM.getAllRegistrations is a function"); + do_check_true(gServiceWorkerManager.propagateSoftUpdate, + "SWM.propagateSoftUpdate exists"); + do_check_true(typeof gServiceWorkerManager.propagateSoftUpdate == "function", + + "SWM.propagateSoftUpdate is a function"); + do_check_true(gServiceWorkerManager.propagateUnregister, + "SWM.propagateUnregister exists"); + do_check_true(typeof gServiceWorkerManager.propagateUnregister == "function", + "SWM.propagateUnregister exists"); + + run_next_test(); +}); diff --git a/b2g/components/test/unit/test_bug793310.js b/b2g/components/test/unit/test_bug793310.js new file mode 100644 index 000000000..2bdb8252e --- /dev/null +++ b/b2g/components/test/unit/test_bug793310.js @@ -0,0 +1,39 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function run_test() { + Components.utils.import("resource:///modules/TelURIParser.jsm") + + // global-phone-number + do_check_eq(TelURIParser.parseURI('tel', 'tel:+1234'), '+1234'); + + // global-phone-number => white space separator + do_check_eq(TelURIParser.parseURI('tel', 'tel:+123 456 789'), '+123 456 789'); + + // global-phone-number => ignored chars + do_check_eq(TelURIParser.parseURI('tel', 'tel:+1234_123'), '+1234'); + + // global-phone-number => visualSeparator + digits + do_check_eq(TelURIParser.parseURI('tel', 'tel:+-.()1234567890'), '+-.()1234567890'); + + // local-phone-number + do_check_eq(TelURIParser.parseURI('tel', 'tel:1234'), '1234'); + + // local-phone-number => visualSeparator + digits + dtmfDigits + pauseCharacter + do_check_eq(TelURIParser.parseURI('tel', 'tel:-.()1234567890ABCDpw'), '-.()1234567890ABCDpw'); + + // local-phone-number => visualSeparator + digits + dtmfDigits + pauseCharacter + ignored chars + do_check_eq(TelURIParser.parseURI('tel', 'tel:-.()1234567890ABCDpw_'), '-.()1234567890ABCDpw'); + + // local-phone-number => isdn-subaddress + do_check_eq(TelURIParser.parseURI('tel', 'tel:123;isub=123'), '123'); + + // local-phone-number => post-dial + do_check_eq(TelURIParser.parseURI('tel', 'tel:123;postd=123'), '123'); + + // local-phone-number => prefix + do_check_eq(TelURIParser.parseURI('tel', 'tel:123;phone-context=+0321'), '+0321123'); + + // local-phone-number => isdn-subaddress + post-dial + prefix + do_check_eq(TelURIParser.parseURI('tel', 'tel:123;isub=123;postd=123;phone-context=+0321'), '+0321123'); +} diff --git a/b2g/components/test/unit/test_bug832946.js b/b2g/components/test/unit/test_bug832946.js new file mode 100644 index 000000000..4ddbd4280 --- /dev/null +++ b/b2g/components/test/unit/test_bug832946.js @@ -0,0 +1,18 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function run_test() { + Components.utils.import("resource:///modules/TelURIParser.jsm") + + // blocked numbers + do_check_eq(TelURIParser.parseURI('tel', 'tel:#1234*'), null); + do_check_eq(TelURIParser.parseURI('tel', 'tel:*1234#'), null); + do_check_eq(TelURIParser.parseURI('tel', 'tel:*1234*'), null); + do_check_eq(TelURIParser.parseURI('tel', 'tel:#1234#'), null); + do_check_eq(TelURIParser.parseURI('tel', 'tel:*#*#7780#*#*'), null); + do_check_eq(TelURIParser.parseURI('tel', 'tel:*1234AB'), null); + + // white list + do_check_eq(TelURIParser.parseURI('tel', 'tel:*1234'), '*1234'); + do_check_eq(TelURIParser.parseURI('tel', 'tel:#1234'), '#1234'); +} diff --git a/b2g/components/test/unit/test_fxaccounts.js b/b2g/components/test/unit/test_fxaccounts.js new file mode 100644 index 000000000..5de0d6565 --- /dev/null +++ b/b2g/components/test/unit/test_fxaccounts.js @@ -0,0 +1,212 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +var {utils: Cu} = Components; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://services-common/utils.js"); +Cu.import("resource://testing-common/httpd.js"); + +XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsMgmtService", + "resource://gre/modules/FxAccountsMgmtService.jsm", + "FxAccountsMgmtService"); + +XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsManager", + "resource://gre/modules/FxAccountsManager.jsm"); + +// At end of test, restore original state +const ORIGINAL_AUTH_URI = Services.prefs.getCharPref("identity.fxaccounts.auth.uri"); +var { SystemAppProxy } = Cu.import("resource://gre/modules/FxAccountsMgmtService.jsm"); +const ORIGINAL_SENDCUSTOM = SystemAppProxy._sendCustomEvent; +do_register_cleanup(function() { + Services.prefs.setCharPref("identity.fxaccounts.auth.uri", ORIGINAL_AUTH_URI); + SystemAppProxy._sendCustomEvent = ORIGINAL_SENDCUSTOM; + Services.prefs.clearUserPref("identity.fxaccounts.skipDeviceRegistration"); +}); + +// Make profile available so that fxaccounts can store user data +do_get_profile(); + +// Mock the system app proxy; make message passing possible +var mockSendCustomEvent = function(aEventName, aMsg) { + Services.obs.notifyObservers({wrappedJSObject: aMsg}, aEventName, null); +}; + +function run_test() { + run_next_test(); +} + +add_task(function test_overall() { + // FxA device registration throws from this context + Services.prefs.setBoolPref("identity.fxaccounts.skipDeviceRegistration", true); + + do_check_neq(FxAccountsMgmtService, null); +}); + +// Check that invalid email capitalization is corrected on signIn. +// https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#post-v1accountlogin +add_test(function test_invalidEmailCase_signIn() { + do_test_pending(); + let clientEmail = "greta.garbo@gmail.com"; + let canonicalEmail = "Greta.Garbo@gmail.COM"; + let attempts = 0; + + function writeResp(response, msg) { + if (typeof msg === "object") { + msg = JSON.stringify(msg); + } + response.bodyOutputStream.write(msg, msg.length); + } + + // Mock of the fxa accounts auth server, reproducing the behavior of + // /account/login when email capitalization is incorrect on signIn. + let server = httpd_setup({ + "/account/login": function(request, response) { + response.setHeader("Content-Type", "application/json"); + attempts += 1; + + // Ensure we don't get in an endless loop + if (attempts > 2) { + response.setStatusLine(request.httpVersion, 429, "Sorry, you had your chance"); + writeResp(response, {}); + return; + } + + let body = CommonUtils.readBytesFromInputStream(request.bodyInputStream); + let jsonBody = JSON.parse(body); + let email = jsonBody.email; + + // The second time through, the accounts client will call the api with + // the correct email capitalization. + if (email == canonicalEmail) { + response.setStatusLine(request.httpVersion, 200, "Yay"); + writeResp(response, { + uid: "your-uid", + sessionToken: "your-sessionToken", + keyFetchToken: "your-keyFetchToken", + verified: true, + authAt: 1392144866, + }); + return; + } + + // If the client has the wrong case on the email, we return a 400, with + // the capitalization of the email as saved in the accounts database. + response.setStatusLine(request.httpVersion, 400, "Incorrect email case"); + writeResp(response, { + code: 400, + errno: 120, + error: "Incorrect email case", + email: canonicalEmail, + }); + return; + }, + }); + + // Point the FxAccountsClient's hawk rest request client to the mock server + Services.prefs.setCharPref("identity.fxaccounts.auth.uri", server.baseURI); + + // FxA device registration throws from this context + Services.prefs.setBoolPref("identity.fxaccounts.skipDeviceRegistration", true); + + // Receive a mozFxAccountsChromeEvent message + function onMessage(subject, topic, data) { + let message = subject.wrappedJSObject; + + switch (message.id) { + // When we signed in as "Greta.Garbo", the server should have told us + // that the proper capitalization is really "greta.garbo". Call + // getAccounts to get the signed-in user and ensure that the + // capitalization is correct. + case "signIn": + FxAccountsMgmtService.handleEvent({ + detail: { + id: "getAccounts", + data: { + method: "getAccounts", + } + } + }); + break; + + // Having initially signed in as "Greta.Garbo", getAccounts should show + // us that the signed-in user has the properly-capitalized email, + // "greta.garbo". + case "getAccounts": + Services.obs.removeObserver(onMessage, "mozFxAccountsChromeEvent"); + + do_check_eq(message.data.email, canonicalEmail); + + do_test_finished(); + server.stop(run_next_test); + break; + + // We should not receive any other mozFxAccountsChromeEvent messages + default: + do_throw("wat!"); + break; + } + } + + Services.obs.addObserver(onMessage, "mozFxAccountsChromeEvent", false); + + SystemAppProxy._sendCustomEvent = mockSendCustomEvent; + + // Trigger signIn using an email with incorrect capitalization + FxAccountsMgmtService.handleEvent({ + detail: { + id: "signIn", + data: { + method: "signIn", + email: clientEmail, + password: "123456", + }, + }, + }); +}); + +add_test(function testHandleGetAssertionError_defaultCase() { + do_test_pending(); + + // FxA device registration throws from this context + Services.prefs.setBoolPref("identity.fxaccounts.skipDeviceRegistration", true); + + FxAccountsManager.getAssertion(null).then( + success => { + // getAssertion should throw with invalid audience + ok(false); + }, + reason => { + equal("INVALID_AUDIENCE", reason.error); + do_test_finished(); + run_next_test(); + } + ) +}); + +// End of tests +// Utility functions follow + +function httpd_setup (handlers, port=-1) { + let server = new HttpServer(); + for (let path in handlers) { + server.registerPathHandler(path, handlers[path]); + } + try { + server.start(port); + } catch (ex) { + dump("ERROR starting server on port " + port + ". Already a process listening?"); + do_throw(ex); + } + + // Set the base URI for convenience. + let i = server.identity; + server.baseURI = i.primaryScheme + "://" + i.primaryHost + ":" + i.primaryPort; + + return server; +} + + diff --git a/b2g/components/test/unit/test_logcapture.js b/b2g/components/test/unit/test_logcapture.js new file mode 100644 index 000000000..9dbe2bc77 --- /dev/null +++ b/b2g/components/test/unit/test_logcapture.js @@ -0,0 +1,13 @@ +/** + * Testing non Gonk-specific code path + */ +function run_test() { + Components.utils.import("resource:///modules/LogCapture.jsm"); + run_next_test(); +} + +// Trivial test just to make sure we have no syntax error +add_test(function test_logCapture_loads() { + ok(LogCapture, "LogCapture object exists"); + run_next_test(); +}); diff --git a/b2g/components/test/unit/test_logcapture_gonk.js b/b2g/components/test/unit/test_logcapture_gonk.js new file mode 100644 index 000000000..d80f33dd9 --- /dev/null +++ b/b2g/components/test/unit/test_logcapture_gonk.js @@ -0,0 +1,70 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + + +/** + * Test that LogCapture successfully reads from the /dev/log devices, returning + * a Uint8Array of some length, including zero. This tests a few standard + * log devices + */ +function run_test() { + Components.utils.import("resource:///modules/LogCapture.jsm"); + run_next_test(); +} + +function verifyLog(log) { + // log exists + notEqual(log, null); + // log has a length and it is non-negative (is probably array-like) + ok(log.length >= 0); +} + +add_test(function test_readLogFile() { + let mainLog = LogCapture.readLogFile("/dev/log/main"); + verifyLog(mainLog); + + let meminfoLog = LogCapture.readLogFile("/proc/meminfo"); + verifyLog(meminfoLog); + + run_next_test(); +}); + +add_test(function test_readProperties() { + let propertiesLog = LogCapture.readProperties(); + notEqual(propertiesLog, null, "Properties should not be null"); + notEqual(propertiesLog, undefined, "Properties should not be undefined"); + + for (let propertyName in propertiesLog) { + equal(typeof(propertiesLog[propertyName]), "string", + "Property " + propertyName + " should be a string"); + } + + equal(propertiesLog["ro.product.locale.language"], "en", + "Locale language should be read correctly. See bug 1171577."); + + equal(propertiesLog["ro.product.locale.region"], "US", + "Locale region should be read correctly. See bug 1171577."); + + run_next_test(); +}); + +add_test(function test_readAppIni() { + let appIni = LogCapture.readLogFile("/system/b2g/application.ini"); + verifyLog(appIni); + + run_next_test(); +}); + +add_test(function test_get_about_memory() { + let memLog = LogCapture.readAboutMemory(); + + ok(memLog, "Should have returned a valid Promise object"); + + memLog.then(file => { + ok(file, "Should have returned a filename"); + run_next_test(); + }, error => { + ok(false, "Dumping about:memory promise rejected: " + error); + run_next_test(); + }); +}); diff --git a/b2g/components/test/unit/test_logparser.js b/b2g/components/test/unit/test_logparser.js new file mode 100644 index 000000000..624dcc6e2 --- /dev/null +++ b/b2g/components/test/unit/test_logparser.js @@ -0,0 +1,75 @@ +/* jshint moz: true */ + +var {utils: Cu, classes: Cc, interfaces: Ci} = Components; + +function debug(msg) { + var timestamp = Date.now(); + dump("LogParser: " + timestamp + ": " + msg + "\n"); +} + +function run_test() { + Cu.import("resource:///modules/LogParser.jsm"); + debug("Starting"); + run_next_test(); +} + +function makeStream(file) { + var fileStream = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + fileStream.init(file, -1, -1, 0); + var bis = Cc["@mozilla.org/binaryinputstream;1"] + .createInstance(Ci.nsIBinaryInputStream); + bis.setInputStream(fileStream); + return bis; +} + +add_test(function test_parse_logfile() { + let loggerFile = do_get_file("data/test_logger_file"); + + let loggerStream = makeStream(loggerFile); + + // Initialize arrays to hold the file contents (lengths are hardcoded) + let loggerArray = new Uint8Array(loggerStream.readByteArray(4037)); + + loggerStream.close(); + + let logMessages = LogParser.parseLogArray(loggerArray); + + ok(logMessages.length === 58, "There should be 58 messages in the log"); + + let expectedLogEntry = { + processId: 271, threadId: 271, + seconds: 790796, nanoseconds: 620000001, time: 790796620.000001, + priority: 4, tag: "Vold", + message: "Vold 2.1 (the revenge) firing up\n" + }; + + deepEqual(expectedLogEntry, logMessages[0]); + run_next_test(); +}); + +add_test(function test_print_properties() { + let properties = { + "ro.secure": "1", + "sys.usb.state": "diag,serial_smd,serial_tty,rmnet_bam,mass_storage,adb" + }; + + let logMessagesRaw = LogParser.prettyPrintPropertiesArray(properties); + let logMessages = new TextDecoder("utf-8").decode(logMessagesRaw); + let logMessagesArray = logMessages.split("\n"); + + ok(logMessagesArray.length === 3, "There should be 3 lines in the log."); + notEqual(logMessagesArray[0], "", "First line should not be empty"); + notEqual(logMessagesArray[1], "", "Second line should not be empty"); + equal(logMessagesArray[2], "", "Last line should be empty"); + + let expectedLog = [ + "[ro.secure]: [1]", + "[sys.usb.state]: [diag,serial_smd,serial_tty,rmnet_bam,mass_storage,adb]", + "" + ].join("\n"); + + deepEqual(expectedLog, logMessages); + + run_next_test(); +}); diff --git a/b2g/components/test/unit/test_logshake.js b/b2g/components/test/unit/test_logshake.js new file mode 100644 index 000000000..cfb81b893 --- /dev/null +++ b/b2g/components/test/unit/test_logshake.js @@ -0,0 +1,218 @@ +/** + * Test the log capturing capabilities of LogShake.jsm + */ + +/* jshint moz: true */ +/* global Components, LogCapture, LogShake, ok, add_test, run_next_test, dump */ +/* exported run_test */ + +/* disable use strict warning */ +/* jshint -W097 */ +"use strict"; + +var Cu = Components.utils; + +Cu.import("resource://gre/modules/LogCapture.jsm"); +Cu.import("resource://gre/modules/LogShake.jsm"); + +const EVENTS_PER_SECOND = 6.25; +const GRAVITY = 9.8; + +/** + * Force logshake to handle a device motion event with given components. + * Does not use SystemAppProxy because event needs special + * accelerationIncludingGravity property. + */ +function sendDeviceMotionEvent(x, y, z) { + let event = { + type: "devicemotion", + accelerationIncludingGravity: { + x: x, + y: y, + z: z + } + }; + LogShake.handleEvent(event); +} + +/** + * Send a screen change event directly, does not use SystemAppProxy due to race + * conditions. + */ +function sendScreenChangeEvent(screenEnabled) { + let event = { + type: "screenchange", + detail: { + screenEnabled: screenEnabled + } + }; + LogShake.handleEvent(event); +} + +/** + * Mock the readLogFile function of LogCapture. + * Used to detect whether LogShake activates. + * @return {Array<String>} Locations that LogShake tries to read + */ +function mockReadLogFile() { + let readLocations = []; + + LogCapture.readLogFile = function(loc) { + readLocations.push(loc); + return null; // we don't want to provide invalid data to a parser + }; + + // Allow inspection of readLocations by caller + return readLocations; +} + +/** + * Send a series of events that corresponds to a shake + */ +function sendSustainedShake() { + // Fire a series of devicemotion events that are of shake magnitude + for (let i = 0; i < 2 * EVENTS_PER_SECOND; i++) { + sendDeviceMotionEvent(0, 2 * GRAVITY, 2 * GRAVITY); + } + +} + +add_test(function test_do_log_capture_after_shaking() { + // Enable LogShake + LogShake.init(); + + let readLocations = mockReadLogFile(); + + sendSustainedShake(); + + ok(readLocations.length > 0, + "LogShake should attempt to read at least one log"); + + LogShake.uninit(); + run_next_test(); +}); + +add_test(function test_do_nothing_when_resting() { + // Enable LogShake + LogShake.init(); + + let readLocations = mockReadLogFile(); + + // Fire several devicemotion events that are relatively tiny + for (let i = 0; i < 2 * EVENTS_PER_SECOND; i++) { + sendDeviceMotionEvent(0, GRAVITY, GRAVITY); + } + + ok(readLocations.length === 0, + "LogShake should not read any logs"); + + LogShake.uninit(); + run_next_test(); +}); + +add_test(function test_do_nothing_when_disabled() { + // Disable LogShake + LogShake.uninit(); + + let readLocations = mockReadLogFile(); + + // Fire a series of events that would normally be a shake + sendSustainedShake(); + + ok(readLocations.length === 0, + "LogShake should not read any logs"); + + run_next_test(); +}); + +add_test(function test_do_nothing_when_screen_off() { + // Enable LogShake + LogShake.init(); + + // Send an event as if the screen has been turned off + sendScreenChangeEvent(false); + + let readLocations = mockReadLogFile(); + + // Fire a series of events that would normally be a shake + sendSustainedShake(); + + ok(readLocations.length === 0, + "LogShake should not read any logs"); + + // Restore the screen + sendScreenChangeEvent(true); + + LogShake.uninit(); + run_next_test(); +}); + +add_test(function test_do_log_capture_resilient_readLogFile() { + // Enable LogShake + LogShake.init(); + + let readLocations = []; + LogCapture.readLogFile = function(loc) { + readLocations.push(loc); + throw new Error("Exception during readLogFile for: " + loc); + }; + + // Fire a series of events that would normally be a shake + sendSustainedShake(); + + ok(readLocations.length > 0, + "LogShake should attempt to read at least one log"); + + LogShake.uninit(); + run_next_test(); +}); + +add_test(function test_do_log_capture_resilient_parseLog() { + // Enable LogShake + LogShake.init(); + + let readLocations = []; + LogCapture.readLogFile = function(loc) { + readLocations.push(loc); + LogShake.LOGS_WITH_PARSERS[loc] = function() { + throw new Error("Exception during LogParser for: " + loc); + }; + return null; + }; + + // Fire a series of events that would normally be a shake + sendSustainedShake(); + + ok(readLocations.length > 0, + "LogShake should attempt to read at least one log"); + + LogShake.uninit(); + run_next_test(); +}); + +add_test(function test_do_nothing_when_dropped() { + // Enable LogShake + LogShake.init(); + + let readLocations = mockReadLogFile(); + + // We want a series of spikes to be ignored by LogShake. This roughly + // corresponds to the compare_stairs_sock graph on bug #1101994 + + for (let i = 0; i < 10 * EVENTS_PER_SECOND; i++) { + // Fire a devicemotion event that is at rest + sendDeviceMotionEvent(0, 0, GRAVITY); + // Fire a spike of motion + sendDeviceMotionEvent(0, 2 * GRAVITY, 2 * GRAVITY); + } + + ok(readLocations.length === 0, + "LogShake should not read any logs"); + + LogShake.uninit(); + run_next_test(); +}); + +function run_test() { + run_next_test(); +} diff --git a/b2g/components/test/unit/test_logshake_gonk.js b/b2g/components/test/unit/test_logshake_gonk.js new file mode 100644 index 000000000..28de0263f --- /dev/null +++ b/b2g/components/test/unit/test_logshake_gonk.js @@ -0,0 +1,61 @@ +/** + * Test the log capturing capabilities of LogShake.jsm, checking + * for Gonk-specific parts + */ + +/* jshint moz: true, esnext: true */ +/* global Cu, LogCapture, LogShake, ok, add_test, run_next_test, dump, + setup_logshake_mocks, OS, sdcard */ +/* exported run_test */ + +/* disable use strict warning */ +/* jshint -W097 */ + +"use strict"; + +Cu.import("resource://gre/modules/Promise.jsm"); + +function run_test() { + Cu.import("resource://gre/modules/LogShake.jsm"); + run_next_test(); +} + +add_test(setup_logshake_mocks); + +add_test(function test_logShake_captureLogs_writes() { + // Enable LogShake + LogShake.init(); + + let expectedFiles = []; + + LogShake.captureLogs().then(logResults => { + LogShake.uninit(); + + ok(logResults.logFilenames.length > 0, "Should have filenames"); + ok(logResults.logPaths.length > 0, "Should have paths"); + ok(!logResults.compressed, "Should not be compressed"); + + logResults.logPaths.forEach(f => { + let p = OS.Path.join(sdcard, f); + ok(p, "Should have a valid result path: " + p); + + let t = OS.File.exists(p).then(rv => { + ok(rv, "File exists: " + p); + }); + + expectedFiles.push(t); + }); + + Promise.all(expectedFiles).then(() => { + ok(true, "Completed all files checks"); + run_next_test(); + }); + }, + error => { + LogShake.uninit(); + + ok(false, "Should not have received error: " + error); + + run_next_test(); + }); +}); diff --git a/b2g/components/test/unit/test_logshake_gonk_compression.js b/b2g/components/test/unit/test_logshake_gonk_compression.js new file mode 100644 index 000000000..b5af46081 --- /dev/null +++ b/b2g/components/test/unit/test_logshake_gonk_compression.js @@ -0,0 +1,76 @@ +/** + * Test the log capturing capabilities of LogShake.jsm, checking + * for Gonk-specific parts + */ + +/* jshint moz: true, esnext: true */ +/* global Cc, Ci, Cu, LogCapture, LogShake, ok, add_test, run_next_test, dump, + setup_logshake_mocks, OS, sdcard, FileUtils */ +/* exported run_test */ + +/* disable use strict warning */ +/* jshint -W097 */ + +"use strict"; + +Cu.import("resource://gre/modules/Promise.jsm"); +Cu.import("resource://gre/modules/FileUtils.jsm"); + +function run_test() { + Cu.import("resource://gre/modules/LogShake.jsm"); + run_next_test(); +} + +add_test(setup_logshake_mocks); + +add_test(function test_logShake_captureLogs_writes_zip() { + // Enable LogShake + LogShake.init(); + + let expectedFiles = []; + + LogShake.enableQAMode(); + + LogShake.captureLogs().then(logResults => { + LogShake.uninit(); + + ok(logResults.logPaths.length === 1, "Should have zip path"); + ok(logResults.logFilenames.length >= 1, "Should have log filenames"); + ok(logResults.compressed, "Log files should be compressed"); + + let zipPath = OS.Path.join(sdcard, logResults.logPaths[0]); + ok(zipPath, "Should have a valid archive path: " + zipPath); + + let zipFile = new FileUtils.File(zipPath); + ok(zipFile, "Should have a valid archive file: " + zipFile); + + let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"] + .createInstance(Ci.nsIZipReader); + zipReader.open(zipFile); + + let logFilenamesSeen = {}; + + let zipEntries = zipReader.findEntries(null); // Find all entries + while (zipEntries.hasMore()) { + let entryName = zipEntries.getNext(); + let entry = zipReader.getEntry(entryName); + logFilenamesSeen[entryName] = true; + ok(!entry.isDirectory, "Archive entry " + entryName + " should be a file"); + } + zipReader.close(); + + // TODO: Verify archive contents + logResults.logFilenames.forEach(filename => { + ok(logFilenamesSeen[filename], "File " + filename + " should be present in archive"); + }); + run_next_test(); + }, + error => { + LogShake.uninit(); + + ok(false, "Should not have received error: " + error); + + run_next_test(); + }); +}); + diff --git a/b2g/components/test/unit/test_logshake_readLog_gonk.js b/b2g/components/test/unit/test_logshake_readLog_gonk.js new file mode 100644 index 000000000..003723ad5 --- /dev/null +++ b/b2g/components/test/unit/test_logshake_readLog_gonk.js @@ -0,0 +1,65 @@ +/** + * Test the log capturing capabilities of LogShake.jsm under conditions that + * could cause races + */ + +/* jshint moz: true, esnext: true */ +/* global Cu, LogCapture, LogShake, ok, add_test, run_next_test, dump, + XPCOMUtils, do_get_profile, OS, volumeService, Promise, equal, + setup_logshake_mocks */ +/* exported run_test */ + +/* disable use strict warning */ +/* jshint -W097 */ + +"use strict"; + +function run_test() { + Cu.import("resource://gre/modules/LogShake.jsm"); + run_next_test(); +} + +add_test(setup_logshake_mocks); + +add_test(function test_logShake_captureLogs_waits_to_read() { + // Enable LogShake + LogShake.init(); + + // Save no logs synchronously (except properties) + LogShake.LOGS_WITH_PARSERS = {}; + + LogShake.captureLogs().then(logResults => { + LogShake.uninit(); + + ok(logResults.logFilenames.length > 0, "Should have filenames"); + ok(logResults.logPaths.length > 0, "Should have paths"); + ok(!logResults.compressed, "Should not be compressed"); + + // This assumes that the about:memory reading will only fail under abnormal + // circumstances. It does not check for screenshot.png because + // systemAppFrame is unavailable during xpcshell tests. + let hasAboutMemory = false; + + logResults.logFilenames.forEach(filename => { + // Because the about:memory log's filename has the PID in it we can not + // use simple equality but instead search for the "about_memory" part of + // the filename which will look like logshake-about_memory-{PID}.json.gz + if (filename.indexOf("about_memory") < 0) { + return; + } + hasAboutMemory = true; + }); + + ok(hasAboutMemory, + "LogShake's asynchronous read of about:memory should have succeeded."); + + run_next_test(); + }, + error => { + LogShake.uninit(); + + ok(false, "Should not have received error: " + error); + + run_next_test(); + }); +}); diff --git a/b2g/components/test/unit/test_signintowebsite.js b/b2g/components/test/unit/test_signintowebsite.js new file mode 100644 index 000000000..38d4fa79e --- /dev/null +++ b/b2g/components/test/unit/test_signintowebsite.js @@ -0,0 +1,322 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Tests for b2g/components/SignInToWebsite.jsm + +"use strict"; + +XPCOMUtils.defineLazyModuleGetter(this, "MinimalIDService", + "resource://gre/modules/identity/MinimalIdentity.jsm", + "IdentityService"); + +XPCOMUtils.defineLazyModuleGetter(this, "SignInToWebsiteController", + "resource://gre/modules/SignInToWebsite.jsm", + "SignInToWebsiteController"); + +Cu.import("resource://gre/modules/identity/LogUtils.jsm"); + +function log(...aMessageArgs) { + Logger.log.apply(Logger, ["test_signintowebsite"].concat(aMessageArgs)); +} + +function test_overall() { + do_check_neq(MinimalIDService, null); + run_next_test(); +} + +function objectContains(object, subset) { + let objectKeys = Object.keys(object); + let subsetKeys = Object.keys(subset); + + // can't have fewer keys than the subset + if (objectKeys.length < subsetKeys.length) { + return false; + } + + let key; + let success = true; + if (subsetKeys.length > 0) { + for (let i=0; i<subsetKeys.length; i++) { + key = subsetKeys[i]; + + // key exists in the source object + if (typeof object[key] === 'undefined') { + success = false; + break; + } + + // recursively check object values + else if (typeof subset[key] === 'object') { + if (typeof object[key] !== 'object') { + success = false; + break; + } + if (! objectContains(object[key], subset[key])) { + success = false; + break; + } + } + + else if (object[key] !== subset[key]) { + success = false; + break; + } + } + } + + return success; +} + +function test_object_contains() { + do_test_pending(); + + let someObj = { + pies: 42, + green: "spam", + flan: {yes: "please"} + }; + let otherObj = { + pies: 42, + flan: {yes: "please"} + }; + do_check_true(objectContains(someObj, otherObj)); + do_test_finished(); + run_next_test(); +} + +function test_mock_doc() { + do_test_pending(); + let mockedDoc = mockDoc({loggedInUser: null}, function(action, params) { + do_check_eq(action, 'coffee'); + do_test_finished(); + run_next_test(); + }); + + // A smoke test to ensure that mockedDoc is functioning correctly. + // There is presently no doCoffee method in Persona. + mockedDoc.doCoffee(); +} + +function test_watch() { + do_test_pending(); + + setup_test_identity("pie@food.gov", TEST_CERT, function() { + let controller = SignInToWebsiteController; + + let mockedDoc = mockDoc({loggedInUser: null}, function(action, params) { + do_check_eq(action, 'ready'); + controller.uninit(); + MinimalIDService.RP.unwatch(mockedDoc.id); + do_test_finished(); + run_next_test(); + }); + + controller.init({pipe: mockReceivingPipe()}); + MinimalIDService.RP.watch(mockedDoc, {}); + }); +} + +function test_request_login() { + do_test_pending(); + + setup_test_identity("flan@food.gov", TEST_CERT, function() { + let controller = SignInToWebsiteController; + + let mockedDoc = mockDoc({loggedInUser: null}, call_sequentially( + function(action, params) { + do_check_eq(action, 'ready'); + do_check_eq(params, undefined); + }, + function(action, params) { + do_check_eq(action, 'login'); + do_check_eq(params, TEST_CERT); + controller.uninit(); + MinimalIDService.RP.unwatch(mockedDoc.id); + do_test_finished(); + run_next_test(); + } + )); + + controller.init({pipe: mockReceivingPipe()}); + MinimalIDService.RP.watch(mockedDoc, {}); + MinimalIDService.RP.request(mockedDoc.id, {}); + }); +} + +function test_request_logout() { + do_test_pending(); + + setup_test_identity("flan@food.gov", TEST_CERT, function() { + let controller = SignInToWebsiteController; + + let mockedDoc = mockDoc({loggedInUser: null}, call_sequentially( + function(action, params) { + do_check_eq(action, 'ready'); + do_check_eq(params, undefined); + }, + function(action, params) { + do_check_eq(action, 'logout'); + do_check_eq(params, undefined); + controller.uninit(); + MinimalIDService.RP.unwatch(mockedDoc.id); + do_test_finished(); + run_next_test(); + } + )); + + controller.init({pipe: mockReceivingPipe()}); + MinimalIDService.RP.watch(mockedDoc, {}); + MinimalIDService.RP.logout(mockedDoc.id, {}); + }); +} + +function test_request_login_logout() { + do_test_pending(); + + setup_test_identity("unagi@food.gov", TEST_CERT, function() { + let controller = SignInToWebsiteController; + + let mockedDoc = mockDoc({loggedInUser: null}, call_sequentially( + function(action, params) { + do_check_eq(action, 'ready'); + do_check_eq(params, undefined); + }, + function(action, params) { + do_check_eq(action, 'login'); + do_check_eq(params, TEST_CERT); + }, + function(action, params) { + do_check_eq(action, 'logout'); + do_check_eq(params, undefined); + controller.uninit(); + MinimalIDService.RP.unwatch(mockedDoc.id); + do_test_finished(); + run_next_test(); + } + )); + + controller.init({pipe: mockReceivingPipe()}); + MinimalIDService.RP.watch(mockedDoc, {}); + MinimalIDService.RP.request(mockedDoc.id, {}); + MinimalIDService.RP.logout(mockedDoc.id, {}); + }); +} + +function test_logout_everywhere() { + do_test_pending(); + let logouts = 0; + + setup_test_identity("fugu@food.gov", TEST_CERT, function() { + let controller = SignInToWebsiteController; + + let mockedDoc1 = mockDoc({loggedInUser: null}, call_sequentially( + function(action, params) { + do_check_eq(action, 'ready'); + }, + function(action, params) { + do_check_eq(action, 'login'); + }, + function(action, params) { + // Result of logout from doc2. + // We don't know what order the logouts will occur in. + do_check_eq(action, 'logout'); + if (++logouts === 2) { + do_test_finished(); + run_next_test(); + } + } + )); + + let mockedDoc2 = mockDoc({loggedInUser: null}, call_sequentially( + function(action, params) { + do_check_eq(action, 'ready'); + }, + function(action, params) { + do_check_eq(action, 'login'); + }, + function(action, params) { + do_check_eq(action, 'logout'); + if (++logouts === 2) { + do_test_finished(); + run_next_test(); + } + } + )); + + controller.init({pipe: mockReceivingPipe()}); + MinimalIDService.RP.watch(mockedDoc1, {}); + MinimalIDService.RP.request(mockedDoc1.id, {}); + + MinimalIDService.RP.watch(mockedDoc2, {}); + MinimalIDService.RP.request(mockedDoc2.id, {}); + + // Logs out of both docs because they share the + // same origin. + MinimalIDService.RP.logout(mockedDoc2.id, {}); + }); +} + +function test_options_pass_through() { + do_test_pending(); + + // An meaningless structure for testing that RP messages preserve + // objects and their parameters as they are passed back and forth. + let randomMixedParams = { + loggedInUser: "juanita@mozilla.com", + forceAuthentication: true, + forceIssuer: "foo.com", + someThing: { + name: "Pertelote", + legs: 4, + nested: {bee: "Eric", remaining: "1/2"} + } + }; + + let mockedDoc = mockDoc(randomMixedParams, function(action, params) {}); + + function pipeOtherEnd(rpOptions, gaiaOptions) { + // Ensure that every time we receive a message, our mixed + // random params are contained in that message + do_check_true(objectContains(rpOptions, randomMixedParams)); + + switch (gaiaOptions.message) { + case "identity-delegate-watch": + MinimalIDService.RP.request(mockedDoc.id, {}); + break; + case "identity-delegate-request": + MinimalIDService.RP.logout(mockedDoc.id, {}); + break; + case "identity-delegate-logout": + do_test_finished(); + controller.uninit(); + MinimalIDService.RP.unwatch(mockedDoc.id); + run_next_test(); + break; + } + } + + let controller = SignInToWebsiteController; + controller.init({pipe: mockSendingPipe(pipeOtherEnd)}); + + MinimalIDService.RP.watch(mockedDoc, {}); +} + +var TESTS = [ + test_overall, + test_mock_doc, + test_object_contains, + + test_watch, + test_request_login, + test_request_logout, + test_request_login_logout, + test_logout_everywhere, + + test_options_pass_through +]; + +TESTS.forEach(add_test); + +function run_test() { + run_next_test(); +} diff --git a/b2g/components/test/unit/xpcshell.ini b/b2g/components/test/unit/xpcshell.ini new file mode 100644 index 000000000..ca3df5bf6 --- /dev/null +++ b/b2g/components/test/unit/xpcshell.ini @@ -0,0 +1,49 @@ +[DEFAULT] +head = +tail = + +support-files = + data/test_logger_file + +[test_bug793310.js] + +[test_bug832946.js] + +[test_fxaccounts.js] +[test_signintowebsite.js] +head = head_identity.js +tail = + +# testing non gonk-specific stuff +[test_logcapture.js] + +[test_logcapture_gonk.js] +# can be slow because of what the test does, so let's give it some more time +# to avoid intermittents: bug 1212395 +requesttimeoutfactor = 2 +# only run on b2g builds due to requiring b2g-specific log files to exist +skip-if = toolkit != "gonk" + +[test_logparser.js] + +[test_logshake.js] + +[test_logshake_gonk.js] +# can be slow because of what the test does, so let's give it some more time +# to avoid intermittents: bug 1144499 +requesttimeoutfactor = 2 +head = head_logshake_gonk.js +# only run on b2g builds due to requiring b2g-specific log files to exist +skip-if = (toolkit != "gonk") + +[test_logshake_gonk_compression.js] +head = head_logshake_gonk.js +# only run on b2g builds due to requiring b2g-specific log files to exist +skip-if = (toolkit != "gonk") + +[test_logshake_readLog_gonk.js] +head = head_logshake_gonk.js +# only run on b2g builds due to requiring b2g-specific log files to exist +skip-if = (toolkit != "gonk") + +[test_aboutserviceworkers.js] |