| 'use strict'; |
| const common = require('../common'); |
| const fixtures = require('../common/fixtures'); |
| const assert = require('assert'); |
| const fs = require('fs'); |
| |
| // Test that concurrent file read streams don’t interfere with each other’s |
| // contents, and that the chunks generated by the reads only retain a |
| // 'reasonable' amount of memory. |
| |
| // Refs: https://github.com/nodejs/node/issues/21967 |
| |
| const filename = fixtures.path('loop.js'); // Some small non-homogeneous file. |
| const content = fs.readFileSync(filename); |
| |
| const N = 2000; |
| let started = 0; |
| let done = 0; |
| |
| const arrayBuffers = new Set(); |
| |
| function startRead() { |
| ++started; |
| const chunks = []; |
| fs.createReadStream(filename) |
| .on('data', (chunk) => { |
| chunks.push(chunk); |
| arrayBuffers.add(chunk.buffer); |
| }) |
| .on('end', common.mustCall(() => { |
| if (started < N) |
| startRead(); |
| assert.deepStrictEqual(Buffer.concat(chunks), content); |
| if (++done === N) { |
| const retainedMemory = |
| [...arrayBuffers].map((ab) => ab.byteLength).reduce((a, b) => a + b); |
| assert(retainedMemory / (N * content.length) <= 3, |
| `Retaining ${retainedMemory} bytes in ABs for ${N} ` + |
| `chunks of size ${content.length}`); |
| } |
| })); |
| } |
| |
| // Don’t start the reads all at once – that way we would have to allocate |
| // a large amount of memory upfront. |
| for (let i = 0; i < 6; ++i) |
| startRead(); |