|
| 1 | +'use strict'; |
| 2 | +constcommon=require('../common'); |
| 3 | +if(common.isIBMi) |
| 4 | +common.skip('On IBMi, the rss memory always returns zero'); |
| 5 | + |
| 6 | +// This test verifies that readFileSync does not leak memory when reading |
| 7 | +// UTF8 files. See: https://github.com/nodejs/node/issues/57800 for details. |
| 8 | + |
| 9 | +constassert=require('node:assert'); |
| 10 | +constfs=require('node:fs'); |
| 11 | +constutil=require('node:util'); |
| 12 | +consttmpdir=require('../common/tmpdir'); |
| 13 | + |
| 14 | +// The memory leak being tested here was from a buffer with the absolute URI to |
| 15 | +// a file. For each file read, 2-4 bytes were (usually) leaked per character in |
| 16 | +// the URI. The length of the file path can be used to estimate the approximate |
| 17 | +// amount of memory that will be leaked if this issue is reintroduced. A longer |
| 18 | +// total path length will make the issue easier to test for. Some operating |
| 19 | +// systems like Windows have shorter default path length limits. If the path |
| 20 | +// is approaching that limit, the length of the path should be long enough to |
| 21 | +// effectively test for this memory leak. |
| 22 | +tmpdir.refresh(); |
| 23 | +lettestFile=tmpdir.resolve( |
| 24 | +'a-file-with-a-longer-than-usual-file-name-for-testing-a-memory-leak-related-to-path-length.txt', |
| 25 | +); |
| 26 | +if(testFile.length>process.env.MAX_PATH){ |
| 27 | +testFile=tmpdir.resolve('reasonable-length.txt'); |
| 28 | +} |
| 29 | + |
| 30 | +// The buffer being checked is WCHAR buffer. The size is going to be at least 2 |
| 31 | +// bytes per character but can be more. Windows: 2; Mac: 2; Linux: 4 (usually); |
| 32 | +constiterations=100_000; |
| 33 | +constminExpectedMemoryLeak=(testFile.length*2)*iterations; |
| 34 | + |
| 35 | +// This memory leak was exclusive to UTF8 encoded files. |
| 36 | +// Create our test file. The contents of the file don't matter. |
| 37 | +constoptions={encoding: 'utf8'}; |
| 38 | +fs.writeFileSync(testFile,'',options); |
| 39 | + |
| 40 | +// Doing an initial big batch of file reads gives a more stable baseline memory |
| 41 | +// usage. Doing the same total iterations as the actual test isn't necessary. |
| 42 | +for(leti=0;i<100;i++){ |
| 43 | +fs.readFileSync(testFile,options); |
| 44 | +} |
| 45 | +conststartMemory=process.memoryUsage(); |
| 46 | +for(leti=0;i<iterations;i++){ |
| 47 | +fs.readFileSync(testFile,options); |
| 48 | +} |
| 49 | +constendMemory=process.memoryUsage(); |
| 50 | + |
| 51 | +// Use 90% of the expected memory leak as the threshold just to be safe. |
| 52 | +constmemoryDifference=endMemory.rss-startMemory.rss; |
| 53 | +assert.ok(memoryDifference<(minExpectedMemoryLeak*0.9), |
| 54 | +`Unexpected memory overhead: ${util.inspect([startMemory,endMemory])}`); |
0 commit comments