test_alt-data_stream.js (4773B)
1 /** 2 * Test for the "alternative data stream" stored withing a cache entry. 3 * 4 * - we load a URL with preference for an alt data (check what we get is the raw data, 5 * since there was nothing previously cached) 6 * - we write a big chunk of alt-data to the output stream 7 * - we load the URL again, expecting to get alt-data 8 * - we check that the alt-data is streamed. We should get the first chunk, then 9 * the rest of the alt-data is written, and we check that it is received in 10 * the proper order. 11 * 12 */ 13 14 "use strict"; 15 16 const { HttpServer } = ChromeUtils.importESModule( 17 "resource://testing-common/httpd.sys.mjs" 18 ); 19 20 ChromeUtils.defineLazyGetter(this, "URL", function () { 21 return "http://localhost:" + httpServer.identity.primaryPort + "/content"; 22 }); 23 24 var httpServer = null; 25 26 function make_channel(url) { 27 return NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true }); 28 } 29 30 const responseContent = "response body"; 31 // We need a large content in order to make sure that the IPDL stream is cut 32 // into several different chunks. 33 // We fill each chunk with a different character for easy debugging. 34 const altContent = 35 "a".repeat(128 * 1024) + 36 "b".repeat(128 * 1024) + 37 "c".repeat(128 * 1024) + 38 "d".repeat(128 * 1024) + 39 "e".repeat(128 * 1024) + 40 "f".repeat(128 * 1024) + 41 "g".repeat(128 * 1024) + 42 "h".repeat(128 * 1024) + 43 "i".repeat(13); // Just so the chunk size doesn't match exactly. 44 45 const firstChunkSize = Math.floor(altContent.length / 4); 46 const altContentType = "text/binary"; 47 48 function contentHandler(metadata, response) { 49 response.setHeader("Content-Type", "text/plain"); 50 response.setHeader("Cache-Control", "max-age=86400"); 51 52 response.bodyOutputStream.write(responseContent, responseContent.length); 53 } 54 55 function run_test() { 56 do_get_profile(); 57 httpServer = new HttpServer(); 58 httpServer.registerPathHandler("/content", contentHandler); 59 httpServer.start(-1); 60 61 var chan = make_channel(URL); 62 63 var cc = chan.QueryInterface(Ci.nsICacheInfoChannel); 64 cc.preferAlternativeDataType( 65 altContentType, 66 "", 67 Ci.nsICacheInfoChannel.ASYNC 68 ); 69 70 chan.asyncOpen(new ChannelListener(readServerContent, null)); 71 do_test_pending(); 72 } 73 74 // Output stream used to write alt-data to the cache entry. 75 var os; 76 77 function readServerContent(request, buffer) { 78 var cc = request.QueryInterface(Ci.nsICacheInfoChannel); 79 80 Assert.equal(buffer, responseContent); 81 Assert.equal(cc.alternativeDataType, ""); 82 83 executeSoon(() => { 84 os = cc.openAlternativeOutputStream(altContentType, altContent.length); 85 // Write a quarter of the alt data content 86 os.write(altContent, firstChunkSize); 87 88 executeSoon(openAltChannel); 89 }); 90 } 91 92 function openAltChannel() { 93 var chan = make_channel(URL); 94 var cc = chan.QueryInterface(Ci.nsICacheInfoChannel); 95 cc.preferAlternativeDataType( 96 altContentType, 97 "", 98 Ci.nsICacheInfoChannel.ASYNC 99 ); 100 101 chan.asyncOpen(altDataListener); 102 } 103 104 var altDataListener = { 105 buffer: "", 106 onStartRequest() {}, 107 onDataAvailable(request, stream, offset, count) { 108 let string = NetUtil.readInputStreamToString(stream, count); 109 this.buffer += string; 110 111 // XXX: this condition might be a bit volatile. If this test times out, 112 // it probably means that for some reason, the listener didn't get all the 113 // data in the first chunk. 114 if (this.buffer.length == firstChunkSize) { 115 // write the rest of the content 116 os.write( 117 altContent.substring(firstChunkSize, altContent.length), 118 altContent.length - firstChunkSize 119 ); 120 os.close(); 121 } 122 }, 123 onStopRequest(request) { 124 var cc = request.QueryInterface(Ci.nsICacheInfoChannel); 125 Assert.equal(cc.alternativeDataType, altContentType); 126 Assert.equal(this.buffer.length, altContent.length); 127 Assert.equal(this.buffer, altContent); 128 openAltChannelWithOriginalContent(); 129 }, 130 }; 131 132 function openAltChannelWithOriginalContent() { 133 var chan = make_channel(URL); 134 var cc = chan.QueryInterface(Ci.nsICacheInfoChannel); 135 cc.preferAlternativeDataType( 136 altContentType, 137 "", 138 Ci.nsICacheInfoChannel.SERIALIZE 139 ); 140 141 chan.asyncOpen(originalListener); 142 } 143 144 var originalListener = { 145 buffer: "", 146 onStartRequest() {}, 147 onDataAvailable(request, stream, offset, count) { 148 let string = NetUtil.readInputStreamToString(stream, count); 149 this.buffer += string; 150 }, 151 onStopRequest(request) { 152 var cc = request.QueryInterface(Ci.nsICacheInfoChannel); 153 Assert.equal(cc.alternativeDataType, altContentType); 154 Assert.equal(this.buffer.length, responseContent.length); 155 Assert.equal(this.buffer, responseContent); 156 testAltDataStream(cc); 157 }, 158 }; 159 160 function testAltDataStream(cc) { 161 Assert.ok(!!cc.alternativeDataInputStream); 162 httpServer.stop(do_test_finished); 163 }