2
2
// for details. All rights reserved. Use of this source code is governed by a
3
3
// BSD-style license that can be found in the LICENSE.md file.
4
4
5
- import 'dart:async' show StreamController;
6
- import 'dart:convert' show utf8, LineSplitter;
7
- import 'dart:io' show Directory, File, FileSystemEntity, IOSink, exitCode;
5
+ import 'dart:async' show StreamController, Zone;
6
+ import 'dart:convert' show Encoding, LineSplitter, utf8;
7
+ import 'dart:io'
8
+ show
9
+ Directory,
10
+ File,
11
+ FileMode,
12
+ FileSystemEntity,
13
+ IOOverrides,
14
+ IOSink,
15
+ exitCode;
16
+ import 'dart:typed_data' show BytesBuilder, Uint8List;
8
17
9
18
import 'package:front_end/src/api_prototype/language_version.dart'
10
19
show uriUsesLegacyLanguageVersion;
@@ -277,8 +286,27 @@ Future<List<String>> attemptStuff(
277
286
Iterator <File > testFileIterator = testFiles.iterator;
278
287
testFileIterator.moveNext ();
279
288
280
- final Future <int > result =
281
- starter (args, input: inputStreamController.stream, output: ioSink);
289
+ Zone parentZone = Zone .current;
290
+ Map <String , _MockFile > files = {};
291
+
292
+ /// Each test writes a complete (modulo platform) dill, often taking around
293
+ /// 40 MB. With 1,500+ tests thats easily 50+ GB data to write. We don't
294
+ /// really need it as an actual file though, we just need to get a hold on it
295
+ /// below so we can run verification on it. We thus use [IOOverrides] to
296
+ /// "catch" dill files (`new File("whatnot.dill")` ) so we can write those to
297
+ /// memory instead of to actual files.
298
+ /// This is specialized for how it's actually written in the production code
299
+ /// (via `openWrite` ) and will fail if that changes (at which point it will
300
+ /// have to be updated).
301
+ final Future <int > result = IOOverrides .runZoned (() {
302
+ return starter (args, input: inputStreamController.stream, output: ioSink);
303
+ }, createFile: (String path) {
304
+ if (files[path] != null ) return files[path]! ;
305
+ File f = parentZone.run (() => File (path));
306
+ if (path.endsWith (".dill" )) return files[path] = _MockFile (f);
307
+ return f;
308
+ });
309
+
282
310
String testName =
283
311
testFileIterator.current.path.substring (flutterDirectory.path.length);
284
312
@@ -304,7 +332,7 @@ Future<List<String>> attemptStuff(
304
332
logger.logUnexpectedResult (testName);
305
333
}
306
334
if (! error) {
307
- List < int > resultBytes = dillFile.readAsBytesSync ();
335
+ Uint8List resultBytes = files[ dillFile.path] ! .writeSink ! .bb. takeBytes ();
308
336
Component component = loadComponentFromBytes (platformData);
309
337
component = loadComponentFromBytes (resultBytes, component);
310
338
verifyComponent (
@@ -318,6 +346,8 @@ Future<List<String>> attemptStuff(
318
346
logger
319
347
.log (" => verified in ${stopwatch2 .elapsedMilliseconds } ms." );
320
348
}
349
+
350
+ files.clear ();
321
351
stopwatch2.reset ();
322
352
323
353
inputStreamController.add ('accept\n ' .codeUnits);
@@ -483,3 +513,52 @@ class StdoutLogger extends Logger {
483
513
print (s);
484
514
}
485
515
}
516
+
517
+ class _MockFile implements File {
518
+ final File _f;
519
+ _MockIOSink ? writeSink;
520
+
521
+ _MockFile (this ._f);
522
+
523
+ @override
524
+ bool existsSync () {
525
+ return _f.existsSync ();
526
+ }
527
+
528
+ @override
529
+ Uint8List readAsBytesSync () {
530
+ return _f.readAsBytesSync ();
531
+ }
532
+
533
+ @override
534
+ IOSink openWrite ({FileMode mode = FileMode .write, Encoding encoding = utf8}) {
535
+ return writeSink = _MockIOSink ();
536
+ }
537
+
538
+ @override
539
+ dynamic noSuchMethod (Invocation invocation) {
540
+ return super .noSuchMethod (invocation);
541
+ }
542
+ }
543
+
544
+ class _MockIOSink implements IOSink {
545
+ BytesBuilder bb = BytesBuilder ();
546
+ bool _closed = false ;
547
+
548
+ @override
549
+ void add (List <int > data) {
550
+ if (_closed) throw "Adding to closed" ;
551
+ bb.add (data);
552
+ }
553
+
554
+ @override
555
+ Future close () {
556
+ _closed = true ;
557
+ return Future .value ();
558
+ }
559
+
560
+ @override
561
+ dynamic noSuchMethod (Invocation invocation) {
562
+ return super .noSuchMethod (invocation);
563
+ }
564
+ }
0 commit comments