"use strict"; var CC = Components.Constructor; const StreamCopier = CC( "@mozilla.org/network/async-stream-copier;1", "nsIAsyncStreamCopier", "init" ); const ScriptableInputStream = CC( "@mozilla.org/scriptableinputstream;1", "nsIScriptableInputStream", "init" ); const Pipe = CC("@mozilla.org/pipe;1", "nsIPipe", "init"); var pipe1; var pipe2; var copier; var test_result; var test_content; var test_source_closed; var test_sink_closed; var test_nr; var copyObserver = { onStartRequest(request) {}, onStopRequest(request, statusCode) { // check status code Assert.equal(statusCode, test_result); // check number of copied bytes Assert.equal(pipe2.inputStream.available(), test_content.length); // check content var scinp = new ScriptableInputStream(pipe2.inputStream); var content = scinp.read(scinp.available()); Assert.equal(content, test_content); // check closed sink try { pipe2.outputStream.write("closedSinkTest", 14); Assert.ok(!test_sink_closed); } catch (ex) { Assert.ok(test_sink_closed); } // check closed source try { pipe1.outputStream.write("closedSourceTest", 16); Assert.ok(!test_source_closed); } catch (ex) { Assert.ok(test_source_closed); } do_timeout(0, do_test); }, QueryInterface: ChromeUtils.generateQI(["nsIRequestObserver"]), }; function startCopier(closeSource, closeSink) { pipe1 = new Pipe( true /* nonBlockingInput */, true /* nonBlockingOutput */, 0 /* segmentSize */, 0xffffffff /* segmentCount */, null /* segmentAllocator */ ); pipe2 = new Pipe( true /* nonBlockingInput */, true /* nonBlockingOutput */, 0 /* segmentSize */, 0xffffffff /* segmentCount */, null /* segmentAllocator */ ); copier = new StreamCopier( pipe1.inputStream /* aSource */, pipe2.outputStream /* aSink */, null /* aTarget */, true /* aSourceBuffered */, true /* aSinkBuffered */, 8192 /* aChunkSize */, closeSource /* aCloseSource */, closeSink /* aCloseSink */ ); copier.asyncCopy(copyObserver, null); } function do_test() { test_nr++; test_content = "test" + test_nr; switch (test_nr) { case 1: case 2: // close sink case 3: // close source case 4: // close both // test canceling transfer // use some undefined error code to check if it is successfully passed // to the request observer test_result = 0x87654321; test_source_closed = (test_nr - 1) >> 1 != 0; test_sink_closed = (test_nr - 1) % 2 != 0; startCopier(test_source_closed, test_sink_closed); pipe1.outputStream.write(test_content, test_content.length); pipe1.outputStream.flush(); do_timeout(20, function() { copier.cancel(test_result); pipe1.outputStream.write("a", 1); }); break; case 5: case 6: // close sink case 7: // close source case 8: // close both // test copying with EOF on source test_result = 0; test_source_closed = (test_nr - 5) >> 1 != 0; test_sink_closed = (test_nr - 5) % 2 != 0; startCopier(test_source_closed, test_sink_closed); pipe1.outputStream.write(test_content, test_content.length); // we will close the source test_source_closed = true; pipe1.outputStream.close(); break; case 9: case 10: // close sink case 11: // close source case 12: // close both // test copying with error on sink // use some undefined error code to check if it is successfully passed // to the request observer test_result = 0x87654321; test_source_closed = (test_nr - 9) >> 1 != 0; test_sink_closed = (test_nr - 9) % 2 != 0; startCopier(test_source_closed, test_sink_closed); pipe1.outputStream.write(test_content, test_content.length); pipe1.outputStream.flush(); // we will close the sink test_sink_closed = true; do_timeout(20, function() { pipe2.outputStream .QueryInterface(Ci.nsIAsyncOutputStream) .closeWithStatus(test_result); pipe1.outputStream.write("a", 1); }); break; case 13: do_test_finished(); break; } } function run_test() { test_nr = 0; do_timeout(0, do_test); do_test_pending(); }