11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures');
41cb0ef41Sopenharmony_ciconst assert = require('assert');
51cb0ef41Sopenharmony_ciconst fs = require('fs');
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci// Test that concurrent file read streams don’t interfere with each other’s
81cb0ef41Sopenharmony_ci// contents, and that the chunks generated by the reads only retain a
91cb0ef41Sopenharmony_ci// 'reasonable' amount of memory.
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci// Refs: https://github.com/nodejs/node/issues/21967
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ciconst filename = fixtures.path('loop.js');  // Some small non-homogeneous file.
141cb0ef41Sopenharmony_ciconst content = fs.readFileSync(filename);
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciconst N = 2000;
171cb0ef41Sopenharmony_cilet started = 0;
181cb0ef41Sopenharmony_cilet done = 0;
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciconst arrayBuffers = new Set();
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_cifunction startRead() {
231cb0ef41Sopenharmony_ci  ++started;
241cb0ef41Sopenharmony_ci  const chunks = [];
251cb0ef41Sopenharmony_ci  fs.createReadStream(filename)
261cb0ef41Sopenharmony_ci    .on('data', (chunk) => {
271cb0ef41Sopenharmony_ci      chunks.push(chunk);
281cb0ef41Sopenharmony_ci      arrayBuffers.add(chunk.buffer);
291cb0ef41Sopenharmony_ci    })
301cb0ef41Sopenharmony_ci    .on('end', common.mustCall(() => {
311cb0ef41Sopenharmony_ci      if (started < N)
321cb0ef41Sopenharmony_ci        startRead();
331cb0ef41Sopenharmony_ci      assert.deepStrictEqual(Buffer.concat(chunks), content);
341cb0ef41Sopenharmony_ci      if (++done === N) {
351cb0ef41Sopenharmony_ci        const retainedMemory =
361cb0ef41Sopenharmony_ci          [...arrayBuffers].map((ab) => ab.byteLength).reduce((a, b) => a + b);
371cb0ef41Sopenharmony_ci        assert(retainedMemory / (N * content.length) <= 3,
381cb0ef41Sopenharmony_ci               `Retaining ${retainedMemory} bytes in ABs for ${N} ` +
391cb0ef41Sopenharmony_ci               `chunks of size ${content.length}`);
401cb0ef41Sopenharmony_ci      }
411cb0ef41Sopenharmony_ci    }));
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci// Don’t start the reads all at once – that way we would have to allocate
451cb0ef41Sopenharmony_ci// a large amount of memory upfront.
461cb0ef41Sopenharmony_cifor (let i = 0; i < 6; ++i)
471cb0ef41Sopenharmony_ci  startRead();
48