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