diff options
Diffstat (limited to 'netwerk/test/unit/test_suspend_channel_on_modified.js')
-rw-r--r-- | netwerk/test/unit/test_suspend_channel_on_modified.js | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/netwerk/test/unit/test_suspend_channel_on_modified.js b/netwerk/test/unit/test_suspend_channel_on_modified.js new file mode 100644 index 000000000..a4f7c221e --- /dev/null +++ b/netwerk/test/unit/test_suspend_channel_on_modified.js @@ -0,0 +1,175 @@ +// This file tests async handling of a channel suspended in http-on-modify-request. + +var CC = Components.Constructor; + +Cu.import("resource://testing-common/httpd.js"); +Cu.import("resource://gre/modules/NetUtil.jsm"); + +var obs = Cc["@mozilla.org/observer-service;1"] + .getService(Ci.nsIObserverService); + +var ios = Cc["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + +// baseUrl is always the initial connection attempt and is handled by +// failResponseHandler since every test expects that request will either be +// redirected or cancelled. +var baseUrl; + +function failResponseHandler(metadata, response) +{ + var text = "failure response"; + response.setHeader("Content-Type", "text/plain", false); + response.bodyOutputStream.write(text, text.length); + do_check_true(false, "Received request when we shouldn't."); +} + +function successResponseHandler(metadata, response) +{ + var text = "success response"; + response.setHeader("Content-Type", "text/plain", false); + response.bodyOutputStream.write(text, text.length); + do_check_true(true, "Received expected request."); +} + +function onModifyListener(callback) { + obs.addObserver({ + observe: function(subject, topic, data) { + var obs = Cc["@mozilla.org/observer-service;1"].getService(); + obs = obs.QueryInterface(Ci.nsIObserverService); + obs.removeObserver(this, "http-on-modify-request"); + callback(subject.QueryInterface(Ci.nsIHttpChannel)); + } + }, "http-on-modify-request", false); +} + +function startChannelRequest(baseUrl, flags, expectedResponse=null) { + var chan = NetUtil.newChannel({ + uri: baseUrl, + loadUsingSystemPrincipal: true + }); + chan.asyncOpen2(new ChannelListener((request, data, context) => { + if (expectedResponse) { + do_check_eq(data, expectedResponse); + } else { + do_check_true(!!!data, "no response"); + } + do_execute_soon(run_next_test) + }, null, flags)); +} + + +add_test(function testSimpleRedirect() { + onModifyListener(chan => { + chan.redirectTo(ios.newURI(`${baseUrl}/success`)); + }); + startChannelRequest(baseUrl, undefined, "success response"); +}); + +add_test(function testSimpleCancel() { + onModifyListener(chan => { + chan.cancel(Cr.NS_BINDING_ABORTED); + }); + startChannelRequest(baseUrl, CL_EXPECT_FAILURE); +}); + +add_test(function testSimpleCancelRedirect() { + onModifyListener(chan => { + chan.redirectTo(ios.newURI(`${baseUrl}/fail`)); + chan.cancel(Cr.NS_BINDING_ABORTED); + }); + startChannelRequest(baseUrl, CL_EXPECT_FAILURE); +}); + +// Test a request that will get redirected asynchronously. baseUrl should +// not be requested, we should receive the request for the redirectedUrl. +add_test(function testAsyncRedirect() { + onModifyListener(chan => { + // Suspend the channel then yield to make this async. + chan.suspend(); + Promise.resolve().then(() => { + chan.redirectTo(ios.newURI(`${baseUrl}/success`)); + chan.resume(); + }); + }); + startChannelRequest(baseUrl, undefined, "success response"); +}); + +add_test(function testSyncRedirect() { + onModifyListener(chan => { + chan.suspend(); + chan.redirectTo(ios.newURI(`${baseUrl}/success`)); + Promise.resolve().then(() => { + chan.resume(); + }); + }); + startChannelRequest(baseUrl, undefined, "success response"); +}); + +add_test(function testAsyncCancel() { + onModifyListener(chan => { + // Suspend the channel then yield to make this async. + chan.suspend(); + Promise.resolve().then(() => { + chan.cancel(Cr.NS_BINDING_ABORTED); + chan.resume(); + }); + }); + startChannelRequest(baseUrl, CL_EXPECT_FAILURE); +}); + +add_test(function testSyncCancel() { + onModifyListener(chan => { + chan.suspend(); + chan.cancel(Cr.NS_BINDING_ABORTED); + Promise.resolve().then(() => { + chan.resume(); + }); + }); + startChannelRequest(baseUrl, CL_EXPECT_FAILURE); +}); + +// Test request that will get redirected and cancelled asynchronously, +// ensure no connection is made. +add_test(function testAsyncCancelRedirect() { + onModifyListener(chan => { + // Suspend the channel then yield to make this async. + chan.suspend(); + Promise.resolve().then(() => { + chan.cancel(Cr.NS_BINDING_ABORTED); + chan.redirectTo(ios.newURI(`${baseUrl}/fail`)); + chan.resume(); + }); + }); + startChannelRequest(baseUrl, CL_EXPECT_FAILURE); +}); + +// Test a request that will get cancelled synchronously, ensure async redirect +// is not made. +add_test(function testSyncCancelRedirect() { + onModifyListener(chan => { + chan.suspend(); + chan.cancel(Cr.NS_BINDING_ABORTED); + Promise.resolve().then(() => { + chan.redirectTo(ios.newURI(`${baseUrl}/fail`)); + chan.resume(); + }); + }); + startChannelRequest(baseUrl, CL_EXPECT_FAILURE); +}); + +function run_test() { + var httpServer = new HttpServer(); + httpServer.registerPathHandler("/", failResponseHandler); + httpServer.registerPathHandler("/fail", failResponseHandler); + httpServer.registerPathHandler("/success", successResponseHandler); + httpServer.start(-1); + + baseUrl = `http://localhost:${httpServer.identity.primaryPort}`; + + run_next_test(); + + do_register_cleanup(function(){ + httpServer.stop(() => {}); + }); +} |