/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ { let dummyCallback = () => {}; let mockWebSocket = new MockWebSocketChannel(); let pushServerRequestCount = 0; add_test(function test_initalize_offline() { Services.io.offline = true; do_check_false(MozLoopPushHandler.initialize()); Services.io.offline = false; run_next_test(); }); add_test(function test_initalize_missing_chanid() { Assert.throws(() => MozLoopPushHandler.register(null, dummyCallback, dummyCallback)); run_next_test(); }); add_test(function test_initalize_missing_regcallback() { Assert.throws(() => MozLoopPushHandler.register("chan-1", null, dummyCallback)); run_next_test(); }); add_test(function test_initalize_missing_notifycallback() { Assert.throws(() => MozLoopPushHandler.register("chan-1", dummyCallback, null)); run_next_test(); }); add_test(function test_initalize_websocket() { do_check_true(MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket})); MozLoopPushHandler.register( "chan-1", function(err, url, id) { Assert.equal(err, null, "err should be null to indicate success"); Assert.equal(url, kEndPointUrl, "Should return push server application URL"); Assert.equal(id, "chan-1", "Should have channel id = chan-1"); Assert.equal(mockWebSocket.uri.prePath, kServerPushUrl, "Should have the url from preferences"); Assert.equal(mockWebSocket.origin, kServerPushUrl, "Should have the origin url from preferences"); Assert.equal(mockWebSocket.protocol, "push-notification", "Should have the protocol set to push-notifications"); mockWebSocket.notify(15); }, function(version, id) { Assert.equal(version, 15, "Should have version number 15"); Assert.equal(id, "chan-1", "Should have channel id = chan-1"); run_next_test(); }); }); add_test(function test_register_twice_same_channel() { MozLoopPushHandler.register( "chan-2", function(err, url, id) { Assert.equal(err, null, "Should return null for success"); Assert.equal(url, kEndPointUrl, "Should return push server application URL"); Assert.equal(id, "chan-2", "Should have channel id = chan-2"); Assert.equal(mockWebSocket.uri.prePath, kServerPushUrl, "Should have the url from preferences"); Assert.equal(mockWebSocket.origin, kServerPushUrl, "Should have the origin url from preferences"); Assert.equal(mockWebSocket.protocol, "push-notification", "Should have the protocol set to push-notifications"); // Register again for the same channel MozLoopPushHandler.register( "chan-2", function(err, url, id) { Assert.equal(err, null, "Should return null for success"); Assert.equal(id, "chan-2", "Should have channel id = chan-2"); run_next_test(); }, dummyCallback ); }, dummyCallback ); }); // Test that the PushHander will re-connect after the near-end disconnect. // The uaID is cleared to force re-registration of all notification channels. add_test(function test_reconnect_websocket() { MozLoopPushHandler.uaID = undefined; mockWebSocket.stop(); // Previously registered onRegistration callbacks will fire and be checked (see above). }); // Test that the PushHander will re-connect after the far-end disconnect. // The uaID is cleared to force re-regsitration of all notification channels. add_test(function test_reopen_websocket() { MozLoopPushHandler.uaID = undefined; MozLoopPushHandler.registeredChannels = {}; //Do this to force a new registration callback. mockWebSocket.serverClose(); // Previously registered onRegistration callbacks will fire and be checked (see above). }); // Force a re-registration cycle and have the PushServer return a 500. // A retry should occur and the registration then complete. add_test(function test_retry_registration() { MozLoopPushHandler.uaID = undefined; mockWebSocket.initRegStatus = 500; mockWebSocket.stop(); }); add_test(function test_reconnect_no_registration() { let regCnt = 0; MozLoopPushHandler.shutdown(); MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket}); MozLoopPushHandler.register( "test-chan", function(err, url, id) { Assert.equal(++regCnt, 1, "onRegistered should only be called once"); Assert.equal(err, null, "err should be null to indicate success"); Assert.equal(url, kEndPointUrl, "Should return push server application URL"); Assert.equal(id, "test-chan", "Should have channel id = test-chan"); mockWebSocket.stop(); setTimeout(run_next_test(), 0); }, dummyCallback ); }); add_test(function test_ping_websocket() { let pingReceived = false, socketClosed = false; mockWebSocket.defaultMsgHandler = (msg) => { pingReceived = true; // Do not send a ping response. } mockWebSocket.close = () => { socketClosed = true; } MozLoopPushHandler.shutdown(); MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket}); MozLoopPushHandler.register( "test-chan", function(err, url) { Assert.equal(err, null, "err should be null to indicate success"); waitForCondition(() => pingReceived).then(() => { waitForCondition(() => socketClosed).then(() => { run_next_test(); }, () => { do_throw("should have closed the websocket"); }); }, () => { do_throw("should have sent ping"); }); }, dummyCallback ); }); add_test(function test_retry_pushurl() { MozLoopPushHandler.shutdown(); loopServer.registerPathHandler("/push-server-config", (request, response) => { // The PushHandler should retry the request for the push-server-config for // each of these cases without throwing an error. let n = 0; switch (++pushServerRequestCount) { case ++n: // Non-200 response response.setStatusLine(null, 500, "Retry"); response.processAsync(); response.finish(); break; case ++n: // missing parameter response.setStatusLine(null, 200, "OK"); response.write(JSON.stringify({pushServerURI: null})); response.processAsync(); response.finish(); break; case ++n: // json parse error response.setStatusLine(null, 200, "OK"); response.processAsync(); response.finish(); break; case ++n: response.setStatusLine(null, 200, "OK"); response.write(JSON.stringify({pushServerURI: kServerPushUrl})); response.processAsync(); response.finish(); run_next_test(); break; } }); do_check_true(MozLoopPushHandler.initialize({mockWebSocket: mockWebSocket})); }); function run_test() { setupFakeLoopServer(); loopServer.registerPathHandler("/push-server-config", (request, response) => { response.setStatusLine(null, 200, "OK"); response.write(JSON.stringify({pushServerURI: kServerPushUrl})); response.processAsync(); response.finish(); }); Services.prefs.setCharPref("services.push.serverURL", kServerPushUrl); Services.prefs.setIntPref("loop.retry_delay.start", 10); // 10 ms Services.prefs.setIntPref("loop.retry_delay.limit", 20); // 20 ms Services.prefs.setIntPref("loop.ping.interval", 50); // 50 ms Services.prefs.setIntPref("loop.ping.timeout", 20); // 20 ms do_register_cleanup(function() { Services.prefs.clearUserPref("services.push.serverULR"); Services.prefs.clearUserPref("loop.retry_delay.start"); Services.prefs.clearUserPref("loop.retry_delay.limit"); Services.prefs.clearUserPref("loop.ping.interval"); Services.prefs.clearUserPref("loop.ping.timeout"); }); run_next_test(); }; }