'use strict'; // This test ensures that servers are able to send data independent of window // size. // TODO: This test makes large buffer allocations (128KiB) and should be tested // on smaller / IoT platforms in case this poses problems for these targets. const common = require('../common'); if (!common.hasCrypto) common.skip('missing crypto'); const assert = require('assert'); const h2 = require('http2'); // Given a list of buffers and an initial window size, have a server write // each buffer to the HTTP2 Writable stream, and let the client verify that // all of the bytes were sent correctly function run(buffers, initialWindowSize) { return new Promise((resolve, reject) => { const expectedBuffer = Buffer.concat(buffers); const server = h2.createServer(); server.on('stream', (stream) => { let i = 0; const writeToStream = () => { const cont = () => { i++; if (i < buffers.length) { setImmediate(writeToStream); } else { stream.end(); } }; const drained = stream.write(buffers[i]); if (drained) { cont(); } else { stream.once('drain', cont); } }; writeToStream(); }); server.listen(0); server.on('listening', common.mustCall(function() { const port = this.address().port; const client = h2.connect({ authority: 'localhost', protocol: 'http:', port }, { settings: { initialWindowSize } }).on('connect', common.mustCall(() => { const req = client.request({ ':method': 'GET', ':path': '/' }); const responses = []; req.on('data', (data) => { responses.push(data); }); req.on('end', common.mustCall(() => { const actualBuffer = Buffer.concat(responses); assert.strictEqual(Buffer.compare(actualBuffer, expectedBuffer), 0); // shut down client.close(); server.close(() => { resolve(); }); })); req.end(); })); })); }); } const bufferValueRange = [0, 1, 2, 3]; const buffersList = [ bufferValueRange.map((a) => Buffer.alloc(1 << 4, a)), bufferValueRange.map((a) => Buffer.alloc((1 << 8) - 1, a)), // Specifying too large of a value causes timeouts on some platforms // bufferValueRange.map((a) => Buffer.alloc(1 << 17, a)) ]; const initialWindowSizeList = [ 1 << 4, (1 << 8) - 1, 1 << 8, 1 << 17, undefined, // Use default window size which is (1 << 16) - 1 ]; // Call `run` on each element in the cartesian product of buffersList and // initialWindowSizeList. let p = Promise.resolve(); for (const buffers of buffersList) { for (const initialWindowSize of initialWindowSizeList) { p = p.then(() => run(buffers, initialWindowSize)); } } p.then(common.mustCall());