1'use strict'; 2 3// This test ensures that servers are able to send data independent of window 4// size. 5// TODO: This test makes large buffer allocations (128KiB) and should be tested 6// on smaller / IoT platforms in case this poses problems for these targets. 7 8const common = require('../common'); 9if (!common.hasCrypto) 10 common.skip('missing crypto'); 11const assert = require('assert'); 12const h2 = require('http2'); 13 14// Given a list of buffers and an initial window size, have a server write 15// each buffer to the HTTP2 Writable stream, and let the client verify that 16// all of the bytes were sent correctly 17function run(buffers, initialWindowSize) { 18 return new Promise((resolve, reject) => { 19 const expectedBuffer = Buffer.concat(buffers); 20 21 const server = h2.createServer(); 22 server.on('stream', (stream) => { 23 let i = 0; 24 const writeToStream = () => { 25 const cont = () => { 26 i++; 27 if (i < buffers.length) { 28 setImmediate(writeToStream); 29 } else { 30 stream.end(); 31 } 32 }; 33 const drained = stream.write(buffers[i]); 34 if (drained) { 35 cont(); 36 } else { 37 stream.once('drain', cont); 38 } 39 }; 40 writeToStream(); 41 }); 42 server.listen(0); 43 44 server.on('listening', common.mustCall(function() { 45 const port = this.address().port; 46 47 const client = 48 h2.connect({ 49 authority: 'localhost', 50 protocol: 'http:', 51 port 52 }, { 53 settings: { 54 initialWindowSize 55 } 56 }).on('connect', common.mustCall(() => { 57 const req = client.request({ 58 ':method': 'GET', 59 ':path': '/' 60 }); 61 const responses = []; 62 req.on('data', (data) => { 63 responses.push(data); 64 }); 65 req.on('end', common.mustCall(() => { 66 const actualBuffer = Buffer.concat(responses); 67 assert.strictEqual(Buffer.compare(actualBuffer, expectedBuffer), 0); 68 // shut down 69 client.close(); 70 server.close(() => { 71 resolve(); 72 }); 73 })); 74 req.end(); 75 })); 76 })); 77 }); 78} 79 80const bufferValueRange = [0, 1, 2, 3]; 81const buffersList = [ 82 bufferValueRange.map((a) => Buffer.alloc(1 << 4, a)), 83 bufferValueRange.map((a) => Buffer.alloc((1 << 8) - 1, a)), 84// Specifying too large of a value causes timeouts on some platforms 85// bufferValueRange.map((a) => Buffer.alloc(1 << 17, a)) 86]; 87const initialWindowSizeList = [ 88 1 << 4, 89 (1 << 8) - 1, 90 1 << 8, 91 1 << 17, 92 undefined, // Use default window size which is (1 << 16) - 1 93]; 94 95// Call `run` on each element in the cartesian product of buffersList and 96// initialWindowSizeList. 97let p = Promise.resolve(); 98for (const buffers of buffersList) { 99 for (const initialWindowSize of initialWindowSizeList) { 100 p = p.then(() => run(buffers, initialWindowSize)); 101 } 102} 103p.then(common.mustCall()); 104