blob: 755bc78916724103f3222307b307ff05a9e435a6 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// @dart = 2.9
import 'dart:io';
import 'package:expect/expect.dart';
import 'package:path/path.dart' as path;
Future runWithTempDir(Future Function(String dir) callback) async {
final tempDir = Directory.systemTemp.createTempSync("large_file_read");
try {
await callback(tempDir.path);
} finally {
tempDir.delete(recursive: true);
}
}
main() async {
// MSAN's malloc implementation will not free memory when shrinking
// allocations via realloc (e.g. realloc(malloc(1 GB), new_size=10) will
// hold on to the 1 GB).
if (Platform.executable.contains('MSAN')) return;
await runWithTempDir((String dir) async {
final file = File(path.join(dir, 'hello_world.txt'));
await file.writeAsString('hello world');
final RandomAccessFile randomAccessFile = await file.open();
try {
final buffers = [];
for (int i = 0; i < 100 * 1000; ++i) {
if (i % 1000 == 0) {
print(i);
}
// We issue a 1 MB read but get only a small typed data back. We hang on
// to those buffers. If the implementation actually malloc()ed 1 MB then
// we would hang on to 100 GB and this test would OOM.
// If the implementation instead correctly shrinks the buffer before
// giving it to Dart as external typed data, we only consume ~ 100 KB.
buffers.add(await randomAccessFile.read(1 * 1024 * 1024));
await randomAccessFile.setPosition(0);
// To avoid machines becoming unusable if the test fails, we'll fail
// explicitly if we hit 2 GB.
if (ProcessInfo.currentRss > 2 * 1024 * 1024 * 1024) {
throw 'The dart:io implementation is buggy and uses too much memory';
}
}
for (final buffer in buffers) {
Expect.equals('hello world'.length, buffer.length);
}
} finally {
randomAccessFile.close();
}
});
}