Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | // |
michael@0 | 2 | // This test makes sure range-requests are sent and treated the way we want |
michael@0 | 3 | // See bug #612135 for a thorough discussion on the subject |
michael@0 | 4 | // |
michael@0 | 5 | // Necko does a range-request for a partial cache-entry iff |
michael@0 | 6 | // |
michael@0 | 7 | // 1) size of the cached entry < value of the cached Content-Length header |
michael@0 | 8 | // (not tested here - see bug #612135 comments 108-110) |
michael@0 | 9 | // 2) the size of the cached entry is > 0 (see bug #628607) |
michael@0 | 10 | // 3) the cached entry does not have a "no-store" Cache-Control header |
michael@0 | 11 | // 4) the cached entry does not have a Content-Encoding (see bug #613159) |
michael@0 | 12 | // 5) the request does not have a conditional-request header set by client |
michael@0 | 13 | // 6) nsHttpResponseHead::IsResumable() is true for the cached entry |
michael@0 | 14 | // 7) a basic positive test that makes sure byte ranges work |
michael@0 | 15 | // 8) ensure NS_ERROR_CORRUPTED_CONTENT is thrown when total entity size |
michael@0 | 16 | // of 206 does not match content-length of 200 |
michael@0 | 17 | // |
michael@0 | 18 | // The test has one handler for each case and run_tests() fires one request |
michael@0 | 19 | // for each. None of the handlers should see a Range-header. |
michael@0 | 20 | |
michael@0 | 21 | Cu.import("resource://testing-common/httpd.js"); |
michael@0 | 22 | |
michael@0 | 23 | var httpserver = null; |
michael@0 | 24 | |
michael@0 | 25 | const clearTextBody = "This is a slightly longer test\n"; |
michael@0 | 26 | const encodedBody = [0x1f, 0x8b, 0x08, 0x08, 0xef, 0x70, 0xe6, 0x4c, 0x00, 0x03, 0x74, 0x65, 0x78, 0x74, 0x66, 0x69, |
michael@0 | 27 | 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, 0x00, 0x0b, 0xc9, 0xc8, 0x2c, 0x56, 0x00, 0xa2, 0x44, 0x85, |
michael@0 | 28 | 0xe2, 0x9c, 0xcc, 0xf4, 0x8c, 0x92, 0x9c, 0x4a, 0x85, 0x9c, 0xfc, 0xbc, 0xf4, 0xd4, 0x22, 0x85, |
michael@0 | 29 | 0x92, 0xd4, 0xe2, 0x12, 0x2e, 0x2e, 0x00, 0x00, 0xe5, 0xe6, 0xf0, 0x20, 0x00, 0x00, 0x00]; |
michael@0 | 30 | const decodedBody = [0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x73, 0x6c, 0x69, 0x67, 0x68, 0x74, |
michael@0 | 31 | 0x6c, 0x79, 0x20, 0x6c, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x20, 0x74, 0x65, 0x73, 0x74, 0x0a, 0x0a]; |
michael@0 | 32 | |
michael@0 | 33 | const partial_data_length = 4; |
michael@0 | 34 | var port = null; // set in run_test |
michael@0 | 35 | |
michael@0 | 36 | function make_channel(url, callback, ctx) { |
michael@0 | 37 | var ios = Cc["@mozilla.org/network/io-service;1"]. |
michael@0 | 38 | getService(Ci.nsIIOService); |
michael@0 | 39 | var chan = ios.newChannel(url, "", null); |
michael@0 | 40 | return chan.QueryInterface(Ci.nsIHttpChannel); |
michael@0 | 41 | } |
michael@0 | 42 | |
michael@0 | 43 | // StreamListener which cancels its request on first data available |
michael@0 | 44 | function Canceler(continueFn) { |
michael@0 | 45 | this.continueFn = continueFn; |
michael@0 | 46 | } |
michael@0 | 47 | Canceler.prototype = { |
michael@0 | 48 | QueryInterface: function(iid) { |
michael@0 | 49 | if (iid.equals(Ci.nsIStreamListener) || |
michael@0 | 50 | iid.equals(Ci.nsIRequestObserver) || |
michael@0 | 51 | iid.equals(Ci.nsISupports)) |
michael@0 | 52 | return this; |
michael@0 | 53 | throw Components.results.NS_ERROR_NO_INTERFACE; |
michael@0 | 54 | }, |
michael@0 | 55 | onStartRequest: function(request, context) { }, |
michael@0 | 56 | |
michael@0 | 57 | onDataAvailable: function(request, context, stream, offset, count) { |
michael@0 | 58 | request.QueryInterface(Ci.nsIChannel) |
michael@0 | 59 | .cancel(Components.results.NS_BINDING_ABORTED); |
michael@0 | 60 | }, |
michael@0 | 61 | onStopRequest: function(request, context, status) { |
michael@0 | 62 | do_check_eq(status, Components.results.NS_BINDING_ABORTED); |
michael@0 | 63 | this.continueFn(request, null); |
michael@0 | 64 | } |
michael@0 | 65 | }; |
michael@0 | 66 | // Simple StreamListener which performs no validations |
michael@0 | 67 | function MyListener(continueFn) { |
michael@0 | 68 | this.continueFn = continueFn; |
michael@0 | 69 | this._buffer = null; |
michael@0 | 70 | } |
michael@0 | 71 | MyListener.prototype = { |
michael@0 | 72 | QueryInterface: function(iid) { |
michael@0 | 73 | if (iid.equals(Ci.nsIStreamListener) || |
michael@0 | 74 | iid.equals(Ci.nsIRequestObserver) || |
michael@0 | 75 | iid.equals(Ci.nsISupports)) |
michael@0 | 76 | return this; |
michael@0 | 77 | throw Components.results.NS_ERROR_NO_INTERFACE; |
michael@0 | 78 | }, |
michael@0 | 79 | onStartRequest: function(request, context) { this._buffer = ""; }, |
michael@0 | 80 | |
michael@0 | 81 | onDataAvailable: function(request, context, stream, offset, count) { |
michael@0 | 82 | this._buffer = this._buffer.concat(read_stream(stream, count)); |
michael@0 | 83 | }, |
michael@0 | 84 | onStopRequest: function(request, context, status) { |
michael@0 | 85 | this.continueFn(request, this._buffer); |
michael@0 | 86 | } |
michael@0 | 87 | }; |
michael@0 | 88 | |
michael@0 | 89 | var case_8_range_request = false; |
michael@0 | 90 | function FailedChannelListener(continueFn) { |
michael@0 | 91 | this.continueFn = continueFn; |
michael@0 | 92 | } |
michael@0 | 93 | FailedChannelListener.prototype = { |
michael@0 | 94 | QueryInterface: function(iid) { |
michael@0 | 95 | if (iid.equals(Ci.nsIStreamListener) || |
michael@0 | 96 | iid.equals(Ci.nsIRequestObserver) || |
michael@0 | 97 | iid.equals(Ci.nsISupports)) |
michael@0 | 98 | return this; |
michael@0 | 99 | throw Components.results.NS_ERROR_NO_INTERFACE; |
michael@0 | 100 | }, |
michael@0 | 101 | onStartRequest: function(request, context) { }, |
michael@0 | 102 | |
michael@0 | 103 | onDataAvailable: function(request, context, stream, offset, count) { }, |
michael@0 | 104 | |
michael@0 | 105 | onStopRequest: function(request, context, status) { |
michael@0 | 106 | if (case_8_range_request) |
michael@0 | 107 | do_check_eq(status, Components.results.NS_ERROR_CORRUPTED_CONTENT); |
michael@0 | 108 | this.continueFn(request, null); |
michael@0 | 109 | } |
michael@0 | 110 | }; |
michael@0 | 111 | |
michael@0 | 112 | function received_cleartext(request, data) { |
michael@0 | 113 | do_check_eq(clearTextBody, data); |
michael@0 | 114 | testFinished(); |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | function setStdHeaders(response, length) { |
michael@0 | 118 | response.setHeader("Content-Type", "text/plain", false); |
michael@0 | 119 | response.setHeader("ETag", "Just testing"); |
michael@0 | 120 | response.setHeader("Cache-Control", "max-age: 360000"); |
michael@0 | 121 | response.setHeader("Accept-Ranges", "bytes"); |
michael@0 | 122 | response.setHeader("Content-Length", "" + length); |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | function handler_2(metadata, response) { |
michael@0 | 126 | setStdHeaders(response, clearTextBody.length); |
michael@0 | 127 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 128 | response.bodyOutputStream.write(clearTextBody, clearTextBody.length); |
michael@0 | 129 | } |
michael@0 | 130 | function received_partial_2(request, data) { |
michael@0 | 131 | do_check_eq(data, undefined); |
michael@0 | 132 | var chan = make_channel("http://localhost:" + port + "/test_2"); |
michael@0 | 133 | chan.asyncOpen(new ChannelListener(received_cleartext, null), null); |
michael@0 | 134 | } |
michael@0 | 135 | |
michael@0 | 136 | var case_3_request_no = 0; |
michael@0 | 137 | function handler_3(metadata, response) { |
michael@0 | 138 | var body = clearTextBody; |
michael@0 | 139 | setStdHeaders(response, body.length); |
michael@0 | 140 | response.setHeader("Cache-Control", "no-store", false); |
michael@0 | 141 | switch (case_3_request_no) { |
michael@0 | 142 | case 0: |
michael@0 | 143 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 144 | body = body.slice(0, partial_data_length); |
michael@0 | 145 | response.processAsync(); |
michael@0 | 146 | response.bodyOutputStream.write(body, body.length); |
michael@0 | 147 | response.finish(); |
michael@0 | 148 | break; |
michael@0 | 149 | case 1: |
michael@0 | 150 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 151 | response.bodyOutputStream.write(body, body.length); |
michael@0 | 152 | break; |
michael@0 | 153 | default: |
michael@0 | 154 | response.setStatusLine(metadata.httpVersion, 404, "Not Found"); |
michael@0 | 155 | } |
michael@0 | 156 | case_3_request_no++; |
michael@0 | 157 | } |
michael@0 | 158 | function received_partial_3(request, data) { |
michael@0 | 159 | do_check_eq(partial_data_length, data.length); |
michael@0 | 160 | var chan = make_channel("http://localhost:" + port + "/test_3"); |
michael@0 | 161 | chan.asyncOpen(new ChannelListener(received_cleartext, null), null); |
michael@0 | 162 | } |
michael@0 | 163 | |
michael@0 | 164 | var case_4_request_no = 0; |
michael@0 | 165 | function handler_4(metadata, response) { |
michael@0 | 166 | switch (case_4_request_no) { |
michael@0 | 167 | case 0: |
michael@0 | 168 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 169 | var body = encodedBody; |
michael@0 | 170 | setStdHeaders(response, body.length); |
michael@0 | 171 | response.setHeader("Content-Encoding", "gzip", false); |
michael@0 | 172 | body = body.slice(0, partial_data_length); |
michael@0 | 173 | var bos = Cc["@mozilla.org/binaryoutputstream;1"] |
michael@0 | 174 | .createInstance(Ci.nsIBinaryOutputStream); |
michael@0 | 175 | bos.setOutputStream(response.bodyOutputStream); |
michael@0 | 176 | response.processAsync(); |
michael@0 | 177 | bos.writeByteArray(body, body.length); |
michael@0 | 178 | response.finish(); |
michael@0 | 179 | break; |
michael@0 | 180 | case 1: |
michael@0 | 181 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 182 | setStdHeaders(response, clearTextBody.length); |
michael@0 | 183 | response.bodyOutputStream.write(clearTextBody, clearTextBody.length); |
michael@0 | 184 | break; |
michael@0 | 185 | default: |
michael@0 | 186 | response.setStatusLine(metadata.httpVersion, 404, "Not Found"); |
michael@0 | 187 | } |
michael@0 | 188 | case_4_request_no++; |
michael@0 | 189 | } |
michael@0 | 190 | function received_partial_4(request, data) { |
michael@0 | 191 | // checking length does not work with encoded data |
michael@0 | 192 | // do_check_eq(partial_data_length, data.length); |
michael@0 | 193 | var chan = make_channel("http://localhost:" + port + "/test_4"); |
michael@0 | 194 | chan.asyncOpen(new MyListener(received_cleartext), null); |
michael@0 | 195 | } |
michael@0 | 196 | |
michael@0 | 197 | var case_5_request_no = 0; |
michael@0 | 198 | function handler_5(metadata, response) { |
michael@0 | 199 | var body = clearTextBody; |
michael@0 | 200 | setStdHeaders(response, body.length); |
michael@0 | 201 | switch (case_5_request_no) { |
michael@0 | 202 | case 0: |
michael@0 | 203 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 204 | body = body.slice(0, partial_data_length); |
michael@0 | 205 | response.processAsync(); |
michael@0 | 206 | response.bodyOutputStream.write(body, body.length); |
michael@0 | 207 | response.finish(); |
michael@0 | 208 | break; |
michael@0 | 209 | case 1: |
michael@0 | 210 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 211 | response.bodyOutputStream.write(body, body.length); |
michael@0 | 212 | break; |
michael@0 | 213 | default: |
michael@0 | 214 | response.setStatusLine(metadata.httpVersion, 404, "Not Found"); |
michael@0 | 215 | } |
michael@0 | 216 | case_5_request_no++; |
michael@0 | 217 | } |
michael@0 | 218 | function received_partial_5(request, data) { |
michael@0 | 219 | do_check_eq(partial_data_length, data.length); |
michael@0 | 220 | var chan = make_channel("http://localhost:" + port + "/test_5"); |
michael@0 | 221 | chan.setRequestHeader("If-Match", "Some eTag", false); |
michael@0 | 222 | chan.asyncOpen(new ChannelListener(received_cleartext, null), null); |
michael@0 | 223 | } |
michael@0 | 224 | |
michael@0 | 225 | var case_6_request_no = 0; |
michael@0 | 226 | function handler_6(metadata, response) { |
michael@0 | 227 | switch (case_6_request_no) { |
michael@0 | 228 | case 0: |
michael@0 | 229 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 230 | var body = clearTextBody; |
michael@0 | 231 | setStdHeaders(response, body.length); |
michael@0 | 232 | response.setHeader("Accept-Ranges", "", false); |
michael@0 | 233 | body = body.slice(0, partial_data_length); |
michael@0 | 234 | response.processAsync(); |
michael@0 | 235 | response.bodyOutputStream.write(body, body.length); |
michael@0 | 236 | response.finish(); |
michael@0 | 237 | break; |
michael@0 | 238 | case 1: |
michael@0 | 239 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 240 | setStdHeaders(response, clearTextBody.length); |
michael@0 | 241 | response.bodyOutputStream.write(clearTextBody, clearTextBody.length); |
michael@0 | 242 | break; |
michael@0 | 243 | default: |
michael@0 | 244 | response.setStatusLine(metadata.httpVersion, 404, "Not Found"); |
michael@0 | 245 | } |
michael@0 | 246 | case_6_request_no++; |
michael@0 | 247 | } |
michael@0 | 248 | function received_partial_6(request, data) { |
michael@0 | 249 | // would like to verify that the response does not have Accept-Ranges |
michael@0 | 250 | do_check_eq(partial_data_length, data.length); |
michael@0 | 251 | var chan = make_channel("http://localhost:" + port + "/test_6"); |
michael@0 | 252 | chan.asyncOpen(new ChannelListener(received_cleartext, null), null); |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | const simpleBody = "0123456789"; |
michael@0 | 256 | |
michael@0 | 257 | function received_simple(request, data) { |
michael@0 | 258 | do_check_eq(simpleBody, data); |
michael@0 | 259 | testFinished(); |
michael@0 | 260 | } |
michael@0 | 261 | |
michael@0 | 262 | var case_7_request_no = 0; |
michael@0 | 263 | function handler_7(metadata, response) { |
michael@0 | 264 | switch (case_7_request_no) { |
michael@0 | 265 | case 0: |
michael@0 | 266 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 267 | response.setHeader("Content-Type", "text/plain", false); |
michael@0 | 268 | response.setHeader("ETag", "test7Etag"); |
michael@0 | 269 | response.setHeader("Accept-Ranges", "bytes"); |
michael@0 | 270 | response.setHeader("Cache-Control", "max-age=360000"); |
michael@0 | 271 | response.setHeader("Content-Length", "10"); |
michael@0 | 272 | response.processAsync(); |
michael@0 | 273 | response.bodyOutputStream.write(simpleBody.slice(0, 4), 4); |
michael@0 | 274 | response.finish(); |
michael@0 | 275 | break; |
michael@0 | 276 | case 1: |
michael@0 | 277 | response.setHeader("Content-Type", "text/plain", false); |
michael@0 | 278 | response.setHeader("ETag", "test7Etag"); |
michael@0 | 279 | if (metadata.hasHeader("Range")) { |
michael@0 | 280 | do_check_true(metadata.hasHeader("If-Range")); |
michael@0 | 281 | response.setStatusLine(metadata.httpVersion, 206, "Partial Content"); |
michael@0 | 282 | response.setHeader("Content-Range", "4-9/10"); |
michael@0 | 283 | response.setHeader("Content-Length", "6"); |
michael@0 | 284 | response.bodyOutputStream.write(simpleBody.slice(4), 6); |
michael@0 | 285 | } else { |
michael@0 | 286 | response.setHeader("Content-Length", "10"); |
michael@0 | 287 | response.bodyOutputStream.write(simpleBody, 10); |
michael@0 | 288 | } |
michael@0 | 289 | break; |
michael@0 | 290 | default: |
michael@0 | 291 | response.setStatusLine(metadata.httpVersion, 404, "Not Found"); |
michael@0 | 292 | } |
michael@0 | 293 | case_7_request_no++; |
michael@0 | 294 | } |
michael@0 | 295 | function received_partial_7(request, data) { |
michael@0 | 296 | // make sure we get the first 4 bytes |
michael@0 | 297 | do_check_eq(4, data.length); |
michael@0 | 298 | // do it again to get the rest |
michael@0 | 299 | var chan = make_channel("http://localhost:" + port + "/test_7"); |
michael@0 | 300 | chan.asyncOpen(new ChannelListener(received_simple, null), null); |
michael@0 | 301 | } |
michael@0 | 302 | |
michael@0 | 303 | var case_8_request_no = 0; |
michael@0 | 304 | function handler_8(metadata, response) { |
michael@0 | 305 | switch (case_8_request_no) { |
michael@0 | 306 | case 0: |
michael@0 | 307 | do_check_false(metadata.hasHeader("Range")); |
michael@0 | 308 | response.setHeader("Content-Type", "text/plain", false); |
michael@0 | 309 | response.setHeader("ETag", "test8Etag"); |
michael@0 | 310 | response.setHeader("Accept-Ranges", "bytes"); |
michael@0 | 311 | response.setHeader("Cache-Control", "max-age=360000"); |
michael@0 | 312 | response.setHeader("Content-Length", "10"); |
michael@0 | 313 | response.processAsync(); |
michael@0 | 314 | response.bodyOutputStream.write(simpleBody.slice(0, 4), 4); |
michael@0 | 315 | response.finish(); |
michael@0 | 316 | break; |
michael@0 | 317 | case 1: |
michael@0 | 318 | if (metadata.hasHeader("Range")) { |
michael@0 | 319 | do_check_true(metadata.hasHeader("If-Range")); |
michael@0 | 320 | case_8_range_request = true; |
michael@0 | 321 | } |
michael@0 | 322 | response.setStatusLine(metadata.httpVersion, 206, "Partial Content"); |
michael@0 | 323 | response.setHeader("Content-Type", "text/plain", false); |
michael@0 | 324 | response.setHeader("ETag", "test8Etag"); |
michael@0 | 325 | response.setHeader("Content-Range", "4-8/9"); // intentionally broken |
michael@0 | 326 | response.setHeader("Content-Length", "5"); |
michael@0 | 327 | response.bodyOutputStream.write(simpleBody.slice(4), 5); |
michael@0 | 328 | break; |
michael@0 | 329 | default: |
michael@0 | 330 | response.setStatusLine(metadata.httpVersion, 404, "Not Found"); |
michael@0 | 331 | } |
michael@0 | 332 | case_8_request_no++; |
michael@0 | 333 | } |
michael@0 | 334 | function received_partial_8(request, data) { |
michael@0 | 335 | // make sure we get the first 4 bytes |
michael@0 | 336 | do_check_eq(4, data.length); |
michael@0 | 337 | // do it again to get the rest |
michael@0 | 338 | var chan = make_channel("http://localhost:" + port + "/test_8"); |
michael@0 | 339 | chan.asyncOpen(new FailedChannelListener(testFinished, null, CL_EXPECT_LATE_FAILURE), null); |
michael@0 | 340 | } |
michael@0 | 341 | |
michael@0 | 342 | // Simple mechanism to keep track of tests and stop the server |
michael@0 | 343 | var numTestsFinished = 0; |
michael@0 | 344 | function testFinished() { |
michael@0 | 345 | if (++numTestsFinished == 7) |
michael@0 | 346 | httpserver.stop(do_test_finished); |
michael@0 | 347 | } |
michael@0 | 348 | |
michael@0 | 349 | function run_test() { |
michael@0 | 350 | httpserver = new HttpServer(); |
michael@0 | 351 | httpserver.registerPathHandler("/test_2", handler_2); |
michael@0 | 352 | httpserver.registerPathHandler("/test_3", handler_3); |
michael@0 | 353 | httpserver.registerPathHandler("/test_4", handler_4); |
michael@0 | 354 | httpserver.registerPathHandler("/test_5", handler_5); |
michael@0 | 355 | httpserver.registerPathHandler("/test_6", handler_6); |
michael@0 | 356 | httpserver.registerPathHandler("/test_7", handler_7); |
michael@0 | 357 | httpserver.registerPathHandler("/test_8", handler_8); |
michael@0 | 358 | httpserver.start(-1); |
michael@0 | 359 | |
michael@0 | 360 | port = httpserver.identity.primaryPort; |
michael@0 | 361 | |
michael@0 | 362 | // wipe out cached content |
michael@0 | 363 | evict_cache_entries(); |
michael@0 | 364 | |
michael@0 | 365 | // Case 2: zero-length partial entry must not trigger range-request |
michael@0 | 366 | var chan = make_channel("http://localhost:" + port + "/test_2"); |
michael@0 | 367 | chan.asyncOpen(new Canceler(received_partial_2), null); |
michael@0 | 368 | |
michael@0 | 369 | // Case 3: no-store response must not trigger range-request |
michael@0 | 370 | var chan = make_channel("http://localhost:" + port + "/test_3"); |
michael@0 | 371 | chan.asyncOpen(new MyListener(received_partial_3), null); |
michael@0 | 372 | |
michael@0 | 373 | // Case 4: response with content-encoding must not trigger range-request |
michael@0 | 374 | var chan = make_channel("http://localhost:" + port + "/test_4"); |
michael@0 | 375 | chan.asyncOpen(new MyListener(received_partial_4), null); |
michael@0 | 376 | |
michael@0 | 377 | // Case 5: conditional request-header set by client |
michael@0 | 378 | var chan = make_channel("http://localhost:" + port + "/test_5"); |
michael@0 | 379 | chan.asyncOpen(new MyListener(received_partial_5), null); |
michael@0 | 380 | |
michael@0 | 381 | // Case 6: response is not resumable (drop the Accept-Ranges header) |
michael@0 | 382 | var chan = make_channel("http://localhost:" + port + "/test_6"); |
michael@0 | 383 | chan.asyncOpen(new MyListener(received_partial_6), null); |
michael@0 | 384 | |
michael@0 | 385 | // Case 7: a basic positive test |
michael@0 | 386 | var chan = make_channel("http://localhost:" + port + "/test_7"); |
michael@0 | 387 | chan.asyncOpen(new MyListener(received_partial_7), null); |
michael@0 | 388 | |
michael@0 | 389 | // Case 8: check that mismatched 206 and 200 sizes throw error |
michael@0 | 390 | var chan = make_channel("http://localhost:" + port + "/test_8"); |
michael@0 | 391 | chan.asyncOpen(new MyListener(received_partial_8), null); |
michael@0 | 392 | |
michael@0 | 393 | do_test_pending(); |
michael@0 | 394 | } |