[null-safety] migrate to _almost_ null safety (#162)
Remove record/replay functionality and update to almost null-safety.
diff --git a/analysis_options.yaml b/analysis_options.yaml
index c6d2ad9..ee1a01b 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,4 +1,6 @@
analyzer:
+ enable-experiment:
+ - non-nullable
strong-mode:
implicit-casts: false
implicit-dynamic: false
diff --git a/appveyor.yml b/appveyor.yml
index 319ec41..27abf4b 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -11,4 +11,4 @@
build: off
test_script:
- - pub run test -j1
+ - pub run --enable-experiment=non-nullable test -j1
diff --git a/dev/bots/travis_script.sh b/dev/bots/travis_script.sh
index fe55e57..d601d39 100755
--- a/dev/bots/travis_script.sh
+++ b/dev/bots/travis_script.sh
@@ -11,10 +11,10 @@
for package in "${PACKAGES[@]}"; do
echo "Analyzing packages/$package"
cd $ROOT/packages/$package
- dartanalyzer --options=$ROOT/analysis_options.yaml . || exit $?
+ dartanalyzer --enable-experiment=non-nullable --options=$ROOT/analysis_options.yaml . || exit $?
done
else
# tests shard
cd $ROOT/packages/file
- pub run test -j1 -rexpanded || exit $?
+ pub run --enable-experiment=non-nullable test -j1 -rexpanded || exit $?
fi
diff --git a/packages/file/CHANGELOG.md b/packages/file/CHANGELOG.md
index 61d3529..46fffae 100644
--- a/packages/file/CHANGELOG.md
+++ b/packages/file/CHANGELOG.md
@@ -1,6 +1,8 @@
-#### 5.2.2-dev
+#### 6.0.0-nullsafety
-* Made `MemoryRandomAccessFile` and `MemoryFile.openWrite` handle the file
+* Update to null safety.
+* Remove record/replay functionality.
+* Made `MemoryRandomAccessFile` and `MemoryFile.openWrite` handle the file.
being removed or renamed while open.
* Fixed incorrect formatting in `NoMatchingInvocationError.toString()`.
* Fixed more test flakiness.
diff --git a/packages/file/lib/chroot.dart b/packages/file/lib/chroot.dart
index 56d2bd5..3967fff 100644
--- a/packages/file/lib/chroot.dart
+++ b/packages/file/lib/chroot.dart
@@ -2,5 +2,7 @@
// 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.10
+
/// A file system that provides a view into _another_ `FileSystem` via a path.
export 'src/backends/chroot.dart';
diff --git a/packages/file/lib/file.dart b/packages/file/lib/file.dart
index cdde9fe..07ee858 100644
--- a/packages/file/lib/file.dart
+++ b/packages/file/lib/file.dart
@@ -2,6 +2,8 @@
// 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.10
+
/// Core interfaces containing the abstract `FileSystem` interface definition
/// and all associated types used by `FileSystem`.
export 'src/forwarding.dart';
diff --git a/packages/file/lib/local.dart b/packages/file/lib/local.dart
index 74f506e..773b000 100644
--- a/packages/file/lib/local.dart
+++ b/packages/file/lib/local.dart
@@ -2,6 +2,8 @@
// 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.10
+
/// A local file system implementation. This relies on the use of `dart:io`
/// and is thus not suitable for use in the browser.
export 'src/backends/local.dart';
diff --git a/packages/file/lib/memory.dart b/packages/file/lib/memory.dart
index 31e90e7..b0d6c3e 100644
--- a/packages/file/lib/memory.dart
+++ b/packages/file/lib/memory.dart
@@ -2,6 +2,8 @@
// 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.10
+
/// An implementation of `FileSystem` that exists entirely in memory with an
/// internal representation loosely based on the Filesystem Hierarchy Standard.
export 'src/backends/memory.dart';
diff --git a/packages/file/lib/record_replay.dart b/packages/file/lib/record_replay.dart
deleted file mode 100644
index be28576..0000000
--- a/packages/file/lib/record_replay.dart
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/// File systems that work together to record invocations during live operation
-/// and then play invocations back in tests.
-export 'src/backends/record_replay/errors.dart';
-export 'src/backends/record_replay/events.dart'
- show InvocationEvent, PropertyGetEvent, PropertySetEvent, MethodEvent;
-export 'src/backends/record_replay/recording.dart';
-export 'src/backends/record_replay/recording_file_system.dart'
- show RecordingFileSystem;
-export 'src/backends/record_replay/replay_file_system.dart'
- show ReplayFileSystem;
diff --git a/packages/file/lib/src/backends/chroot.dart b/packages/file/lib/src/backends/chroot.dart
index 72ce3ca..7a9a1f0 100644
--- a/packages/file/lib/src/backends/chroot.dart
+++ b/packages/file/lib/src/backends/chroot.dart
@@ -2,6 +2,7 @@
// 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.10
library file.src.backends.chroot;
import 'dart:async';
diff --git a/packages/file/lib/src/backends/chroot/chroot_directory.dart b/packages/file/lib/src/backends/chroot/chroot_directory.dart
index 8fec7b1..74e3cd2 100644
--- a/packages/file/lib/src/backends/chroot/chroot_directory.dart
+++ b/packages/file/lib/src/backends/chroot/chroot_directory.dart
@@ -2,6 +2,7 @@
// 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.10
part of file.src.backends.chroot;
class _ChrootDirectory extends _ChrootFileSystemEntity<Directory, io.Directory>
diff --git a/packages/file/lib/src/backends/chroot/chroot_file.dart b/packages/file/lib/src/backends/chroot/chroot_file.dart
index 60bda56..3668ea7 100644
--- a/packages/file/lib/src/backends/chroot/chroot_file.dart
+++ b/packages/file/lib/src/backends/chroot/chroot_file.dart
@@ -2,6 +2,7 @@
// 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.10
part of file.src.backends.chroot;
typedef _SetupCallback = dynamic Function();
@@ -251,7 +252,7 @@
getDelegate(followLinks: true).openSync(mode: mode);
@override
- Stream<Uint8List> openRead([int start, int end]) =>
+ Stream<Uint8List> openRead([int? start, int? end]) =>
getDelegate(followLinks: true).openRead(start, end).cast<Uint8List>();
@override
diff --git a/packages/file/lib/src/backends/chroot/chroot_file_system.dart b/packages/file/lib/src/backends/chroot/chroot_file_system.dart
index 5e383bd..02423b7 100644
--- a/packages/file/lib/src/backends/chroot/chroot_file_system.dart
+++ b/packages/file/lib/src/backends/chroot/chroot_file_system.dart
@@ -2,6 +2,7 @@
// 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.10
part of file.src.backends.chroot;
const String _thisDir = '.';
@@ -51,10 +52,10 @@
/// Directory in [delegate] file system that is treated as the root here.
final String root;
- String _systemTemp;
+ String? _systemTemp;
/// Path to the synthetic current working directory in this file system.
- String _cwd;
+ late String _cwd;
/// Gets the root path, as seen by entities in this file system.
String get _localRoot => delegate.path.rootPrefix(root);
@@ -255,7 +256,7 @@
/// the partially resolved path will be returned.
String _resolve(
String path, {
- String from,
+ String? from,
bool followLinks = true,
_NotFoundBehavior notFound = _NotFoundBehavior.allow,
}) {
@@ -366,14 +367,16 @@
class _NotFoundFileStat implements FileStat {
const _NotFoundFileStat();
- @override
- DateTime get changed => null;
+ static final DateTime _empty = DateTime(0);
@override
- DateTime get modified => null;
+ DateTime get changed => _empty;
@override
- DateTime get accessed => null;
+ DateTime get modified => _empty;
+
+ @override
+ DateTime get accessed => _empty;
@override
FileSystemEntityType get type => FileSystemEntityType.notFound;
diff --git a/packages/file/lib/src/backends/chroot/chroot_file_system_entity.dart b/packages/file/lib/src/backends/chroot/chroot_file_system_entity.dart
index 8e859ac..d9e726d 100644
--- a/packages/file/lib/src/backends/chroot/chroot_file_system_entity.dart
+++ b/packages/file/lib/src/backends/chroot/chroot_file_system_entity.dart
@@ -2,6 +2,7 @@
// 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.10
part of file.src.backends.chroot;
abstract class _ChrootFileSystemEntity<T extends FileSystemEntity,
diff --git a/packages/file/lib/src/backends/chroot/chroot_link.dart b/packages/file/lib/src/backends/chroot/chroot_link.dart
index acbeda6..1eb7497 100644
--- a/packages/file/lib/src/backends/chroot/chroot_link.dart
+++ b/packages/file/lib/src/backends/chroot/chroot_link.dart
@@ -2,6 +2,7 @@
// 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.10
part of file.src.backends.chroot;
class _ChrootLink extends _ChrootFileSystemEntity<Link, io.Link>
diff --git a/packages/file/lib/src/backends/local.dart b/packages/file/lib/src/backends/local.dart
index 1e92241..eef8548 100644
--- a/packages/file/lib/src/backends/local.dart
+++ b/packages/file/lib/src/backends/local.dart
@@ -2,4 +2,5 @@
// 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.10
export 'local/local_file_system.dart' show LocalFileSystem;
diff --git a/packages/file/lib/src/backends/local/local_directory.dart b/packages/file/lib/src/backends/local/local_directory.dart
index ecb55cf..15030c6 100644
--- a/packages/file/lib/src/backends/local/local_directory.dart
+++ b/packages/file/lib/src/backends/local/local_directory.dart
@@ -2,6 +2,7 @@
// 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.10
import 'package:file/src/common.dart' as common;
import 'package:file/src/forwarding.dart';
import 'package:file/src/io.dart' as io;
diff --git a/packages/file/lib/src/backends/local/local_file.dart b/packages/file/lib/src/backends/local/local_file.dart
index e7ed49d..239f46e 100644
--- a/packages/file/lib/src/backends/local/local_file.dart
+++ b/packages/file/lib/src/backends/local/local_file.dart
@@ -2,6 +2,7 @@
// 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.10
import 'package:file/src/forwarding.dart';
import 'package:file/src/io.dart' as io;
import 'package:file/file.dart';
diff --git a/packages/file/lib/src/backends/local/local_file_system.dart b/packages/file/lib/src/backends/local/local_file_system.dart
index 069c436..4dc4451 100644
--- a/packages/file/lib/src/backends/local/local_file_system.dart
+++ b/packages/file/lib/src/backends/local/local_file_system.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:file/src/io.dart' as io;
diff --git a/packages/file/lib/src/backends/local/local_file_system_entity.dart b/packages/file/lib/src/backends/local/local_file_system_entity.dart
index acfe761..fc4adfc 100644
--- a/packages/file/lib/src/backends/local/local_file_system_entity.dart
+++ b/packages/file/lib/src/backends/local/local_file_system_entity.dart
@@ -2,6 +2,7 @@
// 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.10
import 'package:file/src/forwarding.dart';
import 'package:file/src/io.dart' as io;
import 'package:file/file.dart';
diff --git a/packages/file/lib/src/backends/local/local_link.dart b/packages/file/lib/src/backends/local/local_link.dart
index 46c3190..2f8956b 100644
--- a/packages/file/lib/src/backends/local/local_link.dart
+++ b/packages/file/lib/src/backends/local/local_link.dart
@@ -2,6 +2,7 @@
// 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.10
import 'package:file/src/forwarding.dart';
import 'package:file/src/io.dart' as io;
import 'package:file/file.dart';
diff --git a/packages/file/lib/src/backends/memory.dart b/packages/file/lib/src/backends/memory.dart
index 428bc54..8ec1612 100644
--- a/packages/file/lib/src/backends/memory.dart
+++ b/packages/file/lib/src/backends/memory.dart
@@ -2,5 +2,6 @@
// 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.10
export 'memory/memory_file_system.dart' show MemoryFileSystem;
export 'memory/style.dart' show FileSystemStyle, StyleableFileSystem;
diff --git a/packages/file/lib/src/backends/memory/clock.dart b/packages/file/lib/src/backends/memory/clock.dart
index 12549aa..d078057 100644
--- a/packages/file/lib/src/backends/memory/clock.dart
+++ b/packages/file/lib/src/backends/memory/clock.dart
@@ -2,6 +2,8 @@
// 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.10
+
/// Interface describing clocks used by the [MemoryFileSystem].
///
/// The [MemoryFileSystem] uses a clock to determine the modification times of
@@ -39,7 +41,7 @@
class _MonotonicTestClock extends Clock {
_MonotonicTestClock({
- DateTime start,
+ DateTime? start,
}) : _current = start ?? DateTime(2000);
DateTime _current;
diff --git a/packages/file/lib/src/backends/memory/common.dart b/packages/file/lib/src/backends/memory/common.dart
index d9d8f5c..f8f43de 100644
--- a/packages/file/lib/src/backends/memory/common.dart
+++ b/packages/file/lib/src/backends/memory/common.dart
@@ -2,13 +2,14 @@
// 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.10
import 'package:file/src/common.dart' as common;
/// Generates a path to use in error messages.
typedef PathGenerator = dynamic Function();
/// Throws a `FileSystemException` if [object] is null.
-void checkExists(Object object, PathGenerator path) {
+void checkExists(Object? object, PathGenerator path) {
if (object == null) {
throw common.noSuchFileOrDirectory(path() as String);
}
diff --git a/packages/file/lib/src/backends/memory/memory_directory.dart b/packages/file/lib/src/backends/memory/memory_directory.dart
index 688e0df..8285a2a 100644
--- a/packages/file/lib/src/backends/memory/memory_directory.dart
+++ b/packages/file/lib/src/backends/memory/memory_directory.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:file/file.dart';
@@ -39,7 +40,7 @@
}
@override
- bool existsSync() => backingOrNull?.stat?.type == expectedType;
+ bool existsSync() => backingOrNull?.stat.type == expectedType;
@override
Future<Directory> create({bool recursive = false}) async {
@@ -49,7 +50,7 @@
@override
void createSync({bool recursive = false}) {
- Node node = internalCreateSync(
+ Node? node = internalCreateSync(
followTailLink: true,
visitLinks: true,
createChild: (DirectoryNode parent, bool isFinalSegment) {
@@ -59,17 +60,18 @@
return null;
},
);
- if (node.type != expectedType) {
+ if (node?.type != expectedType) {
// There was an existing non-directory node at this object's path
throw common.notADirectory(path);
}
}
@override
- Future<Directory> createTemp([String prefix]) async => createTempSync(prefix);
+ Future<Directory> createTemp([String? prefix]) async =>
+ createTempSync(prefix);
@override
- Directory createTempSync([String prefix]) {
+ Directory createTempSync([String? prefix]) {
prefix = (prefix ?? '') + 'rand';
String fullPath = fileSystem.path.join(path, prefix);
String dirname = fileSystem.path.dirname(fullPath);
@@ -142,7 +144,7 @@
while (followLinks &&
utils.isLink(child) &&
breadcrumbs.add(child as LinkNode)) {
- Node referent = (child as LinkNode).referentOrNull;
+ Node? referent = child.referentOrNull;
if (referent != null) {
child = referent;
}
diff --git a/packages/file/lib/src/backends/memory/memory_file.dart b/packages/file/lib/src/backends/memory/memory_file.dart
index 3d7b8b3..a1315cd 100644
--- a/packages/file/lib/src/backends/memory/memory_file.dart
+++ b/packages/file/lib/src/backends/memory/memory_file.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'dart:convert';
import 'dart:math' as math show min;
@@ -25,7 +26,7 @@
: super(fileSystem, path);
FileNode get _resolvedBackingOrCreate {
- Node node = backingOrNull;
+ Node? node = backingOrNull;
if (node == null) {
node = _doCreate();
} else {
@@ -41,7 +42,7 @@
io.FileSystemEntityType get expectedType => io.FileSystemEntityType.file;
@override
- bool existsSync() => backingOrNull?.stat?.type == expectedType;
+ bool existsSync() => backingOrNull?.stat.type == expectedType;
@override
Future<File> create({bool recursive = false}) async {
@@ -54,8 +55,8 @@
_doCreate(recursive: recursive);
}
- Node _doCreate({bool recursive = false}) {
- Node node = internalCreateSync(
+ Node? _doCreate({bool recursive = false}) {
+ Node? node = internalCreateSync(
followTailLink: true,
createChild: (DirectoryNode parent, bool isFinalSegment) {
if (isFinalSegment) {
@@ -66,9 +67,9 @@
return null;
},
);
- if (node.type != expectedType) {
+ if (node?.type != expectedType) {
// There was an existing non-file entity at this object's path
- assert(node.type == FileSystemEntityType.directory);
+ assert(node?.type == FileSystemEntityType.directory);
throw common.isADirectory(path);
}
return node;
@@ -102,7 +103,7 @@
segmentVisitor: (
DirectoryNode parent,
String childName,
- Node child,
+ Node? child,
int currentSegment,
int finalSegment,
) {
@@ -188,7 +189,7 @@
}
@override
- Stream<Uint8List> openRead([int start, int end]) {
+ Stream<Uint8List> openRead([int? start, int? end]) {
try {
FileNode node = resolvedBacking as FileNode;
Uint8List content = node.content;
@@ -317,8 +318,8 @@
io.FileMode mode,
Encoding encoding,
) {
- FileNode node;
- Exception deferredException;
+ late FileNode node;
+ Exception? deferredException;
// Resolve the backing immediately to ensure that the [FileNode] we write
// to is the same as when [openWrite] was called. This can matter if the
@@ -341,15 +342,12 @@
return _FileSink._(future, encoding);
}
- _FileSink._(this._node, this.encoding) {
- _pendingWrites = _node;
- }
+ _FileSink._(Future<FileNode> _node, this.encoding) : _pendingWrites = _node;
- final Future<FileNode> _node;
final Completer<void> _completer = Completer<void>();
Future<FileNode> _pendingWrites;
- Completer<void> _streamCompleter;
+ Completer<void>? _streamCompleter;
bool _isClosed = false;
@override
@@ -368,13 +366,13 @@
}
@override
- void write(Object obj) => add(encoding.encode(obj?.toString() ?? 'null'));
+ void write(Object? obj) => add(encoding.encode(obj?.toString() ?? 'null'));
@override
void writeAll(Iterable<dynamic> objects, [String separator = '']) {
bool firstIter = true;
for (dynamic obj in objects) {
- if (!firstIter && separator != null) {
+ if (!firstIter) {
write(separator);
}
firstIter = false;
@@ -383,7 +381,7 @@
}
@override
- void writeln([Object obj = '']) {
+ void writeln([Object? obj = '']) {
write(obj);
write('\n');
}
@@ -392,7 +390,7 @@
void writeCharCode(int charCode) => write(String.fromCharCode(charCode));
@override
- void addError(dynamic error, [StackTrace stackTrace]) {
+ void addError(Object error, [StackTrace? stackTrace]) {
_checkNotStreaming();
_completer.completeError(error, stackTrace);
}
@@ -402,20 +400,20 @@
_checkNotStreaming();
_streamCompleter = Completer<void>();
void finish() {
- _streamCompleter.complete();
+ _streamCompleter!.complete();
_streamCompleter = null;
}
stream.listen(
(List<int> data) => _addData(data),
cancelOnError: true,
- onError: (dynamic error, StackTrace stackTrace) {
+ onError: (Object error, StackTrace stackTrace) {
_completer.completeError(error, stackTrace);
finish();
},
onDone: finish,
);
- return _streamCompleter.future;
+ return _streamCompleter!.future;
}
@override
@@ -431,7 +429,7 @@
_isClosed = true;
_pendingWrites.then(
(_) => _completer.complete(),
- onError: (dynamic error, StackTrace stackTrace) =>
+ onError: (Object error, StackTrace stackTrace) =>
_completer.completeError(error, stackTrace),
);
}
diff --git a/packages/file/lib/src/backends/memory/memory_file_stat.dart b/packages/file/lib/src/backends/memory/memory_file_stat.dart
index deadb8a..0e158cc 100644
--- a/packages/file/lib/src/backends/memory/memory_file_stat.dart
+++ b/packages/file/lib/src/backends/memory/memory_file_stat.dart
@@ -2,6 +2,7 @@
// 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.10
import 'package:file/src/io.dart' as io;
/// Internal implementation of [io.FileStat].
@@ -16,16 +17,16 @@
this.size,
);
- const MemoryFileStat._internalNotFound()
- : changed = null,
- modified = null,
- accessed = null,
+ MemoryFileStat._internalNotFound()
+ : changed = DateTime(0),
+ modified = DateTime(0),
+ accessed = DateTime(0),
type = io.FileSystemEntityType.notFound,
mode = 0,
size = -1;
/// Shared instance representing a non-existent entity.
- static const MemoryFileStat notFound = MemoryFileStat._internalNotFound();
+ static final MemoryFileStat notFound = MemoryFileStat._internalNotFound();
@override
final DateTime changed;
diff --git a/packages/file/lib/src/backends/memory/memory_file_system.dart b/packages/file/lib/src/backends/memory/memory_file_system.dart
index 0451326..679f1fc 100644
--- a/packages/file/lib/src/backends/memory/memory_file_system.dart
+++ b/packages/file/lib/src/backends/memory/memory_file_system.dart
@@ -2,11 +2,11 @@
// 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.10
import 'dart:async';
import 'package:file/file.dart';
import 'package:file/src/io.dart' as io;
-import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;
import 'clock.dart';
@@ -74,16 +74,15 @@
implements MemoryFileSystem, NodeBasedFileSystem {
_MemoryFileSystem({
this.style = FileSystemStyle.posix,
- @required this.clock,
- }) : assert(style != null),
- assert(clock != null) {
- _root = RootNode(this);
+ required this.clock,
+ }) {
_context = style.contextFor(style.root);
+ _root = RootNode(this);
}
- RootNode _root;
- String _systemTemp;
- p.Context _context;
+ RootNode? _root;
+ String? _systemTemp;
+ late p.Context _context;
@override
final Clock clock;
@@ -92,7 +91,7 @@
final FileSystemStyle style;
@override
- RootNode get root => _root;
+ RootNode? get root => _root;
@override
String get cwd => _context.current;
@@ -133,9 +132,9 @@
}
value = directory(value).resolveSymbolicLinksSync();
- Node node = findNode(value);
+ Node? node = findNode(value);
checkExists(node, () => value);
- utils.checkIsDir(node, () => value);
+ utils.checkIsDir(node!, () => value);
assert(_context.isAbsolute(value));
_context = style.contextFor(value);
}
@@ -158,9 +157,9 @@
@override
bool identicalSync(String path1, String path2) {
- Node node1 = findNode(path1);
+ Node? node1 = findNode(path1);
checkExists(node1, () => path1);
- Node node2 = findNode(path2);
+ Node? node2 = findNode(path2);
checkExists(node2, () => path2);
return node1 != null && node1 == node2;
}
@@ -177,7 +176,7 @@
@override
io.FileSystemEntityType typeSync(String path, {bool followLinks = true}) {
- Node node;
+ Node? node;
try {
node = findNode(path, followTailLink: followLinks);
} on io.FileSystemException {
@@ -195,18 +194,14 @@
DirectoryNode get _current => findNode(cwd) as DirectoryNode;
@override
- Node findNode(
+ Node? findNode(
String path, {
- Node reference,
- SegmentVisitor segmentVisitor,
+ Node? reference,
+ SegmentVisitor? segmentVisitor,
bool visitLinks = false,
- List<String> pathWithSymlinks,
+ List<String>? pathWithSymlinks,
bool followTailLink = false,
}) {
- if (path == null) {
- throw ArgumentError.notNull('path');
- }
-
if (_context.isAbsolute(path)) {
reference = _root;
path = path.substring(style.drive.length);
@@ -216,8 +211,8 @@
List<String> parts = path.split(style.separator)
..removeWhere(utils.isEmpty);
- DirectoryNode directory = reference.directory;
- Node child = directory;
+ DirectoryNode? directory = reference?.directory;
+ Node? child = directory;
int finalSegment = parts.length - 1;
for (int i = 0; i <= finalSegment; i++) {
@@ -229,11 +224,11 @@
child = directory;
break;
case _parentDir:
- child = directory.parent;
- directory = directory.parent;
+ child = directory?.parent;
+ directory = directory?.parent;
break;
default:
- child = directory.children[basename];
+ child = directory?.children[basename];
}
if (pathWithSymlinks != null) {
@@ -246,7 +241,8 @@
if (utils.isLink(child) && (i < finalSegment || followTailLink)) {
if (visitLinks || segmentVisitor == null) {
if (segmentVisitor != null) {
- child = segmentVisitor(directory, basename, child, i, finalSegment);
+ child =
+ segmentVisitor(directory!, basename, child, i, finalSegment);
}
child = utils.resolveLinks(child as LinkNode, subpath,
ledger: pathWithSymlinks);
@@ -255,18 +251,18 @@
child as LinkNode,
subpath,
ledger: pathWithSymlinks,
- tailVisitor: (DirectoryNode parent, String childName, Node child) {
+ tailVisitor: (DirectoryNode parent, String childName, Node? child) {
return segmentVisitor(parent, childName, child, i, finalSegment);
},
);
}
} else if (segmentVisitor != null) {
- child = segmentVisitor(directory, basename, child, i, finalSegment);
+ child = segmentVisitor(directory!, basename, child, i, finalSegment);
}
if (i < finalSegment) {
checkExists(child, subpath);
- utils.checkIsDir(child, subpath);
+ utils.checkIsDir(child!, subpath);
directory = child as DirectoryNode;
}
}
diff --git a/packages/file/lib/src/backends/memory/memory_file_system_entity.dart b/packages/file/lib/src/backends/memory/memory_file_system_entity.dart
index 3ff5ba9..fa0b0a6 100644
--- a/packages/file/lib/src/backends/memory/memory_file_system_entity.dart
+++ b/packages/file/lib/src/backends/memory/memory_file_system_entity.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:file/file.dart';
@@ -47,7 +48,7 @@
/// Gets the node that backs this file system entity, or null if this
/// entity does not exist.
@protected
- Node get backingOrNull {
+ Node? get backingOrNull {
try {
return fileSystem.findNode(path);
} on io.FileSystemException {
@@ -61,9 +62,9 @@
/// The type of the node is not guaranteed to match [expectedType].
@protected
Node get backing {
- Node node = fileSystem.findNode(path);
+ Node? node = fileSystem.findNode(path);
checkExists(node, () => path);
- return node;
+ return node!;
}
/// Gets the node that backs this file system entity, or if that node is
@@ -112,7 +113,7 @@
if (isAbsolute) {
ledger.add(fileSystem.style.drive);
}
- Node node = fileSystem.findNode(path,
+ Node? node = fileSystem.findNode(path,
pathWithSymlinks: ledger, followTailLink: true);
checkExists(node, () => path);
String resolved = ledger.join(fileSystem.path.separator);
@@ -181,8 +182,8 @@
/// If [followTailLink] is true and the result node is a link, this will
/// resolve it to its target prior to returning it.
@protected
- Node internalCreateSync({
- Node createChild(DirectoryNode parent, bool isFinalSegment),
+ Node? internalCreateSync({
+ required Node? createChild(DirectoryNode parent, bool isFinalSegment),
bool followTailLink = false,
bool visitLinks = false,
}) {
@@ -193,7 +194,7 @@
segmentVisitor: (
DirectoryNode parent,
String childName,
- Node child,
+ Node? child,
int currentSegment,
int finalSegment,
) {
@@ -238,9 +239,9 @@
@protected
FileSystemEntity internalRenameSync<T extends Node>(
String newPath, {
- RenameOverwriteValidator<T> validateOverwriteExistingEntity,
+ RenameOverwriteValidator<T>? validateOverwriteExistingEntity,
bool followTailLink = false,
- utils.TypeChecker checkType,
+ utils.TypeChecker? checkType,
}) {
Node node = backing;
(checkType ?? defaultCheckType)(node);
@@ -249,7 +250,7 @@
segmentVisitor: (
DirectoryNode parent,
String childName,
- Node child,
+ Node? child,
int currentSegment,
int finalSegment,
) {
@@ -286,7 +287,7 @@
@protected
void internalDeleteSync({
bool recursive = false,
- utils.TypeChecker checkType,
+ utils.TypeChecker? checkType,
}) {
Node node = backing;
if (!recursive) {
diff --git a/packages/file/lib/src/backends/memory/memory_link.dart b/packages/file/lib/src/backends/memory/memory_link.dart
index b22e2fd..895cfe4 100644
--- a/packages/file/lib/src/backends/memory/memory_link.dart
+++ b/packages/file/lib/src/backends/memory/memory_link.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:file/file.dart';
diff --git a/packages/file/lib/src/backends/memory/memory_random_access_file.dart b/packages/file/lib/src/backends/memory/memory_random_access_file.dart
index b30389f..3998cb8 100644
--- a/packages/file/lib/src/backends/memory/memory_random_access_file.dart
+++ b/packages/file/lib/src/backends/memory/memory_random_access_file.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:convert';
import 'dart:math' as math show min;
import 'dart:typed_data';
@@ -232,11 +233,11 @@
}
@override
- Future<int> readInto(List<int> buffer, [int start = 0, int end]) =>
+ Future<int> readInto(List<int> buffer, [int start = 0, int? end]) =>
_asyncWrapper(() => readIntoSync(buffer, start, end));
@override
- int readIntoSync(List<int> buffer, [int start = 0, int end]) {
+ int readIntoSync(List<int> buffer, [int start = 0, int? end]) {
_checkOpen();
_checkAsync();
_checkReadable('readInto');
@@ -349,14 +350,14 @@
Future<io.RandomAccessFile> writeFrom(
List<int> buffer, [
int start = 0,
- int end,
+ int? end,
]) async {
await _asyncWrapper(() => writeFromSync(buffer, start, end));
return this;
}
@override
- void writeFromSync(List<int> buffer, [int start = 0, int end]) {
+ void writeFromSync(List<int> buffer, [int start = 0, int? end]) {
_checkOpen();
_checkAsync();
_checkWritable('writeFrom');
diff --git a/packages/file/lib/src/backends/memory/node.dart b/packages/file/lib/src/backends/memory/node.dart
index e7a4029..476af38 100644
--- a/packages/file/lib/src/backends/memory/node.dart
+++ b/packages/file/lib/src/backends/memory/node.dart
@@ -2,6 +2,8 @@
// 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.10
+
import 'dart:typed_data';
import 'package:file/file.dart';
@@ -30,10 +32,10 @@
///
/// [finalSegment] is the index of the final segment that will be walked by
/// [NodeBasedFileSystem.findNode].
-typedef SegmentVisitor = Node Function(
+typedef SegmentVisitor = Node? Function(
DirectoryNode parent,
String childName,
- Node childNode,
+ Node? childNode,
int currentSegment,
int finalSegment,
);
@@ -42,7 +44,7 @@
/// instances, rooted at a single node.
abstract class NodeBasedFileSystem implements StyleableFileSystem {
/// The root node.
- RootNode get root;
+ RootNode? get root;
/// The path of the current working directory.
String get cwd;
@@ -80,7 +82,7 @@
/// If [pathWithSymlinks] is specified, the path to the node with symbolic
/// links explicitly broken out will be appended to the buffer. `..` and `.`
/// path segments will *not* be resolved and are left to the caller.
- Node findNode(
+ Node? findNode(
String path, {
Node reference,
SegmentVisitor segmentVisitor,
@@ -104,14 +106,13 @@
}
}
- DirectoryNode _parent;
+ DirectoryNode? _parent;
/// Gets the directory that holds this node.
- DirectoryNode get parent => _parent;
+ DirectoryNode get parent => _parent!;
/// Reparents this node to live in the specified directory.
set parent(DirectoryNode parent) {
- assert(parent != null);
DirectoryNode ancestor = parent;
while (!ancestor.isRoot) {
if (ancestor == this) {
@@ -132,13 +133,13 @@
/// Returns the closest directory in the ancestry hierarchy starting with
/// this node. For directory nodes, it returns the node itself; for other
/// nodes, it returns the parent node.
- DirectoryNode get directory => _parent;
+ DirectoryNode get directory => _parent!;
/// Tells if this node is a root node.
bool get isRoot => false;
/// Returns the file system responsible for this node.
- NodeBasedFileSystem get fs => _parent.fs;
+ NodeBasedFileSystem get fs => _parent!.fs;
}
/// Base class that represents the backing for those nodes that have
@@ -146,7 +147,7 @@
/// you call [stat] on them).
abstract class RealNode extends Node {
/// Constructs a new [RealNode] as a child of the specified [parent].
- RealNode(DirectoryNode parent) : super(parent) {
+ RealNode(DirectoryNode? parent) : super(parent) {
int now = clock.now.millisecondsSinceEpoch;
changed = now;
modified = now;
@@ -157,13 +158,13 @@
Clock get clock => parent.clock;
/// Last changed time in milliseconds since the Epoch.
- int changed;
+ late int changed;
/// Last modified time in milliseconds since the Epoch.
- int modified;
+ late int modified;
/// Last accessed time in milliseconds since the Epoch.
- int accessed;
+ late int accessed;
/// Bitmask representing the file read/write/execute mode.
int mode = 0x777;
@@ -192,7 +193,7 @@
/// Class that represents the backing for an in-memory directory.
class DirectoryNode extends RealNode {
/// Constructs a new [DirectoryNode] as a child of the specified [parent].
- DirectoryNode(DirectoryNode parent) : super(parent);
+ DirectoryNode(DirectoryNode? parent) : super(parent);
/// Child nodes, indexed by their basename.
final Map<String, Node> children = <String, Node>{};
@@ -211,8 +212,7 @@
class RootNode extends DirectoryNode {
/// Constructs a new [RootNode] tied to the specified file system.
RootNode(this.fs)
- : assert(fs != null),
- assert(fs.root == null),
+ : assert(fs.root == null),
super(null);
@override
@@ -285,7 +285,7 @@
/// Constructs a new [LinkNode] as a child of the specified [parent] and
/// linking to the specified [target] path.
LinkNode(DirectoryNode parent, this.target)
- : assert(target != null && target.isNotEmpty),
+ : assert(target.isNotEmpty),
super(parent);
/// The path to which this link points.
@@ -304,15 +304,15 @@
/// target cannot be traversed into, a [FileSystemException] will be thrown,
/// and [tailVisitor] will not be invoked.
Node getReferent({
- Node tailVisitor(DirectoryNode parent, String childName, Node child),
+ Node? tailVisitor(DirectoryNode parent, String childName, Node? child)?,
}) {
- Node referent = fs.findNode(
+ Node? referent = fs.findNode(
target,
reference: this,
segmentVisitor: (
DirectoryNode parent,
String childName,
- Node child,
+ Node? child,
int currentSegment,
int finalSegment,
) {
@@ -323,12 +323,12 @@
},
);
checkExists(referent, () => target);
- return referent;
+ return referent!;
}
/// Gets the node backing for this link's target, or null if this link
/// references a non-existent file system entity.
- Node get referentOrNull {
+ Node? get referentOrNull {
try {
return getReferent();
} on io.FileSystemException {
@@ -346,7 +346,7 @@
}
_reentrant = true;
try {
- Node node = referentOrNull;
+ Node? node = referentOrNull;
return node == null ? MemoryFileStat.notFound : node.stat;
} finally {
_reentrant = false;
diff --git a/packages/file/lib/src/backends/memory/style.dart b/packages/file/lib/src/backends/memory/style.dart
index 701c9d0..945afe8 100644
--- a/packages/file/lib/src/backends/memory/style.dart
+++ b/packages/file/lib/src/backends/memory/style.dart
@@ -2,6 +2,7 @@
// 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.10
import 'package:file/file.dart';
import 'package:path/path.dart' as p;
diff --git a/packages/file/lib/src/backends/memory/utils.dart b/packages/file/lib/src/backends/memory/utils.dart
index de1b6ae..e27a82a 100644
--- a/packages/file/lib/src/backends/memory/utils.dart
+++ b/packages/file/lib/src/backends/memory/utils.dart
@@ -2,6 +2,7 @@
// 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.10
import 'package:file/file.dart';
import 'package:file/src/common.dart' as common;
import 'package:file/src/io.dart' as io;
@@ -10,13 +11,13 @@
import 'node.dart';
/// Checks if `node.type` returns [io.FileSystemEntityType.FILE].
-bool isFile(Node node) => node?.type == io.FileSystemEntityType.file;
+bool isFile(Node? node) => node?.type == io.FileSystemEntityType.file;
/// Checks if `node.type` returns [io.FileSystemEntityType.DIRECTORY].
-bool isDirectory(Node node) => node?.type == io.FileSystemEntityType.directory;
+bool isDirectory(Node? node) => node?.type == io.FileSystemEntityType.directory;
/// Checks if `node.type` returns [io.FileSystemEntityType.LINK].
-bool isLink(Node node) => node?.type == io.FileSystemEntityType.link;
+bool isLink(Node? node) => node?.type == io.FileSystemEntityType.link;
/// Validator function that is expected to throw a [FileSystemException] if
/// the node does not represent the type that is expected in any given context.
@@ -81,8 +82,8 @@
Node resolveLinks(
LinkNode link,
PathGenerator path, {
- List<String> ledger,
- Node tailVisitor(DirectoryNode parent, String childName, Node child),
+ List<String>? ledger,
+ Node? tailVisitor(DirectoryNode parent, String childName, Node? child)?,
}) {
// Record a breadcrumb trail to guard against symlink loops.
Set<LinkNode> breadcrumbs = Set<LinkNode>();
@@ -102,7 +103,7 @@
ledger.addAll(link.target.split(link.fs.path.separator));
}
node = link.getReferent(
- tailVisitor: (DirectoryNode parent, String childName, Node child) {
+ tailVisitor: (DirectoryNode parent, String childName, Node? child) {
if (tailVisitor != null && !isLink(child)) {
// Only invoke [tailListener] on the final resolution pass.
child = tailVisitor(parent, childName, child);
diff --git a/packages/file/lib/src/backends/record_replay/codecs.dart b/packages/file/lib/src/backends/record_replay/codecs.dart
deleted file mode 100644
index 01f4abe..0000000
--- a/packages/file/lib/src/backends/record_replay/codecs.dart
+++ /dev/null
@@ -1,774 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io' show systemEncoding;
-import 'dart:typed_data';
-
-import 'package:file/file.dart';
-import 'package:path/path.dart' as path;
-
-import 'common.dart';
-import 'errors.dart';
-import 'events.dart';
-import 'replay_directory.dart';
-import 'replay_file.dart';
-import 'replay_file_stat.dart';
-import 'replay_file_system.dart';
-import 'replay_io_sink.dart';
-import 'replay_link.dart';
-import 'replay_random_access_file.dart';
-import 'result_reference.dart';
-
-/// Encodes an arbitrary [object] into a JSON-ready representation (a number,
-/// boolean, string, null, list, or map).
-///
-/// Returns a value suitable for conversion into JSON using [JsonEncoder]
-/// without the need for a `toEncodable` argument.
-dynamic encode(dynamic object) => const _GenericEncoder().convert(object);
-
-typedef _ConverterDelegate<S, T> = T Function(S input);
-
-class _ForwardingConverter<S, T> extends Converter<S, T> {
- const _ForwardingConverter(this._delegate);
-
- final _ConverterDelegate<S, T> _delegate;
-
- @override
- T convert(S input) => _delegate(input);
-}
-
-class _GenericEncoder extends Converter<dynamic, dynamic> {
- const _GenericEncoder();
-
- /// Known encoders. Types not covered here will be encoded as a [String]
- /// whose value is the runtime type of the object being encoded.
- ///
- /// When encoding an object, we will walk this map in insertion order looking
- /// for a matching encoder. Thus, when there are two encoders that match an
- /// object, the first one will win.
- static const Map<TypeMatcher<dynamic>, Converter<Object, Object>> _encoders =
- <TypeMatcher<dynamic>, Converter<Object, Object>>{
- TypeMatcher<num>(): Passthrough<num>(),
- TypeMatcher<bool>(): Passthrough<bool>(),
- TypeMatcher<String>(): Passthrough<String>(),
- TypeMatcher<Null>(): Passthrough<Null>(),
- TypeMatcher<Iterable<dynamic>>(): _IterableEncoder(),
- TypeMatcher<Map<dynamic, dynamic>>(): _MapEncoder(),
- TypeMatcher<Symbol>(): _SymbolEncoder(),
- TypeMatcher<DateTime>(): DateTimeCodec.serialize,
- TypeMatcher<Uri>(): UriCodec.serialize,
- TypeMatcher<path.Context>(): PathContextCodec.serialize,
- TypeMatcher<ResultReference<dynamic>>(): _ResultEncoder(),
- TypeMatcher<LiveInvocationEvent<dynamic>>(): _EventEncoder(),
- TypeMatcher<ReplayAware>(): _ReplayAwareEncoder(),
- TypeMatcher<Encoding>(): EncodingCodec.serialize,
- TypeMatcher<FileMode>(): _FileModeEncoder(),
- TypeMatcher<FileStat>(): FileStatCodec.serialize,
- TypeMatcher<FileSystemEntityType>(): EntityTypeCodec.serialize,
- TypeMatcher<FileSystemEvent>(): FileSystemEventCodec.serialize,
- TypeMatcher<FileSystemException>(): _FSExceptionCodec.serialize,
- TypeMatcher<OSError>(): _OSErrorCodec.serialize,
- TypeMatcher<ArgumentError>(): _ArgumentErrorCodec.serialize,
- TypeMatcher<NoSuchMethodError>(): _NoSuchMethodErrorCodec.serialize,
- };
-
- @override
- dynamic convert(dynamic input) {
- for (TypeMatcher<dynamic> matcher in _encoders.keys) {
- if (matcher.matches(input)) {
- return _encoders[matcher].convert(input);
- }
- }
- return input.runtimeType.toString();
- }
-}
-
-/// A trivial conversion turning a Sink<List<String>> into a
-/// Sink<String>
-class _StringSinkWrapper implements Sink<String> {
- _StringSinkWrapper(this._sink);
-
- final Sink<List<String>> _sink;
-
- @override
- void add(String s) => _sink.add(<String>[s]);
-
- @override
- void close() => _sink.close();
-}
-
-/// A [Converter] version of the dart:convert [LineSplitter] (which in
-/// 2.0 no longer implements the [Converter] interface).
-class LineSplitterConverter extends Converter<String, List<String>> {
- /// Creates a new [LineSplitterConverter]
- const LineSplitterConverter();
-
- LineSplitter get _splitter => const LineSplitter();
-
- @override
- List<String> convert(String input) => _splitter.convert(input);
- @override
- StringConversionSink startChunkedConversion(Sink<List<String>> sink) =>
- _splitter.startChunkedConversion(_StringSinkWrapper(sink));
-}
-
-/// Converter that leaves an object untouched.
-class Passthrough<T> extends Converter<T, T> {
- /// Creates a new [Passthrough].
- const Passthrough();
-
- @override
- T convert(T input) => input;
-}
-
-class _IterableEncoder extends Converter<Iterable<dynamic>, List<dynamic>> {
- const _IterableEncoder();
-
- @override
- List<dynamic> convert(Iterable<dynamic> input) {
- _GenericEncoder generic = const _GenericEncoder();
- List<dynamic> encoded = <dynamic>[];
- for (Object element in input) {
- encoded.add(generic.convert(element));
- }
- return encoded;
- }
-}
-
-class _MapEncoder
- extends Converter<Map<dynamic, dynamic>, Map<String, dynamic>> {
- const _MapEncoder();
-
- @override
- Map<String, dynamic> convert(Map<dynamic, dynamic> input) {
- _GenericEncoder generic = const _GenericEncoder();
- Map<String, dynamic> encoded = <String, dynamic>{};
- for (dynamic key in input.keys) {
- String encodedKey = generic.convert(key) as String;
- encoded[encodedKey] = generic.convert(input[key]);
- }
- return encoded;
- }
-}
-
-class _SymbolEncoder extends Converter<Symbol, String> {
- const _SymbolEncoder();
-
- @override
- String convert(Symbol input) => getSymbolName(input);
-}
-
-/// A [DateTimeCodec] serializes and deserializes [DateTime] instances.
-class DateTimeCodec extends Codec<DateTime, int> {
- /// Creates a new [DateTimeCodec].
- const DateTimeCodec();
-
- static int _encode(DateTime input) => input?.millisecondsSinceEpoch;
-
- static DateTime _decode(int input) {
- return input == null ? null : DateTime.fromMillisecondsSinceEpoch(input);
- }
-
- /// Converter that serializes [DateTime] instances.
- static const Converter<DateTime, int> serialize =
- _ForwardingConverter<DateTime, int>(_encode);
-
- /// Converter that deserializes [DateTime] instances.
- static const Converter<int, DateTime> deserialize =
- _ForwardingConverter<int, DateTime>(_decode);
-
- @override
- Converter<DateTime, int> get encoder => serialize;
-
- @override
- Converter<int, DateTime> get decoder => deserialize;
-}
-
-/// A [UriCodec] serializes and deserializes [Uri] instances.
-class UriCodec extends Codec<Uri, String> {
- /// Creates a new [UriCodec].
- const UriCodec();
-
- static String _encode(Uri input) => input.toString();
-
- static Uri _decode(String input) => Uri.parse(input);
-
- /// Converter that serializes [Uri] instances.
- static const Converter<Uri, String> serialize =
- _ForwardingConverter<Uri, String>(_encode);
-
- /// Converter that deserializes [Uri] instances.
- static const Converter<String, Uri> deserialize =
- _ForwardingConverter<String, Uri>(_decode);
-
- @override
- Converter<Uri, String> get encoder => serialize;
-
- @override
- Converter<String, Uri> get decoder => deserialize;
-}
-
-/// A [PathContextCodec] serializes and deserializes [path.Context] instances.
-class PathContextCodec extends Codec<path.Context, Map<String, dynamic>> {
- /// Creates a new [PathContextCodec].
- const PathContextCodec();
-
- static Map<String, dynamic> _encode(path.Context input) {
- return <String, String>{
- 'style': input.style.name,
- 'cwd': input.current,
- };
- }
-
- static path.Context _decode(Map<String, dynamic> input) {
- return path.Context(
- style: <String, path.Style>{
- 'posix': path.Style.posix,
- 'windows': path.Style.windows,
- 'url': path.Style.url,
- }[input['style']],
- current: input['cwd'] as String,
- );
- }
-
- /// Converter that serializes [path.Context] instances.
- static const Converter<path.Context, Map<String, dynamic>> serialize =
- _ForwardingConverter<path.Context, Map<String, dynamic>>(_encode);
-
- /// Converter that deserializes [path.Context] instances.
- static const Converter<Map<String, dynamic>, path.Context> deserialize =
- _ForwardingConverter<Map<String, dynamic>, path.Context>(_decode);
-
- @override
- Converter<path.Context, Map<String, dynamic>> get encoder => serialize;
-
- @override
- Converter<Map<String, dynamic>, path.Context> get decoder => deserialize;
-}
-
-class _ResultEncoder extends Converter<ResultReference<dynamic>, Object> {
- const _ResultEncoder();
-
- @override
- Object convert(ResultReference<dynamic> input) => input.serializedValue;
-}
-
-class _EventEncoder
- extends Converter<LiveInvocationEvent<dynamic>, Map<String, Object>> {
- const _EventEncoder();
-
- @override
- Map<String, Object> convert(LiveInvocationEvent<dynamic> input) {
- return input.serialize();
- }
-}
-
-class _ReplayAwareEncoder extends Converter<ReplayAware, String> {
- const _ReplayAwareEncoder();
-
- @override
- String convert(ReplayAware input) => input.identifier;
-}
-
-/// An [EncodingCodec] serializes and deserializes [Encoding] instances.
-class EncodingCodec extends Codec<Encoding, String> {
- /// Creates a new [EncodingCodec].
- const EncodingCodec();
-
- static String _encode(Encoding input) => input.name;
-
- static Encoding _decode(String input) {
- if (input == 'system') {
- return systemEncoding;
- } else if (input != null) {
- return Encoding.getByName(input);
- }
- return null;
- }
-
- /// Converter that serializes [Encoding] instances.
- static const Converter<Encoding, String> serialize =
- _ForwardingConverter<Encoding, String>(_encode);
-
- /// Converter that deserializes [Encoding] instances.
- static const Converter<String, Encoding> deserialize =
- _ForwardingConverter<String, Encoding>(_decode);
-
- @override
- Converter<Encoding, String> get encoder => serialize;
-
- @override
- Converter<String, Encoding> get decoder => deserialize;
-}
-
-class _FileModeEncoder extends Converter<FileMode, String> {
- const _FileModeEncoder();
-
- @override
- String convert(FileMode input) {
- switch (input) {
- case FileMode.read:
- return 'READ';
- case FileMode.write:
- return 'WRITE';
- case FileMode.append:
- return 'APPEND';
- case FileMode.writeOnly:
- return 'WRITE_ONLY';
- case FileMode.writeOnlyAppend:
- return 'WRITE_ONLY_APPEND';
- }
- throw ArgumentError('Invalid value: $input');
- }
-}
-
-/// An [FileStatCodec] serializes and deserializes [FileStat] instances.
-class FileStatCodec extends Codec<FileStat, Map<String, Object>> {
- /// Creates a new [FileStatCodec].
- const FileStatCodec();
-
- static Map<String, Object> _encode(FileStat input) {
- return <String, dynamic>{
- 'changed': const DateTimeCodec().encode(input.changed),
- 'modified': const DateTimeCodec().encode(input.modified),
- 'accessed': const DateTimeCodec().encode(input.accessed),
- 'type': const EntityTypeCodec().encode(input.type),
- 'mode': input.mode,
- 'size': input.size,
- 'modeString': input.modeString(),
- };
- }
-
- static FileStat _decode(Map<String, Object> input) => ReplayFileStat(input);
-
- /// Converter that serializes [FileStat] instances.
- static const Converter<FileStat, Map<String, Object>> serialize =
- _ForwardingConverter<FileStat, Map<String, Object>>(_encode);
-
- /// Converter that deserializes [FileStat] instances.
- static const Converter<Map<String, Object>, FileStat> deserialize =
- _ForwardingConverter<Map<String, Object>, FileStat>(_decode);
-
- @override
- Converter<FileStat, Map<String, Object>> get encoder => serialize;
-
- @override
- Converter<Map<String, Object>, FileStat> get decoder => deserialize;
-}
-
-/// An [EntityTypeCodec] serializes and deserializes [FileSystemEntity]
-/// instances.
-class EntityTypeCodec extends Codec<FileSystemEntityType, String> {
- /// Creates a new [EntityTypeCodec].
- const EntityTypeCodec();
-
- static String _encode(FileSystemEntityType input) => input.toString();
-
- static FileSystemEntityType _decode(String input) {
- return const <String, FileSystemEntityType>{
- 'file': FileSystemEntityType.file,
- 'directory': FileSystemEntityType.directory,
- 'link': FileSystemEntityType.link,
- 'notFound': FileSystemEntityType.notFound,
- }[input];
- }
-
- /// Converter that serializes [FileSystemEntityType] instances.
- static const Converter<FileSystemEntityType, String> serialize =
- _ForwardingConverter<FileSystemEntityType, String>(_encode);
-
- /// Converter that deserializes [FileSystemEntityType] instances.
- static const Converter<String, FileSystemEntityType> deserialize =
- _ForwardingConverter<String, FileSystemEntityType>(_decode);
-
- @override
- Converter<FileSystemEntityType, String> get encoder => serialize;
-
- @override
- Converter<String, FileSystemEntityType> get decoder => deserialize;
-}
-
-/// A [FileSystemEventCodec] serializes and deserializes [FileSystemEvent]
-/// instances.
-class FileSystemEventCodec extends Codec<FileSystemEvent, Map<String, Object>> {
- /// Creates a new [FileSystemEventCodec].
- const FileSystemEventCodec();
-
- static Map<String, Object> _encode(FileSystemEvent input) {
- return <String, Object>{
- 'type': input.type,
- 'path': input.path,
- 'isDirectory': input.isDirectory,
- };
- }
-
- static FileSystemEvent _decode(Map<String, Object> input) =>
- _FileSystemEvent(input);
-
- /// Converter that serializes [FileSystemEvent] instances.
- static const Converter<FileSystemEvent, Map<String, Object>> serialize =
- _ForwardingConverter<FileSystemEvent, Map<String, Object>>(_encode);
-
- /// Converter that deserializes [FileSystemEvent] instances.
- static const Converter<Map<String, Object>, FileSystemEvent> deserialize =
- _ForwardingConverter<Map<String, Object>, FileSystemEvent>(_decode);
-
- @override
- Converter<FileSystemEvent, Map<String, Object>> get encoder => serialize;
-
- @override
- Converter<Map<String, Object>, FileSystemEvent> get decoder => deserialize;
-}
-
-class _FileSystemEvent implements FileSystemEvent {
- const _FileSystemEvent(this._data);
-
- final Map<String, Object> _data;
-
- @override
- int get type => _data['type'] as int;
-
- @override
- String get path => _data['path'] as String;
-
- @override
- bool get isDirectory => _data['isDirectory'] as bool;
-}
-
-/// Converts an object into a [Future] that completes with that object.
-class ToFuture<T> extends Converter<T, Future<T>> {
- /// Creates a new [ToFuture].
- const ToFuture();
-
- @override
- Future<T> convert(T input) async => input;
-}
-
-/// Converts an object into a single-element [List] containing that object.
-class Listify<T> extends Converter<T, List<T>> {
- /// Creates a new [Listify].
- const Listify();
-
- @override
- List<T> convert(T input) => <T>[input];
-}
-
-/// Converts a simple [List<int>] to a [Uint8List].
-class ToUint8List extends Converter<List<int>, Uint8List> {
- /// Creates a new [ToUint8List].
- const ToUint8List();
-
- @override
- Uint8List convert(List<int> input) => Uint8List.fromList(input);
-}
-
-/// Revives a [Directory] entity reference into a [ReplayDirectory].
-class ReviveDirectory extends Converter<String, Directory> {
- /// Creates a new [ReviveDirectory].
- const ReviveDirectory(this._fileSystem);
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- Directory convert(String input) => ReplayDirectory(_fileSystem, input);
-}
-
-/// Revives a [File] entity reference into a [ReplayFile].
-class ReviveFile extends Converter<String, File> {
- /// Creates a new [ReviveFile].
- const ReviveFile(this._fileSystem);
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- File convert(String input) => ReplayFile(_fileSystem, input);
-}
-
-/// Revives a [Link] entity reference into a [ReplayLink].
-class ReviveLink extends Converter<String, Link> {
- /// Creates a new [ReviveLink].
- const ReviveLink(this._fileSystem);
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- Link convert(String input) => ReplayLink(_fileSystem, input);
-}
-
-/// Revives a [FileSystemEntity] entity reference into a [ReplayDirectory],
-/// [ReplayFile], or a [ReplayLink] depending on the identifier of the entity
-/// reference.
-class ReviveFileSystemEntity extends Converter<String, FileSystemEntity> {
- /// Creates a new [ReviveFileSystemEntity].
- const ReviveFileSystemEntity(this._fileSystem);
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- FileSystemEntity convert(String input) {
- if (input.contains('Directory')) {
- return ReplayDirectory(_fileSystem, input);
- } else if (input.contains('File')) {
- return ReplayFile(_fileSystem, input);
- } else {
- return ReplayLink(_fileSystem, input);
- }
- }
-}
-
-/// Revives a [RandomAccessFile] entity reference into a
-/// [ReplayRandomAccessFile].
-class ReviveRandomAccessFile extends Converter<String, RandomAccessFile> {
- /// Creates a new [ReviveRandomAccessFile] that will derive its behavior
- /// from the specified file system's recording.
- const ReviveRandomAccessFile(this._fileSystem);
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- RandomAccessFile convert(String input) =>
- ReplayRandomAccessFile(_fileSystem, input);
-}
-
-/// Revives an [IOSink] entity reference into a [ReplayIOSink].
-class ReviveIOSink extends Converter<String, IOSink> {
- /// Creates a new [ReviveIOSink] that will derive its behavior from the
- /// specified file system's recording.
- const ReviveIOSink(this._fileSystem);
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- IOSink convert(String input) => ReplayIOSink(_fileSystem, input);
-}
-
-/// Converts all elements of a [List], returning a new [List] of converted
-/// elements.
-class ConvertElements<S, T> extends Converter<List<S>, List<T>> {
- /// Creates a new [ConvertElements] that will use the specified
- /// [elementConverter] to convert the elements of an [Iterable].
- const ConvertElements(Converter<S, T> elementConverter)
- : _delegate = elementConverter;
-
- final Converter<S, T> _delegate;
-
- @override
- List<T> convert(List<S> input) => input.map(_delegate.convert).toList();
-}
-
-/// Converts a `List<S>` into a `List<T>` by casting it to the appropriate
-/// type. The list must contain only elements of type `T`, or a runtime error
-/// will be thrown.
-class CastList<S, T> extends Converter<List<S>, List<T>> {
- /// Creates a new [CastList].
- const CastList();
-
- @override
- List<T> convert(List<S> input) => input.cast<T>();
-}
-
-/// Converts a [List] of elements into a [Stream] of the same elements.
-class ToStream<T> extends Converter<List<T>, Stream<T>> {
- /// Creates a new [ToStream].
- const ToStream();
-
- @override
- Stream<T> convert(List<T> input) => Stream<T>.fromIterable(input);
-}
-
-/// Converts a blob reference (serialized as a [String] of the form
-/// `!<filename>`) into a byte list.
-class BlobToBytes extends Converter<String, Uint8List> {
- /// Creates a new [BlobToBytes] that will use the specified file system's
- /// recording to load the blob.
- const BlobToBytes(this._fileSystem);
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- Uint8List convert(String input) {
- assert(input.startsWith('!'));
- String basename = input.substring(1);
- String dirname = _fileSystem.recording.path;
- String path = _fileSystem.recording.fileSystem.path.join(dirname, basename);
- File file = _fileSystem.recording.fileSystem.file(path);
- return file.readAsBytesSync();
- }
-}
-
-/// Converts serialized errors into throwable objects.
-class ToError extends Converter<dynamic, dynamic> {
- /// Creates a new [ToError].
- const ToError();
-
- /// Known decoders (keyed by `type`). Types not covered here will be decoded
- /// into [InvocationException].
- static const Map<String, Converter<Object, Object>> _decoders =
- <String, Converter<Object, Object>>{
- _FSExceptionCodec.type: _FSExceptionCodec.deserialize,
- _OSErrorCodec.type: _OSErrorCodec.deserialize,
- _ArgumentErrorCodec.type: _ArgumentErrorCodec.deserialize,
- _NoSuchMethodErrorCodec.type: _NoSuchMethodErrorCodec.deserialize,
- };
-
- @override
- dynamic convert(dynamic input) {
- if (input is Map) {
- String errorType = input[kManifestErrorTypeKey] as String;
- if (_decoders.containsKey(errorType)) {
- return _decoders[errorType].convert(input);
- }
- }
- return InvocationException();
- }
-}
-
-class _FSExceptionCodec
- extends Codec<FileSystemException, Map<String, Object>> {
- const _FSExceptionCodec();
-
- static const String type = 'FileSystemException';
-
- static Map<String, Object> _encode(FileSystemException exception) {
- return <String, Object>{
- kManifestErrorTypeKey: type,
- 'message': exception.message,
- 'path': exception.path,
- 'osError': encode(exception.osError),
- };
- }
-
- static FileSystemException _decode(Map<String, Object> input) {
- Object osError = input['osError'];
- return FileSystemException(
- input['message'] as String,
- input['path'] as String,
- osError == null ? null : const ToError().convert(osError) as OSError,
- );
- }
-
- static const Converter<FileSystemException, Map<String, Object>> serialize =
- _ForwardingConverter<FileSystemException, Map<String, Object>>(_encode);
-
- static const Converter<Map<String, Object>, FileSystemException> deserialize =
- _ForwardingConverter<Map<String, Object>, FileSystemException>(_decode);
-
- @override
- Converter<FileSystemException, Map<String, Object>> get encoder => serialize;
-
- @override
- Converter<Map<String, Object>, FileSystemException> get decoder =>
- deserialize;
-}
-
-class _OSErrorCodec extends Codec<OSError, Map<String, Object>> {
- const _OSErrorCodec();
-
- static const String type = 'OSError';
-
- static Map<String, Object> _encode(OSError error) {
- return <String, Object>{
- kManifestErrorTypeKey: type,
- 'message': error.message,
- 'errorCode': error.errorCode,
- };
- }
-
- static OSError _decode(Map<String, Object> input) {
- return OSError(input['message'] as String, input['errorCode'] as int);
- }
-
- static const Converter<OSError, Map<String, Object>> serialize =
- _ForwardingConverter<OSError, Map<String, Object>>(_encode);
-
- static const Converter<Map<String, Object>, OSError> deserialize =
- _ForwardingConverter<Map<String, Object>, OSError>(_decode);
-
- @override
- Converter<OSError, Map<String, Object>> get encoder => serialize;
-
- @override
- Converter<Map<String, Object>, OSError> get decoder => deserialize;
-}
-
-class _ArgumentErrorCodec extends Codec<ArgumentError, Map<String, Object>> {
- const _ArgumentErrorCodec();
-
- static const String type = 'ArgumentError';
-
- static Map<String, Object> _encode(ArgumentError error) {
- return <String, Object>{
- kManifestErrorTypeKey: type,
- 'message': encode(error.message),
- 'invalidValue': encode(error.invalidValue),
- 'name': error.name,
- };
- }
-
- static ArgumentError _decode(Map<String, Object> input) {
- dynamic message = input['message'];
- dynamic invalidValue = input['invalidValue'];
- String name = input['name'] as String;
- if (invalidValue != null) {
- return ArgumentError.value(invalidValue, name, message);
- } else if (name != null) {
- return ArgumentError.notNull(name);
- } else {
- return ArgumentError(message);
- }
- }
-
- static const Converter<ArgumentError, Map<String, Object>> serialize =
- _ForwardingConverter<ArgumentError, Map<String, Object>>(_encode);
-
- static const Converter<Map<String, Object>, ArgumentError> deserialize =
- _ForwardingConverter<Map<String, Object>, ArgumentError>(_decode);
-
- @override
- Converter<ArgumentError, Map<String, Object>> get encoder => serialize;
-
- @override
- Converter<Map<String, Object>, ArgumentError> get decoder => deserialize;
-}
-
-class _NoSuchMethodErrorCodec
- extends Codec<NoSuchMethodError, Map<String, Object>> {
- const _NoSuchMethodErrorCodec();
-
- static const String type = 'NoSuchMethodError';
-
- static Map<String, Object> _encode(NoSuchMethodError error) {
- return <String, Object>{
- kManifestErrorTypeKey: type,
- 'toString': error.toString(),
- };
- }
-
- static NoSuchMethodError _decode(Map<String, Object> input) {
- return _NoSuchMethodError(input['toString'] as String);
- }
-
- static const Converter<NoSuchMethodError, Map<String, Object>> serialize =
- _ForwardingConverter<NoSuchMethodError, Map<String, Object>>(_encode);
-
- static const Converter<Map<String, Object>, NoSuchMethodError> deserialize =
- _ForwardingConverter<Map<String, Object>, NoSuchMethodError>(_decode);
-
- @override
- Converter<NoSuchMethodError, Map<String, Object>> get encoder => serialize;
-
- @override
- Converter<Map<String, Object>, NoSuchMethodError> get decoder => deserialize;
-}
-
-class _NoSuchMethodError extends Error implements NoSuchMethodError {
- _NoSuchMethodError(this._toString);
-
- final String _toString;
-
- @override
- String toString() => _toString;
-}
diff --git a/packages/file/lib/src/backends/record_replay/common.dart b/packages/file/lib/src/backends/record_replay/common.dart
deleted file mode 100644
index 8fb680c..0000000
--- a/packages/file/lib/src/backends/record_replay/common.dart
+++ /dev/null
@@ -1,193 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'codecs.dart';
-import 'events.dart';
-
-/// Encoded value of the file system in a recording.
-const String kFileSystemEncodedValue = '__fs__';
-
-/// The name of the recording manifest file.
-const String kManifestName = 'MANIFEST.txt';
-
-/// The key in a serialized [InvocationEvent] map that is used to store the
-/// type of invocation.
-///
-/// See also:
-/// - [kGetType]
-/// - [kSetType]
-/// - [kInvokeType]
-const String kManifestTypeKey = 'type';
-
-/// The key in a serialized [InvocationEvent] map that is used to store the
-/// target of the invocation.
-const String kManifestObjectKey = 'object';
-
-/// The key in a serialized [InvocationEvent] map that is used to store the
-/// result (return value) of the invocation.
-const String kManifestResultKey = 'result';
-
-/// The key in a serialized [InvocationEvent] map that is used to store the
-/// error that was thrown during the invocation.
-const String kManifestErrorKey = 'error';
-
-/// The key in a serialized error that is used to store the runtime type of
-/// the error that was thrown.
-const String kManifestErrorTypeKey = 'type';
-
-/// The key in a serialized [InvocationEvent] map that is used to store the
-/// timestamp of the invocation.
-const String kManifestTimestampKey = 'timestamp';
-
-/// The key in a serialized [PropertyGetEvent] or [PropertySetEvent] map that
-/// is used to store the property that was accessed or mutated.
-const String kManifestPropertyKey = 'property';
-
-/// The key in a serialized [PropertySetEvent] map that is used to store the
-/// value to which the property was set.
-const String kManifestValueKey = 'value';
-
-/// The key in a serialized [MethodEvent] map that is used to store the name of
-/// the method that was invoked.
-const String kManifestMethodKey = 'method';
-
-/// The key in a serialized [MethodEvent] map that is used to store the
-/// positional arguments that were passed to the method.
-const String kManifestPositionalArgumentsKey = 'positionalArguments';
-
-/// The key in a serialized [MethodEvent] map that is used to store the
-/// named arguments that were passed to the method.
-const String kManifestNamedArgumentsKey = 'namedArguments';
-
-/// The key in a serialized [InvocationEvent] map that is used to store the
-/// order in which the invocation has been replayed (if it has been replayed).
-const String kManifestOrdinalKey = 'ordinal';
-
-/// The serialized [kManifestTypeKey] for property retrievals.
-const String kGetType = 'get';
-
-/// The serialized [kManifestTypeKey] for property mutations.
-const String kSetType = 'set';
-
-/// The serialized [kManifestTypeKey] for method invocations.
-const String kInvokeType = 'invoke';
-
-/// Gets an id guaranteed to be unique on this isolate for objects within this
-/// library.
-int newUid() => _nextUid++;
-int _nextUid = 1;
-
-/// Gets the name of the specified [symbol].
-// TODO(tvolkert): Symbol.name (https://github.com/dart-lang/sdk/issues/28372)
-String getSymbolName(Symbol symbol) {
- // Format of `str` is `Symbol("<name>")`
- String str = symbol.toString();
- int offset = str.indexOf('"') + 1;
- return str.substring(offset, str.indexOf('"', offset));
-}
-
-/// This class is a work-around for the "is" operator not accepting a variable
-/// value as its right operand (https://github.com/dart-lang/sdk/issues/27680).
-class TypeMatcher<T> {
- /// Creates a type matcher for the given type parameter.
- const TypeMatcher();
-
- static const TypeMatcher<void> _void = TypeMatcher<void>();
-
- /// This matcher's type, `T`.
- Type get type => T;
-
- /// Returns `true` if the given object is of type `T`.
- bool matches(dynamic object) {
- return T == _void.type ? object == T : object is T;
- }
-}
-
-/// Marks a class that, when serialized, will be referred to merely by an
-/// opaque identifier.
-///
-/// Unlike other objects, objects that are replay-aware don't need to serialize
-/// meaningful metadata about their state for the sake of revival. Rather, they
-/// derive all the information they need to operate from the recording. As such,
-/// they are serialized using only an opaque unique identifier. When they are
-/// revived during replay, their identifier allows them to find invocations in
-/// the recording for which they are the target.
-abstract class ReplayAware {
- /// The identifier of this object, guaranteed to be unique within a single
- /// recording.
- String get identifier;
-}
-
-/// Tells whether two objects are equal using deep equality checking.
-///
-/// Two lists are deeply equal if they have the same runtime type, the same
-/// length, and every element in list A is pairwise deeply equal with the
-/// corresponding element in list B.
-///
-/// Two maps are deeply equal if they have the same runtime type, the same
-/// length, the same set of keys, and the value for every key in map A is
-/// deeply equal to the corresponding value in map B.
-///
-/// All other types of objects are deeply equal if they have the same runtime
-/// type and are logically equal (according to `operator==`).
-bool deeplyEqual(dynamic object1, dynamic object2) {
- if (object1.runtimeType != object2.runtimeType) {
- return false;
- } else if (object1 is List) {
- return _areListsEqual<dynamic>(object1, object2 as List<dynamic>);
- } else if (object1 is Map) {
- return _areMapsEqual<dynamic, dynamic>(
- object1, object2 as Map<dynamic, dynamic>);
- } else {
- return object1 == object2;
- }
-}
-
-bool _areListsEqual<T>(List<T> list1, List<T> list2) {
- int i = 0;
- return list1.length == list2.length &&
- list1.every((T element) => deeplyEqual(element, list2[i++]));
-}
-
-bool _areMapsEqual<K, V>(Map<K, V> map1, Map<K, V> map2) {
- return map1.length == map2.length &&
- map1.keys.every((K key) {
- return map1.containsKey(key) == map2.containsKey(key) &&
- deeplyEqual(map1[key], map2[key]);
- });
-}
-
-/// Returns a human-readable representation of an [Invocation].
-String describeInvocation(Invocation invocation) {
- final StringBuffer buffer = StringBuffer()
- ..write(getSymbolName(invocation.memberName));
- if (invocation.isMethod) {
- buffer.write('(');
- int printedCount = 0;
- for (dynamic arg in invocation.positionalArguments) {
- if (printedCount > 0) {
- buffer.write(', ');
- }
- buffer.write(Error.safeToString(encode(arg)));
- printedCount += 1;
- }
- for (final MapEntry<Symbol, dynamic> nameValue
- in invocation.namedArguments.entries) {
- final Symbol name = nameValue.key;
- final dynamic value = nameValue.value;
- if (printedCount > 0) {
- buffer.write(', ');
- }
- buffer.write(
- '${getSymbolName(name)}: ${Error.safeToString(encode(value))}');
- printedCount += 1;
- }
- buffer.write(')');
- } else if (invocation.isSetter) {
- buffer
- ..write(' = ')
- ..write(Error.safeToString(encode(invocation.positionalArguments[0])));
- }
- return buffer.toString();
-}
diff --git a/packages/file/lib/src/backends/record_replay/errors.dart b/packages/file/lib/src/backends/record_replay/errors.dart
deleted file mode 100644
index 3d3fa12..0000000
--- a/packages/file/lib/src/backends/record_replay/errors.dart
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'common.dart';
-
-/// Error thrown during replay when there is no matching invocation in the
-/// recording.
-class NoMatchingInvocationError extends Error {
- /// Creates a new `NoMatchingInvocationError` caused by the failure to replay
- /// the specified [invocation].
- NoMatchingInvocationError(this.invocation);
-
- /// The invocation that was unable to be replayed.
- final Invocation invocation;
-
- @override
- String toString() =>
- 'No matching invocation found: ${describeInvocation(invocation)}';
-}
-
-/// Exception thrown during replay when an invocation recorded error, but we
-/// were unable to find a type-specific converter to deserialize the recorded
-/// error into a more specific exception type.
-class InvocationException implements Exception {}
diff --git a/packages/file/lib/src/backends/record_replay/events.dart b/packages/file/lib/src/backends/record_replay/events.dart
deleted file mode 100644
index 01e5ff4..0000000
--- a/packages/file/lib/src/backends/record_replay/events.dart
+++ /dev/null
@@ -1,216 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-
-import 'codecs.dart';
-import 'common.dart';
-import 'recording.dart';
-import 'result_reference.dart';
-
-/// Base class for recordable file system invocation events.
-///
-/// Instances of this class will be aggregated in a [Recording]
-abstract class InvocationEvent<T> {
- /// The object on which the invocation occurred. Will always be non-null.
- Object get object;
-
- /// The return value of the invocation if the invocation completed
- /// successfully.
- ///
- /// This may be null (and will always be `null` for setters).
- ///
- /// If the invocation completed with an error, this value will be `null`,
- /// and [error] will be set.
- T get result;
-
- /// The error that was thrown by the invocation if the invocation completed
- /// with an error.
- ///
- /// If the invocation completed successfully, this value will be `null`, and
- /// [result] will hold the result of the invocation (which may also be
- /// `null`).
- ///
- /// This field being non-null can be used as an indication that the invocation
- /// completed with an error.
- dynamic get error;
-
- /// The stopwatch value (in milliseconds) when the invocation occurred.
- ///
- /// This value is recorded when the invocation first occurs, not when the
- /// delegate returns.
- int get timestamp;
-}
-
-/// A recordable invocation of a property getter on a file system object.
-abstract class PropertyGetEvent<T> extends InvocationEvent<T> {
- /// The property that was retrieved.
- Symbol get property;
-}
-
-/// A recordable invocation of a property setter on a file system object.
-abstract class PropertySetEvent<T> extends InvocationEvent<Null> {
- /// The property that was set.
- ///
- /// All setter property symbols will have a trailing equals sign. For example,
- /// if the `foo` property was set, this value will be a symbol of `foo=`.
- Symbol get property;
-
- /// The value to which [property] was set. This is distinct from [result],
- /// which is always `null` for setters.
- T get value;
-}
-
-/// A recordable invocation of a method on a file system object.
-abstract class MethodEvent<T> extends InvocationEvent<T> {
- /// The method that was invoked.
- Symbol get method;
-
- /// The positional arguments that were passed to the method.
- List<dynamic> get positionalArguments;
-
- /// The named arguments that were passed to the method.
- Map<Symbol, dynamic> get namedArguments;
-}
-
-/// An [InvocationEvent] that's in the process of being recorded.
-abstract class LiveInvocationEvent<T> implements InvocationEvent<T> {
- /// Creates a new [LiveInvocationEvent].
- LiveInvocationEvent(this.object, this._result, this.error, this.timestamp);
-
- final dynamic _result;
-
- @override
- final Object object;
-
- @override
- T get result {
- dynamic result = _result;
- while (result is ResultReference) {
- ResultReference<dynamic> reference = result as ResultReference<dynamic>;
- result = reference.recordedValue;
- }
- return result as T;
- }
-
- @override
- final dynamic error;
-
- @override
- final int timestamp;
-
- /// A [Future] that completes once [result] is ready for serialization.
- ///
- /// If [result] is a [Future], this future completes when [result] completes.
- /// If [result] is a [Stream], this future completes when the stream sends a
- /// "done" event. If [result] is neither a future nor a stream, this future
- /// completes immediately.
- ///
- /// It is legal for [serialize] to be called before this future completes,
- /// but doing so will cause incomplete results to be serialized. Results that
- /// are unfinished futures will be serialized as `null`, and results that are
- /// unfinished streams will be serialized as the data that has been received
- /// thus far.
- Future<void> get done async {
- dynamic result = _result;
- while (result is ResultReference) {
- ResultReference<dynamic> reference = result as ResultReference<dynamic>;
- await reference.complete;
- result = reference.recordedValue;
- }
- }
-
- /// Returns this event as a JSON-serializable object.
- Map<String, dynamic> serialize() {
- return <String, dynamic>{
- kManifestObjectKey: encode(object),
- kManifestResultKey: encode(_result),
- kManifestErrorKey: encode(error),
- kManifestTimestampKey: timestamp,
- };
- }
-
- @override
- String toString() => serialize().toString();
-}
-
-/// A [PropertyGetEvent] that's in the process of being recorded.
-class LivePropertyGetEvent<T> extends LiveInvocationEvent<T>
- implements PropertyGetEvent<T> {
- /// Creates a new [LivePropertyGetEvent].
- LivePropertyGetEvent(
- Object object, this.property, T result, dynamic error, int timestamp)
- : super(object, result, error, timestamp);
-
- @override
- final Symbol property;
-
- @override
- Map<String, dynamic> serialize() {
- return <String, dynamic>{
- kManifestTypeKey: kGetType,
- kManifestPropertyKey: getSymbolName(property),
- }..addAll(super.serialize());
- }
-}
-
-/// A [PropertySetEvent] that's in the process of being recorded.
-class LivePropertySetEvent<T> extends LiveInvocationEvent<Null>
- implements PropertySetEvent<T> {
- /// Creates a new [LivePropertySetEvent].
- LivePropertySetEvent(
- Object object, this.property, this.value, dynamic error, int timestamp)
- : super(object, null, error, timestamp);
-
- @override
- final Symbol property;
-
- @override
- final T value;
-
- @override
- Map<String, dynamic> serialize() {
- return <String, dynamic>{
- kManifestTypeKey: kSetType,
- kManifestPropertyKey: getSymbolName(property),
- kManifestValueKey: encode(value),
- }..addAll(super.serialize());
- }
-}
-
-/// A [MethodEvent] that's in the process of being recorded.
-class LiveMethodEvent<T> extends LiveInvocationEvent<T>
- implements MethodEvent<T> {
- /// Creates a new [LiveMethodEvent].
- LiveMethodEvent(
- Object object,
- this.method,
- List<dynamic> positionalArguments,
- Map<Symbol, dynamic> namedArguments,
- T result,
- dynamic error,
- int timestamp,
- ) : positionalArguments = List<dynamic>.unmodifiable(positionalArguments),
- namedArguments = Map<Symbol, dynamic>.unmodifiable(namedArguments),
- super(object, result, error, timestamp);
-
- @override
- final Symbol method;
-
- @override
- final List<dynamic> positionalArguments;
-
- @override
- final Map<Symbol, dynamic> namedArguments;
-
- @override
- Map<String, dynamic> serialize() {
- return <String, dynamic>{
- kManifestTypeKey: kInvokeType,
- kManifestMethodKey: getSymbolName(method),
- kManifestPositionalArgumentsKey: encode(positionalArguments),
- kManifestNamedArgumentsKey: encode(namedArguments),
- }..addAll(super.serialize());
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/mutable_recording.dart b/packages/file/lib/src/backends/record_replay/mutable_recording.dart
deleted file mode 100644
index ec30905..0000000
--- a/packages/file/lib/src/backends/record_replay/mutable_recording.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:file/file.dart';
-
-import 'codecs.dart';
-import 'common.dart';
-import 'events.dart';
-import 'recording.dart';
-
-/// A mutable live recording.
-class MutableRecording implements LiveRecording {
- /// Creates a new `MutableRecording` that will serialize its data to the
- /// specified [destination].
- MutableRecording(this.destination);
-
- final List<LiveInvocationEvent<dynamic>> _events =
- <LiveInvocationEvent<dynamic>>[];
-
- bool _flushing = false;
-
- @override
- final Directory destination;
-
- @override
- List<LiveInvocationEvent<dynamic>> get events =>
- List<LiveInvocationEvent<dynamic>>.unmodifiable(_events);
-
- @override
- Future<void> flush({Duration pendingResultTimeout}) async {
- if (_flushing) {
- throw StateError('Recording is already flushing');
- }
- _flushing = true;
- try {
- Iterable<Future<void>> futures =
- _events.map((LiveInvocationEvent<dynamic> event) => event.done);
- Future<List<void>> results = Future.wait<void>(futures);
- if (pendingResultTimeout != null) {
- results = results.timeout(pendingResultTimeout, onTimeout: () {
- return null;
- });
- }
- await results;
- Directory dir = destination;
- String json = const JsonEncoder.withIndent(' ').convert(encode(_events));
- String filename = dir.fileSystem.path.join(dir.path, kManifestName);
- await dir.fileSystem.file(filename).writeAsString(json, flush: true);
- } finally {
- _flushing = false;
- }
- }
-
- /// Returns a new file for use with this recording.
- ///
- /// The file name will combine the specified [name] with [newUid] to ensure
- /// that its name is unique among all recording files.
- ///
- /// It is up to the caller to create the file - it will not exist in the
- /// file system when it is returned from this method.
- File newFile(String name) {
- String basename = '${newUid()}.$name';
- String dirname = destination.path;
- String path = destination.fileSystem.path.join(dirname, basename);
- return destination.fileSystem.file(path);
- }
-
- /// Adds the specified [event] to this recording.
- void add(LiveInvocationEvent<dynamic> event) => _events.add(event);
-}
diff --git a/packages/file/lib/src/backends/record_replay/proxy.dart b/packages/file/lib/src/backends/record_replay/proxy.dart
deleted file mode 100644
index 06cf974..0000000
--- a/packages/file/lib/src/backends/record_replay/proxy.dart
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2017, 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.
-
-/// An object that uses [noSuchMethod] to dynamically handle invocations
-/// (property getters, property setters, and method invocations).
-abstract class ProxyObject {}
-
-/// A function reference that, when invoked, will forward the invocation back
-/// to a [ProxyObject].
-///
-/// This is used when a caller accesses a method on a [ProxyObject] via the
-/// method's getter. In these cases, the caller will receive a [MethodProxy]
-/// that allows delayed invocation of the method.
-class MethodProxy {
- /// Creates a new [MethodProxy] that, when invoked, will invoke the method
- /// identified by [methodName] on the specified target [object].
- MethodProxy(ProxyObject object, Symbol methodName)
- : _proxyObject = object,
- _methodName = methodName;
-
- /// The object on which the method was retrieved.
- ///
- /// This will be the target object when this method proxy is invoked.
- final ProxyObject _proxyObject;
-
- /// The name of the method in question.
- final Symbol _methodName;
-
- @override
- dynamic noSuchMethod(Invocation invocation) {
- if (invocation.isMethod && invocation.memberName == #call) {
- // The method is being invoked. Capture the arguments, and invoke the
- // method on the proxy object. We have to synthesize an invocation, since
- // our current `invocation` object represents the invocation of `call()`.
- return _proxyObject.noSuchMethod(Invocation.method(
- _methodName,
- invocation.positionalArguments,
- invocation.namedArguments,
- ));
- }
- return super.noSuchMethod(invocation);
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/recording.dart b/packages/file/lib/src/backends/record_replay/recording.dart
deleted file mode 100644
index d5f7901..0000000
--- a/packages/file/lib/src/backends/record_replay/recording.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-
-import 'package:file/file.dart';
-
-import 'events.dart';
-import 'replay_file_system.dart';
-
-/// A recording of a series of invocations on a [FileSystem] and its associated
-/// objects (`File`, `Directory`, `IOSink`, etc).
-///
-/// Recorded invocations include property getters, property setters, and
-/// standard method invocations. A recording exists as an ordered series of
-/// "invocation events".
-abstract class Recording {
- /// The invocation events that have been captured by this recording.
- List<InvocationEvent<dynamic>> get events;
-}
-
-/// An [Recording] in progress that can be serialized to disk for later use
-/// in [ReplayFileSystem].
-///
-/// Live recordings exist only in memory until [flush] is called.
-abstract class LiveRecording extends Recording {
- /// The directory in which recording files will be stored.
- ///
- /// These contents of these files, while human readable, do not constitute an
- /// API or contract. Their makeup and structure is subject to change from
- /// one version of `package:file` to the next.
- Directory get destination;
-
- /// Writes this recording to disk.
- ///
- /// Live recordings will *not* call `flush` on themselves, so it is up to
- /// callers to call this method when they wish to write the recording to
- /// disk.
- ///
- /// If [pendingResultTimeout] is specified, this will wait the specified
- /// duration for any results that are `Future`s or `Stream`s to complete
- /// before serializing the recording to disk. Futures that don't complete
- /// within the specified duration will have their results recorded as `null`,
- /// and streams that don't send a "done" event within the specified duration
- /// will have their results recorded as the list of events the stream has
- /// fired thus far.
- ///
- /// If [pendingResultTimeout] is not specified (or is `null`), this will wait
- /// indefinitely for for any results that are `Future`s or `Stream`s to
- /// complete before serializing the recording to disk.
- ///
- /// Throws a [StateError] if a flush is already in progress.
- ///
- /// Returns a future that completes once the recording has been fully written
- /// to disk.
- Future<void> flush({Duration pendingResultTimeout});
-}
diff --git a/packages/file/lib/src/backends/record_replay/recording_directory.dart b/packages/file/lib/src/backends/record_replay/recording_directory.dart
deleted file mode 100644
index e157327..0000000
--- a/packages/file/lib/src/backends/record_replay/recording_directory.dart
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-
-import 'package:file/file.dart';
-import 'package:file/src/io.dart' as io;
-
-import 'recording_file_system.dart';
-import 'recording_file_system_entity.dart';
-
-/// [Directory] implementation that records all invocation activity to its file
-/// system's recording.
-class RecordingDirectory extends RecordingFileSystemEntity<Directory>
- implements Directory {
- /// Creates a new `RecordingDirectory`.
- RecordingDirectory(RecordingFileSystem fileSystem, io.Directory delegate)
- : super(fileSystem as RecordingFileSystemImpl, delegate as Directory) {
- methods.addAll(<Symbol, Function>{
- #create: _create,
- #createSync: delegate.createSync,
- #createTemp: _createTemp,
- #createTempSync: _createTempSync,
- #list: _list,
- #listSync: _listSync,
- #childDirectory: _childDirectory,
- #childFile: _childFile,
- #childLink: _childLink,
- });
- }
-
- // These four abstract methods, [create], [createSync], [list], and [listSync],
- // are implemented by [noSuchMethod], but their presence here works around
- // https://github.com/dart-lang/sdk/issues/33459, allowing these methods to
- // be called within a Dart 2 runtime.
- // TODO(srawlins): Remove these when the minimum SDK version in
- // `pubspec.yaml` contains a fix for
- // https://github.com/dart-lang/sdk/issues/33459.
-
- @override
- Future<Directory> create({bool recursive = false});
-
- @override
- void createSync({bool recursive = false});
-
- @override
- Stream<FileSystemEntity> list(
- {bool recursive = false, bool followLinks = true});
-
- @override
- List<FileSystemEntity> listSync(
- {bool recursive = false, bool followLinks = true});
-
- @override
- Directory wrap(Directory delegate) =>
- super.wrap(delegate) ?? wrapDirectory(delegate);
-
- Future<Directory> _create({bool recursive = false}) =>
- delegate.create(recursive: recursive).then(wrap);
-
- Future<Directory> _createTemp([String prefix]) =>
- delegate.createTemp(prefix).then(wrap);
-
- Directory _createTempSync([String prefix]) =>
- wrap(delegate.createTempSync(prefix));
-
- Stream<FileSystemEntity> _list(
- {bool recursive = false, bool followLinks = true}) =>
- delegate
- .list(recursive: recursive, followLinks: followLinks)
- .map(_wrapGeneric);
-
- List<FileSystemEntity> _listSync(
- {bool recursive = false, bool followLinks = true}) =>
- delegate
- .listSync(recursive: recursive, followLinks: followLinks)
- .map(_wrapGeneric)
- .toList();
-
- FileSystemEntity _wrapGeneric(io.FileSystemEntity entity) {
- if (entity is io.File) {
- return wrapFile(entity);
- } else if (entity is io.Directory) {
- return wrapDirectory(entity);
- } else if (entity is io.Link) {
- return wrapLink(entity);
- }
- throw FileSystemException('Unsupported type: $entity', entity.path);
- }
-
- Directory _childDirectory(String basename) =>
- wrapDirectory(delegate.childDirectory(basename));
-
- File _childFile(String basename) => wrapFile(delegate.childFile(basename));
-
- Link _childLink(String basename) => wrapLink(delegate.childLink(basename));
-}
diff --git a/packages/file/lib/src/backends/record_replay/recording_file.dart b/packages/file/lib/src/backends/record_replay/recording_file.dart
deleted file mode 100644
index cc9b03e..0000000
--- a/packages/file/lib/src/backends/record_replay/recording_file.dart
+++ /dev/null
@@ -1,268 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'package:meta/meta.dart';
-import 'package:file/file.dart';
-import 'package:file/src/io.dart' as io;
-
-import 'recording_file_system.dart';
-import 'recording_file_system_entity.dart';
-import 'recording_io_sink.dart';
-import 'recording_random_access_file.dart';
-import 'result_reference.dart';
-
-/// Callback responsible for synchronously writing result [data] to the
-/// specified [file].
-///
-/// See also:
-/// - [_BlobReference]
-/// - [_BlobStreamReference]
-typedef _BlobDataSyncWriter<T> = void Function(File file, T data);
-
-/// Callback responsible for asynchronously writing result [data] to the
-/// specified [file].
-///
-/// See also:
-/// - [_BlobFutureReference]
-typedef _BlobDataAsyncWriter<T> = Future<void> Function(File file, T data);
-
-/// [File] implementation that records all invocation activity to its file
-/// system's recording.
-class RecordingFile extends RecordingFileSystemEntity<File> implements File {
- /// Creates a new `RecordingFile`.
- RecordingFile(RecordingFileSystem fileSystem, io.File delegate)
- : super(fileSystem as RecordingFileSystemImpl, delegate as File) {
- methods.addAll(<Symbol, Function>{
- #create: _create,
- #createSync: delegate.createSync,
- #copy: _copy,
- #copySync: _copySync,
- #length: delegate.length,
- #lengthSync: delegate.lengthSync,
- #lastAccessed: delegate.lastAccessed,
- #lastAccessedSync: delegate.lastAccessedSync,
- #setLastAccessed: delegate.setLastAccessed,
- #setLastAccessedSync: delegate.setLastAccessedSync,
- #lastModified: delegate.lastModified,
- #lastModifiedSync: delegate.lastModifiedSync,
- #setLastModified: delegate.setLastModified,
- #setLastModifiedSync: delegate.setLastModifiedSync,
- #open: _open,
- #openSync: _openSync,
- #openRead: _openRead,
- #openWrite: _openWrite,
- #readAsBytes: _readAsBytes,
- #readAsBytesSync: _readAsBytesSync,
- #readAsString: _readAsString,
- #readAsStringSync: _readAsStringSync,
- #readAsLines: _readAsLines,
- #readAsLinesSync: _readAsLinesSync,
- #writeAsBytes: _writeAsBytes,
- #writeAsBytesSync: delegate.writeAsBytesSync,
- #writeAsString: _writeAsString,
- #writeAsStringSync: delegate.writeAsStringSync,
- });
- }
-
- @override
- File wrap(File delegate) => super.wrap(delegate) ?? wrapFile(delegate);
-
- File _newRecordingFile() => recording.newFile(delegate.basename);
-
- RandomAccessFile _wrapRandomAccessFile(RandomAccessFile delegate) =>
- RecordingRandomAccessFile(fileSystem, delegate);
-
- Future<File> _create({bool recursive = false}) =>
- delegate.create(recursive: recursive).then(wrap);
-
- Future<File> _copy(String newPath) => delegate.copy(newPath).then(wrap);
-
- File _copySync(String newPath) => wrap(delegate.copySync(newPath));
-
- Future<RandomAccessFile> _open({FileMode mode = FileMode.read}) =>
- delegate.open(mode: mode).then(_wrapRandomAccessFile);
-
- RandomAccessFile _openSync({FileMode mode = FileMode.read}) =>
- _wrapRandomAccessFile(delegate.openSync(mode: mode));
-
- StreamReference<Uint8List> _openRead([int start, int end]) {
- return _BlobStreamReference<Uint8List>(
- file: _newRecordingFile(),
- stream: delegate.openRead(start, end).cast<Uint8List>(),
- writer: (File file, Uint8List bytes) {
- file.writeAsBytesSync(bytes, mode: FileMode.append, flush: true);
- },
- );
- }
-
- IOSink _openWrite(
- {FileMode mode = FileMode.write, Encoding encoding = utf8}) {
- return RecordingIOSink(
- fileSystem,
- delegate.openWrite(mode: mode, encoding: encoding),
- );
- }
-
- FutureReference<Uint8List> _readAsBytes() {
- return _BlobFutureReference<Uint8List>(
- file: _newRecordingFile(),
- future: delegate.readAsBytes(),
- writer: (File file, Uint8List bytes) async {
- await file.writeAsBytes(bytes, flush: true);
- },
- );
- }
-
- ResultReference<Uint8List> _readAsBytesSync() {
- return _BlobReference<Uint8List>(
- file: _newRecordingFile(),
- value: delegate.readAsBytesSync(),
- writer: (File file, Uint8List bytes) {
- file.writeAsBytesSync(bytes, flush: true);
- },
- );
- }
-
- FutureReference<String> _readAsString({Encoding encoding = utf8}) {
- return _BlobFutureReference<String>(
- file: _newRecordingFile(),
- future: delegate.readAsString(encoding: encoding),
- writer: (File file, String content) async {
- await file.writeAsString(content, flush: true);
- },
- );
- }
-
- ResultReference<String> _readAsStringSync({Encoding encoding = utf8}) {
- return _BlobReference<String>(
- file: _newRecordingFile(),
- value: delegate.readAsStringSync(encoding: encoding),
- writer: (File file, String content) {
- file.writeAsStringSync(content, flush: true);
- },
- );
- }
-
- FutureReference<List<String>> _readAsLines({Encoding encoding = utf8}) {
- return _BlobFutureReference<List<String>>(
- file: _newRecordingFile(),
- future: delegate.readAsLines(encoding: encoding),
- writer: (File file, List<String> lines) async {
- await file.writeAsString(_joinLines(lines), flush: true);
- },
- );
- }
-
- ResultReference<List<String>> _readAsLinesSync({Encoding encoding = utf8}) {
- return _BlobReference<List<String>>(
- file: _newRecordingFile(),
- value: delegate.readAsLinesSync(encoding: encoding),
- writer: (File file, List<String> lines) {
- file.writeAsStringSync(_joinLines(lines), flush: true);
- },
- );
- }
-
- Future<File> _writeAsBytes(
- List<int> bytes, {
- FileMode mode = FileMode.write,
- bool flush = false,
- }) =>
- delegate.writeAsBytes(bytes, mode: mode, flush: flush).then(wrap);
-
- Future<File> _writeAsString(
- String contents, {
- FileMode mode = FileMode.write,
- Encoding encoding = utf8,
- bool flush = false,
- }) =>
- delegate
- .writeAsString(contents, mode: mode, encoding: encoding, flush: flush)
- .then(wrap);
-}
-
-/// A [ResultReference] that serializes its value data to a separate file.
-class _BlobReference<T> extends ResultReference<T> {
- _BlobReference({
- @required File file,
- @required T value,
- @required _BlobDataSyncWriter<T> writer,
- }) : _file = file,
- _value = value,
- _writer = writer;
-
- final File _file;
- final T _value;
- final _BlobDataSyncWriter<T> _writer;
-
- @override
- T get value {
- _writer(_file, _value);
- return _value;
- }
-
- @override
- T get recordedValue => _value;
-
- @override
- String get serializedValue => '!${_file.basename}';
-}
-
-/// A [FutureReference] that serializes its value data to a separate file.
-class _BlobFutureReference<T> extends FutureReference<T> {
- _BlobFutureReference({
- @required File file,
- @required Future<T> future,
- @required _BlobDataAsyncWriter<T> writer,
- }) : _file = file,
- _writer = writer,
- super(future);
-
- final File _file;
- final _BlobDataAsyncWriter<T> _writer;
-
- @override
- Future<T> get value {
- return super.value.then((T value) async {
- await _writer(_file, value);
- return value;
- });
- }
-
- @override
- String get serializedValue => '!${_file.basename}';
-}
-
-/// A [StreamReference] that serializes its value data to a separate file.
-class _BlobStreamReference<T> extends StreamReference<T> {
- _BlobStreamReference({
- @required File file,
- @required Stream<T> stream,
- @required _BlobDataSyncWriter<T> writer,
- }) : _file = file,
- _writer = writer,
- super(stream);
-
- final File _file;
- final _BlobDataSyncWriter<T> _writer;
-
- @override
- void onData(T event) {
- _writer(_file, event);
- }
-
- @override
- String get serializedValue => '!${_file.basename}';
-}
-
-/// Flattens a list of lines into a single, newline-delimited string.
-///
-/// Each element of [lines] is assumed to represent a complete line and will
-/// be end with a newline in the resulting string.
-String _joinLines(List<String> lines) =>
- lines.isEmpty ? '' : (lines.join('\n') + '\n');
diff --git a/packages/file/lib/src/backends/record_replay/recording_file_system.dart b/packages/file/lib/src/backends/record_replay/recording_file_system.dart
deleted file mode 100644
index dd6a768..0000000
--- a/packages/file/lib/src/backends/record_replay/recording_file_system.dart
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'package:file/file.dart';
-import 'package:meta/meta.dart';
-
-import 'common.dart';
-import 'mutable_recording.dart';
-import 'recording.dart';
-import 'recording_directory.dart';
-import 'recording_file.dart';
-import 'recording_link.dart';
-import 'recording_proxy_mixin.dart';
-import 'replay_file_system.dart';
-
-/// File system that records invocations for later playback in tests.
-///
-/// This will record all invocations (methods, property getters, and property
-/// setters) that occur on it, in an opaque format that can later be used in
-/// [ReplayFileSystem]. All activity in the [File], [Directory], [Link],
-/// [IOSink], and [RandomAccessFile] instances returned from this API will also
-/// be recorded.
-///
-/// This class is intended for use in tests, where you would otherwise have to
-/// set up complex mocks or fake file systems. With this class, the process is
-/// as follows:
-///
-/// - You record the file system activity during a real run of your program
-/// by injecting a `RecordingFileSystem` that delegates to your real file
-/// system.
-/// - You serialize that recording to disk as your program finishes.
-/// - You use that recording in tests to create a mock file system that knows
-/// how to respond to the exact invocations your program makes. Any
-/// invocations that aren't in the recording will throw, and you can make
-/// assertions in your tests about which methods were invoked and in what
-/// order.
-///
-/// *Implementation note*: this class uses [noSuchMethod] to dynamically handle
-/// invocations. As a result, method references on objects herein will not pass
-/// `is` checks or checked-mode checks on type. For example:
-///
-/// ```dart
-/// typedef FileStat StatSync(String path);
-/// FileSystem fs = RecordingFileSystem(delegate: delegate, destination: dir);
-///
-/// StatSync method = fs.statSync; // Will fail in checked-mode
-/// fs.statSync is StatSync // Will return false
-/// fs.statSync is Function // Will return false
-///
-/// dynamic method2 = fs.statSync; // OK
-/// FileStat stat = method2('/path'); // OK
-/// ```
-///
-/// See also:
-/// - [ReplayFileSystem]
-abstract class RecordingFileSystem extends FileSystem {
- /// Creates a new `RecordingFileSystem`.
- ///
- /// Invocations will be recorded and forwarded to the specified [delegate]
- /// file system.
- ///
- /// The recording will be serialized to the specified [destination] directory
- /// (only when `flush` is called on this file system's [recording]).
- ///
- /// If [stopwatch] is specified, it will be assumed to have already been
- /// started by the caller, and it will be used to record timestamps on each
- /// recorded invocation. If `stopwatch` is unspecified (or `null`), a new
- /// stopwatch will be created and started immediately to record these
- /// timestamps.
- factory RecordingFileSystem({
- @required FileSystem delegate,
- @required Directory destination,
- Stopwatch stopwatch,
- }) =>
- RecordingFileSystemImpl(delegate, destination, stopwatch);
-
- /// The file system to which invocations will be forwarded upon recording.
- FileSystem get delegate;
-
- /// The recording generated by invocations on this file system.
- ///
- /// The recording provides access to the invocation events that have been
- /// recorded thus far, as well as the ability to flush them to disk.
- LiveRecording get recording;
-
- /// The stopwatch used to record timestamps on invocation events.
- ///
- /// Timestamps will be recorded before the delegate is invoked (not after
- /// the delegate returns).
- Stopwatch get stopwatch;
-}
-
-/// Non-exported implementation class for `RecordingFileSystem`.
-class RecordingFileSystemImpl extends FileSystem
- with RecordingProxyMixin
- implements RecordingFileSystem {
- /// Creates a new `RecordingFileSystemImpl`.
- RecordingFileSystemImpl(
- this.delegate, Directory destination, Stopwatch recordingStopwatch)
- : recording = MutableRecording(destination),
- stopwatch = recordingStopwatch ?? Stopwatch() {
- if (recordingStopwatch == null) {
- // We instantiated our own stopwatch, so start it ourselves.
- stopwatch.start();
- }
-
- methods.addAll(<Symbol, Function>{
- #directory: _directory,
- #file: _file,
- #link: _link,
- #stat: delegate.stat,
- #statSync: delegate.statSync,
- #identical: delegate.identical,
- #identicalSync: delegate.identicalSync,
- #type: delegate.type,
- #typeSync: delegate.typeSync,
- });
-
- properties.addAll(<Symbol, Function>{
- #path: () => delegate.path,
- #systemTempDirectory: _getSystemTempDirectory,
- #currentDirectory: _getCurrentDirectory,
- const Symbol('currentDirectory='): _setCurrentDirectory,
- #isWatchSupported: () => delegate.isWatchSupported,
- });
- }
-
- @override
- String get identifier => kFileSystemEncodedValue;
-
- /// The file system to which invocations will be forwarded upon recording.
- @override
- final FileSystem delegate;
-
- /// The recording generated by invocations on this file system.
- @override
- final MutableRecording recording;
-
- /// The stopwatch used to record timestamps on invocation events.
- @override
- final Stopwatch stopwatch;
-
- Directory _directory(dynamic path) =>
- RecordingDirectory(this, delegate.directory(path));
-
- File _file(dynamic path) => RecordingFile(this, delegate.file(path));
-
- Link _link(dynamic path) => RecordingLink(this, delegate.link(path));
-
- Directory _getSystemTempDirectory() =>
- RecordingDirectory(this, delegate.systemTempDirectory);
-
- Directory _getCurrentDirectory() =>
- RecordingDirectory(this, delegate.currentDirectory);
-
- void _setCurrentDirectory(dynamic value) {
- delegate.currentDirectory = value;
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/recording_file_system_entity.dart b/packages/file/lib/src/backends/record_replay/recording_file_system_entity.dart
deleted file mode 100644
index 236994e..0000000
--- a/packages/file/lib/src/backends/record_replay/recording_file_system_entity.dart
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-
-import 'package:file/file.dart';
-import 'package:file/src/io.dart' as io;
-import 'package:meta/meta.dart';
-
-import 'common.dart';
-import 'mutable_recording.dart';
-import 'recording_directory.dart';
-import 'recording_file.dart';
-import 'recording_file_system.dart';
-import 'recording_link.dart';
-import 'recording_proxy_mixin.dart';
-
-/// [FileSystemEntity] implementation that records all invocation activity to
-/// its file system's recording.
-abstract class RecordingFileSystemEntity<T extends FileSystemEntity>
- extends Object with RecordingProxyMixin implements FileSystemEntity {
- /// Creates a new `RecordingFileSystemEntity`.
- RecordingFileSystemEntity(this.fileSystem, this.delegate) {
- methods.addAll(<Symbol, Function>{
- #exists: delegate.exists,
- #existsSync: delegate.existsSync,
- #rename: _rename,
- #renameSync: _renameSync,
- #resolveSymbolicLinks: delegate.resolveSymbolicLinks,
- #resolveSymbolicLinksSync: delegate.resolveSymbolicLinksSync,
- #stat: delegate.stat,
- #statSync: delegate.statSync,
- #delete: _delete,
- #deleteSync: delegate.deleteSync,
- #watch: delegate.watch,
- });
-
- properties.addAll(<Symbol, Function>{
- #path: () => delegate.path,
- #uri: () => delegate.uri,
- #isAbsolute: () => delegate.isAbsolute,
- #absolute: _getAbsolute,
- #parent: _getParent,
- #basename: () => delegate.basename,
- #dirname: () => delegate.dirname,
- });
- }
-
- /// A unique entity id.
- final int uid = newUid();
-
- @override
- String get identifier => '$runtimeType@$uid';
-
- @override
- final RecordingFileSystemImpl fileSystem;
-
- @override
- MutableRecording get recording => fileSystem.recording;
-
- @override
- Stopwatch get stopwatch => fileSystem.stopwatch;
-
- /// The entity to which this entity delegates its functionality while
- /// recording.
- @protected
- final T delegate;
-
- /// Returns an entity with the same file system and same type as this
- /// entity but backed by the specified delegate.
- ///
- /// This base implementation checks to see if the specified delegate is the
- /// same as this entity's delegate, and if so, it returns this entity.
- /// Otherwise it returns `null`. Subclasses should override this method to
- /// instantiate the correct wrapped type only if this super implementation
- /// returns `null`.
- @protected
- @mustCallSuper
- T wrap(T delegate) => delegate == this.delegate ? this as T : null;
-
- /// Returns a directory with the same file system as this entity but backed
- /// by the specified delegate directory.
- @protected
- Directory wrapDirectory(io.Directory delegate) =>
- RecordingDirectory(fileSystem, delegate);
-
- /// Returns a file with the same file system as this entity but backed
- /// by the specified delegate file.
- @protected
- File wrapFile(io.File delegate) => RecordingFile(fileSystem, delegate);
-
- /// Returns a link with the same file system as this entity but backed
- /// by the specified delegate link.
- @protected
- Link wrapLink(io.Link delegate) => RecordingLink(fileSystem, delegate);
-
- Future<T> _rename(String newPath) => delegate
- .rename(newPath)
- .then((io.FileSystemEntity entity) => wrap(entity as T));
-
- T _renameSync(String newPath) => wrap(delegate.renameSync(newPath) as T);
-
- Future<T> _delete({bool recursive = false}) => delegate
- .delete(recursive: recursive)
- .then((io.FileSystemEntity entity) => wrap(entity as T));
-
- T _getAbsolute() => wrap(delegate.absolute as T);
-
- Directory _getParent() => wrapDirectory(delegate.parent);
-}
diff --git a/packages/file/lib/src/backends/record_replay/recording_io_sink.dart b/packages/file/lib/src/backends/record_replay/recording_io_sink.dart
deleted file mode 100644
index 1925018..0000000
--- a/packages/file/lib/src/backends/record_replay/recording_io_sink.dart
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:convert';
-
-import 'package:file/file.dart';
-
-import 'common.dart';
-import 'mutable_recording.dart';
-import 'recording_file_system.dart';
-import 'recording_proxy_mixin.dart';
-
-/// [IOSink] implementation that records all invocation activity to its file
-/// system's recording.
-class RecordingIOSink extends Object
- with RecordingProxyMixin
- implements IOSink {
- /// Creates a new `RecordingIOSink`.
- RecordingIOSink(this.fileSystem, this.delegate) {
- methods.addAll(<Symbol, Function>{
- #add: delegate.add,
- #write: delegate.write,
- #writeAll: delegate.writeAll,
- #writeln: delegate.writeln,
- #writeCharCode: delegate.writeCharCode,
- #addError: delegate.addError,
- #addStream: delegate.addStream,
- #flush: delegate.flush,
- #close: delegate.close,
- });
-
- properties.addAll(<Symbol, Function>{
- #encoding: () => delegate.encoding,
- const Symbol('encoding='): _setEncoding,
- #done: () => delegate.done,
- });
- }
-
- /// The file system that owns this sink.
- final RecordingFileSystem fileSystem;
-
- /// The sink to which this sink delegates its functionality while recording.
- final IOSink delegate;
-
- /// A unique entity id.
- final int uid = newUid();
-
- @override
- String get identifier => '$runtimeType@$uid';
-
- @override
- MutableRecording get recording => fileSystem.recording as MutableRecording;
-
- @override
- Stopwatch get stopwatch => fileSystem.stopwatch;
-
- void _setEncoding(Encoding value) {
- delegate.encoding = value;
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/recording_link.dart b/packages/file/lib/src/backends/record_replay/recording_link.dart
deleted file mode 100644
index 01954b9..0000000
--- a/packages/file/lib/src/backends/record_replay/recording_link.dart
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-
-import 'package:file/file.dart';
-import 'package:file/src/io.dart' as io;
-
-import 'recording_file_system.dart';
-import 'recording_file_system_entity.dart';
-
-/// [Link] implementation that records all invocation activity to its file
-/// system's recording.
-class RecordingLink extends RecordingFileSystemEntity<Link> implements Link {
- /// Creates a new `RecordingLink`.
- RecordingLink(RecordingFileSystem fileSystem, io.Link delegate)
- : super(fileSystem as RecordingFileSystemImpl, delegate as Link) {
- methods.addAll(<Symbol, Function>{
- #create: _create,
- #createSync: delegate.createSync,
- #update: _update,
- #updateSync: delegate.updateSync,
- #target: delegate.target,
- #targetSync: delegate.targetSync,
- });
- }
-
- @override
- Link wrap(Link delegate) => super.wrap(delegate) ?? wrapLink(delegate);
-
- Future<Link> _create(String target, {bool recursive = false}) =>
- delegate.create(target, recursive: recursive).then(wrap);
-
- Future<Link> _update(String target) => delegate.update(target).then(wrap);
-}
diff --git a/packages/file/lib/src/backends/record_replay/recording_proxy_mixin.dart b/packages/file/lib/src/backends/record_replay/recording_proxy_mixin.dart
deleted file mode 100644
index 08f92da..0000000
--- a/packages/file/lib/src/backends/record_replay/recording_proxy_mixin.dart
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'package:file/file.dart';
-import 'package:file/src/backends/memory/node.dart';
-
-import 'package:meta/meta.dart';
-
-import 'common.dart';
-import 'events.dart';
-import 'mutable_recording.dart';
-import 'proxy.dart';
-import 'result_reference.dart';
-
-/// Mixin that enables recording of property accesses, property mutations, and
-/// method invocations.
-///
-/// This class uses `noSuchMethod` to record a well-defined set of invocations
-/// (including property gets and sets) on an object before passing the
-/// invocation on to a delegate. Subclasses wire this up by doing the following:
-///
-/// - Populate the list of method invocations to record in the [methods] map.
-/// - Populate the list of property invocations to record in the [properties]
-/// map. The symbol name for getters should be the property name, and the
-/// symbol name for setters should be the property name immediately
-/// followed by an equals sign (e.g. `propertyName=`).
-/// - Do not implement a concrete getter, setter, or method that you wish to
-/// record, as doing so will circumvent the machinery that this mixin uses
-/// (`noSuchMethod`) to record invocations.
-///
-/// **Example use**:
-///
-/// abstract class Foo {
-/// void sampleMethod();
-///
-/// int sampleProperty;
-/// }
-///
-/// class RecordingFoo extends RecordingProxyMixin implements Foo {
-/// final Foo delegate;
-///
-/// RecordingFoo(this.delegate) {
-/// methods.addAll(<Symbol, Function>{
-/// #sampleMethod: delegate.sampleMethod,
-/// });
-///
-/// properties.addAll(<Symbol, Function>{
-/// #sampleProperty: () => delegate.sampleProperty,
-/// const Symbol('sampleProperty='): (int value) {
-/// delegate.sampleProperty = value;
-/// },
-/// });
-/// }
-/// }
-///
-/// **Behavioral notes**:
-///
-/// Methods that return [Future]s will not be recorded until the future
-/// completes.
-///
-/// Methods that return [Stream]s will be recorded immediately, but their
-/// return values will be recorded as a [List] that will grow as the stream
-/// produces data.
-mixin RecordingProxyMixin on Object implements ProxyObject, ReplayAware {
- /// Maps method names to delegate functions.
- ///
- /// Invocations of methods listed in this map will be recorded after
- /// invoking the underlying delegate function.
- @protected
- final Map<Symbol, Function> methods = <Symbol, Function>{};
-
- /// Maps property getter and setter names to delegate functions.
- ///
- /// Access and mutation of properties listed in this map will be recorded
- /// after invoking the underlying delegate function.
- ///
- /// The keys for property getters are the simple property names, whereas the
- /// keys for property setters are the property names followed by an equals
- /// sign (e.g. `propertyName=`).
- @protected
- final Map<Symbol, Function> properties = <Symbol, Function>{};
-
- /// The object to which invocation events will be recorded.
- @protected
- MutableRecording get recording;
-
- /// The stopwatch used to record invocation timestamps.
- @protected
- Stopwatch get stopwatch;
-
- /// Handles invocations for which there is no concrete implementation
- /// function.
- ///
- /// For invocations that have matching entries in [methods] (for method
- /// invocations) or [properties] (for property access and mutation), this
- /// will record the invocation in [recording] after invoking the underlying
- /// delegate method. All other invocations will throw a [NoSuchMethodError].
- @override
- dynamic noSuchMethod(Invocation invocation) {
- Symbol name = invocation.memberName;
- List<dynamic> args = invocation.positionalArguments;
- Map<Symbol, dynamic> namedArgs = invocation.namedArguments;
- Function method = invocation.isAccessor ? properties[name] : methods[name];
- int time = stopwatch.elapsedMilliseconds;
-
- if (method == null) {
- // No delegate function generally means that there truly is no such
- // method on this object. The exception is when the invocation represents
- // a getter on a method, in which case we return a method proxy that,
- // when invoked, will perform the desired recording.
- return invocation.isGetter && methods[name] != null
- ? MethodProxy(this, name)
- : super.noSuchMethod(invocation);
- }
-
- InvocationEvent<dynamic> createEvent({dynamic result, dynamic error}) {
- if (invocation.isGetter) {
- return LivePropertyGetEvent<dynamic>(this, name, result, error, time);
- } else if (invocation.isSetter) {
- return LivePropertySetEvent<dynamic>(this, name, args[0], error, time);
- } else {
- return LiveMethodEvent<dynamic>(
- this, name, args, namedArgs, result, error, time);
- }
- }
-
- // Invoke the configured delegate method, recording an error if one occurs.
- dynamic value;
- try {
- value = Function.apply(method, args, namedArgs);
- } catch (error) {
- recording.add(createEvent(error: error) as LiveInvocationEvent<dynamic>);
- rethrow;
- }
-
- // Wrap Future and Stream results so that we record their values as they
- // become available.
- // We have to instantiate the correct type of StreamReference or
- // FutureReference, so that types are not lost when we unwrap the references
- // afterward.
- if (value is Stream<FileSystemEntity>) {
- value =
- StreamReference<FileSystemEntity>(value as Stream<FileSystemEntity>);
- } else if (value is Stream<String>) {
- value = StreamReference<String>(value as Stream<String>);
- } else if (value is Stream) {
- throw UnimplementedError(
- 'Cannot record method with return type ${value.runtimeType}');
- } else if (value is Future<bool>) {
- value = FutureReference<bool>(value as Future<bool>);
- } else if (value is Future<Directory>) {
- value = FutureReference<Directory>(value as Future<Directory>);
- } else if (value is Future<File>) {
- value = FutureReference<File>(value as Future<File>);
- } else if (value is Future<FileNode>) {
- value = FutureReference<FileNode>(value as Future<FileNode>);
- } else if (value is Future<FileStat>) {
- value = FutureReference<FileStat>(value as Future<FileStat>);
- } else if (value is Future<Link>) {
- value = FutureReference<Link>(value as Future<Link>);
- } else if (value is Future<FileSystemEntity>) {
- value =
- FutureReference<FileSystemEntity>(value as Future<FileSystemEntity>);
- } else if (value is Future<FileSystemEntityType>) {
- value = FutureReference<FileSystemEntityType>(
- value as Future<FileSystemEntityType>);
- } else if (value is Future<String>) {
- value = FutureReference<String>(value as Future<String>);
- } else if (value is Future<RandomAccessFile>) {
- value =
- FutureReference<RandomAccessFile>(value as Future<RandomAccessFile>);
- } else if (value is Future<void>) {
- value = FutureReference<void>(value as Future<void>);
- }
-
- // Record the invocation event associated with this invocation.
- recording.add(createEvent(result: value) as LiveInvocationEvent<dynamic>);
-
- // Unwrap any result references before returning to the caller.
- dynamic result = value;
- while (result is ResultReference) {
- result = result.value;
- }
- return result;
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/recording_random_access_file.dart b/packages/file/lib/src/backends/record_replay/recording_random_access_file.dart
deleted file mode 100644
index f5ba461..0000000
--- a/packages/file/lib/src/backends/record_replay/recording_random_access_file.dart
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:file/file.dart';
-
-import 'common.dart';
-import 'mutable_recording.dart';
-import 'recording_file_system.dart';
-import 'recording_proxy_mixin.dart';
-
-/// [RandomAccessFile] implementation that records all invocation activity to
-/// its file system's recording.
-class RecordingRandomAccessFile extends Object
- with RecordingProxyMixin
- implements RandomAccessFile {
- /// Creates a new `RecordingRandomAccessFile`.
- RecordingRandomAccessFile(this.fileSystem, this.delegate) {
- methods.addAll(<Symbol, Function>{
- #close: _close,
- #closeSync: delegate.closeSync,
- #readByte: delegate.readByte,
- #readByteSync: delegate.readByteSync,
- #read: delegate.read,
- #readSync: delegate.readSync,
- #readInto: delegate.readInto,
- #readIntoSync: delegate.readIntoSync,
- #writeByte: _writeByte,
- #writeByteSync: delegate.writeByteSync,
- #writeFrom: _writeFrom,
- #writeFromSync: delegate.writeFromSync,
- #writeString: _writeString,
- #writeStringSync: delegate.writeStringSync,
- #position: delegate.position,
- #positionSync: delegate.positionSync,
- #setPosition: _setPosition,
- #setPositionSync: delegate.setPositionSync,
- #truncate: _truncate,
- #truncateSync: delegate.truncateSync,
- #length: delegate.length,
- #lengthSync: delegate.lengthSync,
- #flush: _flush,
- #flushSync: delegate.flushSync,
- #lock: _lock,
- #lockSync: delegate.lockSync,
- #unlock: _unlock,
- #unlockSync: delegate.unlockSync,
- });
-
- properties.addAll(<Symbol, Function>{
- #path: () => delegate.path,
- });
- }
-
- /// The file system that owns this random access file.
- final RecordingFileSystem fileSystem;
-
- /// The random access file to which this random access file delegates its
- /// functionality while recording.
- final RandomAccessFile delegate;
-
- /// A unique entity id.
- final int uid = newUid();
-
- @override
- String get identifier => '$runtimeType@$uid';
-
- @override
- MutableRecording get recording => fileSystem.recording as MutableRecording;
-
- @override
- Stopwatch get stopwatch => fileSystem.stopwatch;
-
- RandomAccessFile _wrap(RandomAccessFile raw) =>
- raw == delegate ? this : RecordingRandomAccessFile(fileSystem, raw);
-
- Future<void> _close() => delegate.close();
-
- Future<RandomAccessFile> _writeByte(int value) =>
- delegate.writeByte(value).then(_wrap);
-
- Future<RandomAccessFile> _writeFrom(List<int> buffer,
- [int start = 0, int end]) =>
- delegate.writeFrom(buffer, start, end).then(_wrap);
-
- Future<RandomAccessFile> _writeString(String string,
- {Encoding encoding = utf8}) =>
- delegate.writeString(string, encoding: encoding).then(_wrap);
-
- Future<RandomAccessFile> _setPosition(int position) =>
- delegate.setPosition(position).then(_wrap);
-
- Future<RandomAccessFile> _truncate(int length) =>
- delegate.truncate(length).then(_wrap);
-
- Future<RandomAccessFile> _flush() => delegate.flush().then(_wrap);
-
- Future<RandomAccessFile> _lock(
- [FileLock mode = FileLock.exclusive, int start = 0, int end = -1]) =>
- delegate.lock(mode, start, end).then(_wrap);
-
- Future<RandomAccessFile> _unlock([int start = 0, int end = -1]) =>
- delegate.unlock(start, end).then(_wrap);
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_directory.dart b/packages/file/lib/src/backends/record_replay/replay_directory.dart
deleted file mode 100644
index f0b1add..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_directory.dart
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:file/file.dart';
-
-import 'codecs.dart';
-import 'replay_file_system.dart';
-import 'replay_file_system_entity.dart';
-
-/// [Directory] implementation that replays all invocation activity from a
-/// prior recording.
-class ReplayDirectory extends ReplayFileSystemEntity implements Directory {
- /// Creates a new `ReplayDirectory`.
- ReplayDirectory(ReplayFileSystemImpl fileSystem, String identifier)
- : super(fileSystem, identifier) {
- Converter<String, Directory> reviveDirectory = ReviveDirectory(fileSystem);
- Converter<String, Future<Directory>> reviveFutureDirectory =
- reviveDirectory.fuse(const ToFuture<Directory>());
- Converter<String, FileSystemEntity> reviveEntity =
- ReviveFileSystemEntity(fileSystem);
- Converter<List<dynamic>, List<String>> dynamicToString =
- const CastList<dynamic, String>();
- Converter<List<dynamic>, List<FileSystemEntity>> reviveEntities =
- dynamicToString.fuse<List<FileSystemEntity>>(
- ConvertElements<String, FileSystemEntity>(reviveEntity));
- Converter<List<dynamic>, Stream<FileSystemEntity>> reviveEntitiesAsStream =
- reviveEntities
- .fuse<Stream<FileSystemEntity>>(const ToStream<FileSystemEntity>());
-
- methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #rename: reviveFutureDirectory,
- #renameSync: reviveDirectory,
- #delete: reviveFutureDirectory,
- #create: reviveFutureDirectory,
- #createSync: const Passthrough<Null>(),
- #createTemp: reviveFutureDirectory,
- #createTempSync: reviveDirectory,
- #list: reviveEntitiesAsStream,
- #listSync: reviveEntities,
- #childDirectory: reviveDirectory,
- #childFile: ReviveFile(fileSystem),
- #childLink: ReviveLink(fileSystem),
- });
-
- properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #absolute: reviveDirectory,
- });
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_file.dart b/packages/file/lib/src/backends/record_replay/replay_file.dart
deleted file mode 100644
index 8eaa790..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_file.dart
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'package:file/file.dart';
-
-import 'codecs.dart';
-import 'replay_file_system.dart';
-import 'replay_file_system_entity.dart';
-
-/// [File] implementation that replays all invocation activity from a prior
-/// recording.
-class ReplayFile extends ReplayFileSystemEntity implements File {
- /// Creates a new `ReplayFile`.
- ReplayFile(ReplayFileSystemImpl fileSystem, String identifier)
- : super(fileSystem, identifier) {
- Converter<String, File> reviveFile = ReviveFile(fileSystem);
- Converter<String, Future<File>> reviveFileAsFuture =
- reviveFile.fuse(const ToFuture<File>());
- Converter<String, Uint8List> blobToBytes = BlobToBytes(fileSystem);
- Converter<String, Future<Uint8List>> blobToBytesFuture =
- blobToBytes.fuse(const ToFuture<Uint8List>());
- Converter<String, String> blobToString =
- blobToBytes.cast<String, List<int>>().fuse(utf8.decoder);
- Converter<String, Future<String>> blobToStringFuture =
- blobToString.fuse(const ToFuture<String>());
- Converter<String, RandomAccessFile> reviveRandomAccessFile =
- ReviveRandomAccessFile(fileSystem);
- Converter<String, Future<RandomAccessFile>> reviveRandomAccessFileFuture =
- reviveRandomAccessFile.fuse(const ToFuture<RandomAccessFile>());
- Converter<String, List<String>> lineSplitter =
- const LineSplitterConverter();
- Converter<String, List<String>> blobToLines =
- blobToString.fuse(lineSplitter);
- Converter<String, Future<List<String>>> blobToLinesFuture =
- blobToLines.fuse(const ToFuture<List<String>>());
- Converter<String, Stream<Uint8List>> blobToByteStream = blobToBytes
- .fuse(const Listify<Uint8List>())
- .fuse(const ToStream<Uint8List>());
- Converter<int, Future<DateTime>> reviveDateTime =
- DateTimeCodec.deserialize.fuse(const ToFuture<DateTime>());
-
- methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #rename: reviveFileAsFuture,
- #renameSync: reviveFile,
- #delete: reviveFileAsFuture,
- #create: reviveFileAsFuture,
- #createSync: const Passthrough<Null>(),
- #copy: reviveFileAsFuture,
- #copySync: reviveFile,
- #length: const ToFuture<int>(),
- #lengthSync: const Passthrough<int>(),
- #lastAccessed: reviveDateTime,
- #lastAccessedSync: DateTimeCodec.deserialize,
- #setLastAccessed: const ToFuture<dynamic>(),
- #setLastAccessedSync: const Passthrough<Null>(),
- #lastModified: reviveDateTime,
- #lastModifiedSync: DateTimeCodec.deserialize,
- #setLastModified: const ToFuture<dynamic>(),
- #setLastModifiedSync: const Passthrough<Null>(),
- #open: reviveRandomAccessFileFuture,
- #openSync: reviveRandomAccessFile,
- #openRead: blobToByteStream,
- #openWrite: ReviveIOSink(fileSystem),
- #readAsBytes: blobToBytesFuture,
- #readAsBytesSync: blobToBytes,
- #readAsString: blobToStringFuture,
- #readAsStringSync: blobToString,
- #readAsLines: blobToLinesFuture,
- #readAsLinesSync: blobToLines,
- #writeAsBytes: reviveFileAsFuture,
- #writeAsBytesSync: const Passthrough<Null>(),
- #writeAsString: reviveFileAsFuture,
- #writeAsStringSync: const Passthrough<Null>(),
- });
-
- properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #absolute: reviveFile,
- });
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_file_stat.dart b/packages/file/lib/src/backends/record_replay/replay_file_stat.dart
deleted file mode 100644
index 497d403..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_file_stat.dart
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'package:file/file.dart';
-
-import 'codecs.dart';
-
-/// [FileStat] implementation that derives its properties from a recorded
-/// invocation event.
-class ReplayFileStat implements FileStat {
- /// Creates a new `ReplayFileStat` that will derive its properties from the
- /// specified [data].
- ReplayFileStat(Map<String, dynamic> data) : _data = data;
-
- final Map<String, dynamic> _data;
-
- @override
- DateTime get changed =>
- DateTimeCodec.deserialize.convert(_data['changed'] as int);
-
- @override
- DateTime get modified =>
- DateTimeCodec.deserialize.convert(_data['modified'] as int);
-
- @override
- DateTime get accessed =>
- DateTimeCodec.deserialize.convert(_data['accessed'] as int);
-
- @override
- FileSystemEntityType get type =>
- EntityTypeCodec.deserialize.convert(_data['type'] as String);
-
- @override
- int get mode => _data['mode'] as int;
-
- @override
- int get size => _data['size'] as int;
-
- @override
- String modeString() => _data['modeString'] as String;
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_file_system.dart b/packages/file/lib/src/backends/record_replay/replay_file_system.dart
deleted file mode 100644
index 35b12c4..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_file_system.dart
+++ /dev/null
@@ -1,127 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:file/file.dart';
-import 'package:meta/meta.dart';
-
-import 'codecs.dart';
-import 'common.dart';
-import 'errors.dart';
-import 'recording_file_system.dart';
-import 'replay_proxy_mixin.dart';
-
-/// A file system that replays invocations from a prior recording for use
-/// in tests.
-///
-/// This will replay all invocations (methods, property getters, and property
-/// setters) that occur on it, based on an opaque recording that was generated
-/// in [RecordingFileSystem]. All activity in the [File], [Directory], [Link],
-/// [IOSink], and [RandomAccessFile] instances returned from this API will also
-/// be replayed from the same recording.
-///
-/// Once an invocation has been replayed once, it is marked as such and will
-/// not be eligible for further replay. If an eligible invocation cannot be
-/// found that matches an incoming invocation, a [NoMatchingInvocationError]
-/// will be thrown.
-///
-/// This class is intended for use in tests, where you would otherwise have to
-/// set up complex mocks or fake file systems. With this class, the process is
-/// as follows:
-///
-/// - You record the file system activity during a real run of your program
-/// by injecting a `RecordingFileSystem` that delegates to your real file
-/// system.
-/// - You serialize that recording to disk as your program finishes.
-/// - You use that recording in tests to create a mock file system that knows
-/// how to respond to the exact invocations your program makes. Any
-/// invocations that aren't in the recording will throw, and you can make
-/// assertions in your tests about which methods were invoked and in what
-/// order.
-///
-/// *Implementation note*: this class uses [noSuchMethod] to dynamically handle
-/// invocations. As a result, method references on objects herein will not pass
-/// `is` checks or checked-mode checks on type. For example:
-///
-/// ```dart
-/// typedef FileStat StatSync(String path);
-/// FileSystem fs = ReplayFileSystem(directory);
-///
-/// StatSync method = fs.statSync; // Will fail in checked-mode
-/// fs.statSync is StatSync // Will return false
-/// fs.statSync is Function // Will return false
-///
-/// dynamic method2 = fs.statSync; // OK
-/// FileStat stat = method2('/path'); // OK
-/// ```
-///
-/// See also:
-/// - [RecordingFileSystem]
-abstract class ReplayFileSystem extends FileSystem {
- /// Creates a new `ReplayFileSystem`.
- ///
- /// Recording data will be loaded from the specified [recording] location.
- /// This location must have been created by [RecordingFileSystem], or an
- /// [ArgumentError] will be thrown.
- factory ReplayFileSystem({
- @required Directory recording,
- }) {
- String dirname = recording.path;
- String path = recording.fileSystem.path.join(dirname, kManifestName);
- File manifestFile = recording.fileSystem.file(path);
- if (!manifestFile.existsSync()) {
- throw ArgumentError('Not a valid recording directory: $dirname');
- }
- List<Map<String, dynamic>> manifest = (const JsonDecoder()
- .convert(manifestFile.readAsStringSync()) as List<dynamic>)
- .cast<Map<String, dynamic>>();
- return ReplayFileSystemImpl(recording, manifest);
- }
-}
-
-/// Non-exported implementation class for `ReplayFileSystem`.
-class ReplayFileSystemImpl extends FileSystem
- with ReplayProxyMixin
- implements ReplayFileSystem, ReplayAware {
- /// Creates a new `ReplayFileSystemImpl`.
- ReplayFileSystemImpl(this.recording, this.manifest) {
- Converter<String, Directory> reviveDirectory = ReviveDirectory(this);
- Converter<String, Future<FileSystemEntityType>> reviveEntityFuture =
- EntityTypeCodec.deserialize
- .fuse(const ToFuture<FileSystemEntityType>());
- Converter<Map<String, Object>, Future<FileStat>> reviveFileStatFuture =
- FileStatCodec.deserialize.fuse(const ToFuture<FileStat>());
-
- methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #directory: reviveDirectory,
- #file: ReviveFile(this),
- #link: ReviveLink(this),
- #stat: reviveFileStatFuture,
- #statSync: FileStatCodec.deserialize,
- #identical: const ToFuture<bool>(),
- #identicalSync: const Passthrough<bool>(),
- #type: reviveEntityFuture,
- #typeSync: EntityTypeCodec.deserialize,
- });
-
- properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #path: PathContextCodec.deserialize,
- #systemTempDirectory: reviveDirectory,
- #currentDirectory: reviveDirectory,
- const Symbol('currentDirectory='): const Passthrough<Null>(),
- #isWatchSupported: const Passthrough<bool>(),
- });
- }
-
- /// The location of the recording that's driving this file system
- final Directory recording;
-
- @override
- String get identifier => kFileSystemEncodedValue;
-
- @override
- final List<Map<String, dynamic>> manifest;
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_file_system_entity.dart b/packages/file/lib/src/backends/record_replay/replay_file_system_entity.dart
deleted file mode 100644
index 1f32f8e..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_file_system_entity.dart
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:file/file.dart';
-
-import 'codecs.dart';
-import 'replay_file_system.dart';
-import 'replay_proxy_mixin.dart';
-
-/// [FileSystemEntity] implementation that replays all invocation activity
-/// from a prior recording.
-abstract class ReplayFileSystemEntity extends Object
- with ReplayProxyMixin
- implements FileSystemEntity {
- /// Creates a new `ReplayFileSystemEntity`.
- ReplayFileSystemEntity(this.fileSystem, this.identifier) {
- Converter<List<Map<String, Object>>, List<FileSystemEvent>> toEvents =
- const ConvertElements<Map<String, Object>, FileSystemEvent>(
- FileSystemEventCodec.deserialize);
- Converter<List<Map<String, Object>>, Stream<FileSystemEvent>>
- toEventStream = toEvents.fuse(const ToStream<FileSystemEvent>());
- Converter<Map<String, Object>, Future<FileStat>> reviveFileStatFuture =
- FileStatCodec.deserialize.fuse(const ToFuture<FileStat>());
-
- methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #exists: const ToFuture<bool>(),
- #existsSync: const Passthrough<bool>(),
- #resolveSymbolicLinks: const ToFuture<String>(),
- #resolveSymbolicLinksSync: const Passthrough<String>(),
- #stat: reviveFileStatFuture,
- #statSync: FileStatCodec.deserialize,
- #deleteSync: const Passthrough<Null>(),
- #watch: toEventStream,
- });
-
- properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #path: const Passthrough<String>(),
- #uri: UriCodec.deserialize,
- #isAbsolute: const Passthrough<bool>(),
- #parent: ReviveDirectory(fileSystem),
- #basename: const Passthrough<String>(),
- #dirname: const Passthrough<String>(),
- });
- }
-
- @override
- final ReplayFileSystemImpl fileSystem;
-
- @override
- final String identifier;
-
- @override
- List<Map<String, dynamic>> get manifest => fileSystem.manifest;
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_io_sink.dart b/packages/file/lib/src/backends/record_replay/replay_io_sink.dart
deleted file mode 100644
index 4dbbd4d..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_io_sink.dart
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:file/file.dart';
-
-import 'codecs.dart';
-import 'replay_file_system.dart';
-import 'replay_proxy_mixin.dart';
-
-/// [IOSink] implementation that replays all invocation activity from a prior
-/// recording.
-class ReplayIOSink extends Object with ReplayProxyMixin implements IOSink {
- /// Creates a new [ReplayIOSink].
- ReplayIOSink(this._fileSystem, this.identifier) {
- methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #add: const Passthrough<Null>(),
- #write: const Passthrough<Null>(),
- #writeAll: const Passthrough<Null>(),
- #writeln: const Passthrough<Null>(),
- #writeCharCode: const Passthrough<Null>(),
- #addError: const Passthrough<Null>(),
- #addStream: const ToFuture<dynamic>(),
- #flush: const ToFuture<dynamic>(),
- #close: const ToFuture<dynamic>(),
- });
-
- properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #encoding: EncodingCodec.deserialize,
- const Symbol('encoding='): const Passthrough<Null>(),
- #done: const ToFuture<dynamic>(),
- });
- }
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- final String identifier;
-
- @override
- List<Map<String, dynamic>> get manifest => _fileSystem.manifest;
-
- @override
- dynamic onResult(Invocation invocation, dynamic result) {
- if (invocation.memberName == #addStream) {
- Stream<List<int>> stream =
- invocation.positionalArguments.first as Stream<List<int>>;
- Future<dynamic> future = result as Future<dynamic>;
- return future.then<void>(stream.drain);
- }
- return result;
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_link.dart b/packages/file/lib/src/backends/record_replay/replay_link.dart
deleted file mode 100644
index 74deb53..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_link.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:file/file.dart';
-
-import 'codecs.dart';
-import 'replay_file_system.dart';
-import 'replay_file_system_entity.dart';
-
-/// [Link] implementation that replays all invocation activity from a prior
-/// recording.
-class ReplayLink extends ReplayFileSystemEntity implements Link {
- /// Creates a new `ReplayLink`.
- ReplayLink(ReplayFileSystemImpl fileSystem, String identifier)
- : super(fileSystem, identifier) {
- Converter<String, Link> reviveLink = ReviveLink(fileSystem);
- Converter<String, Future<Link>> reviveLinkAsFuture =
- reviveLink.fuse(const ToFuture<Link>());
-
- methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #rename: reviveLinkAsFuture,
- #renameSync: reviveLink,
- #delete: reviveLinkAsFuture,
- #create: reviveLinkAsFuture,
- #createSync: const Passthrough<Null>(),
- #update: reviveLinkAsFuture,
- #updateSync: const Passthrough<Null>(),
- #target: const ToFuture<String>(),
- #targetSync: const Passthrough<String>(),
- });
-
- properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #absolute: reviveLink,
- });
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_proxy_mixin.dart b/packages/file/lib/src/backends/record_replay/replay_proxy_mixin.dart
deleted file mode 100644
index d501ab3..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_proxy_mixin.dart
+++ /dev/null
@@ -1,182 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:convert';
-
-import 'package:meta/meta.dart';
-
-import 'codecs.dart';
-import 'common.dart';
-import 'errors.dart';
-import 'proxy.dart';
-
-typedef _InvocationMatcher = bool Function(Map<String, dynamic> entry);
-
-/// Used to record the order in which invocations were replayed.
-///
-/// Tests can later check expectations about the order in which invocations
-/// were replayed vis-a-vis the order in which they were recorded.
-int _nextOrdinal = 0;
-
-/// Mixin that enables replaying of property accesses, property mutations, and
-/// method invocations from a prior recording.
-///
-/// This class uses `noSuchMethod` to replay a well-defined set of invocations
-/// (including property gets and sets) on an object. Subclasses wire this up by
-/// doing the following:
-///
-/// - Populate the list of method invocations to replay in the [methods] map.
-/// - Populate the list of property invocations to replay in the [properties]
-/// map. The symbol name for getters should be the property name, and the
-/// symbol name for setters should be the property name immediately
-/// followed by an equals sign (e.g. `propertyName=`).
-/// - Do not implement a concrete getter, setter, or method that you wish to
-/// replay, as doing so will circumvent the machinery that this mixin uses
-/// (`noSuchMethod`) to replay invocations.
-///
-/// **Example use**:
-///
-/// abstract class Foo {
-/// ComplexObject sampleMethod();
-///
-/// Foo sampleParent;
-/// }
-///
-/// class ReplayFoo extends Object with ReplayProxyMixin implements Foo {
-/// final List<Map<String, dynamic>> manifest;
-/// final String identifier;
-///
-/// ReplayFoo(this.manifest, this.identifier) {
-/// methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
-/// #sampleMethod: complexObjectReviver,
-/// });
-///
-/// properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
-/// #sampleParent: fooReviver,
-/// const Symbol('sampleParent='): passthroughReviver,
-/// });
-/// }
-/// }
-mixin ReplayProxyMixin on Object implements ProxyObject, ReplayAware {
- /// Maps method names to [Converter]s that will revive result values.
- ///
- /// Invocations of methods listed in this map will be replayed by looking for
- /// matching invocations in the [manifest] and reviving the invocation return
- /// value using the [Converter] found in this map.
- @protected
- final Map<Symbol, Converter<dynamic, dynamic>> methods =
- <Symbol, Converter<dynamic, dynamic>>{};
-
- /// Maps property getter and setter names to [Converter]s that will revive
- /// result values.
- ///
- /// Access and mutation of properties listed in this map will be replayed
- /// by looking for matching property accesses in the [manifest] and reviving
- /// the invocation return value using the [Converter] found in this map.
- ///
- /// The keys for property getters are the simple property names, whereas the
- /// keys for property setters are the property names followed by an equals
- /// sign (e.g. `propertyName=`).
- @protected
- final Map<Symbol, Converter<dynamic, dynamic>> properties =
- <Symbol, Converter<dynamic, dynamic>>{};
-
- /// The manifest of recorded invocation events.
- ///
- /// When invocations are received on this object, we will attempt find a
- /// matching invocation in this manifest to perform the replay. If no such
- /// invocation is found (or if it has already been replayed), the caller will
- /// receive a [NoMatchingInvocationError].
- ///
- /// This manifest exists as `MANIFEST.txt` in a recording directory.
- @protected
- List<Map<String, dynamic>> get manifest;
-
- /// Protected method for subclasses to be notified when an invocation has
- /// been successfully replayed, and the result is about to be returned to
- /// the caller.
- ///
- /// Returns the value that is to be returned to the caller. The default
- /// implementation returns [result] (replayed from the recording); subclasses
- /// may override this method to alter the result that's returned to the
- /// caller.
- @protected
- dynamic onResult(Invocation invocation, dynamic result) => result;
-
- @override
- dynamic noSuchMethod(Invocation invocation) {
- Symbol name = invocation.memberName;
- Converter<dynamic, dynamic> reviver =
- invocation.isAccessor ? properties[name] : methods[name];
-
- if (reviver == null) {
- // No reviver generally means that there truly is no such method on
- // this object. The exception is when the invocation represents a getter
- // on a method, in which case we return a method proxy that, when
- // invoked, will replay the desired invocation.
- return invocation.isGetter && methods[name] != null
- ? MethodProxy(this, name)
- : super.noSuchMethod(invocation);
- }
-
- Map<String, dynamic> entry = _nextEvent(invocation);
- if (entry == null) {
- throw NoMatchingInvocationError(invocation);
- }
- entry[kManifestOrdinalKey] = _nextOrdinal++;
-
- dynamic error = entry[kManifestErrorKey];
- if (error != null) {
- throw const ToError().convert(error);
- }
- dynamic result = reviver.convert(entry[kManifestResultKey]);
- result = onResult(invocation, result);
- return result;
- }
-
- /// Finds the next available invocation event in the [manifest] that matches
- /// the specified [invocation].
- Map<String, dynamic> _nextEvent(Invocation invocation) {
- _InvocationMatcher matches = _getMatcher(invocation);
- return manifest.firstWhere((Map<String, dynamic> entry) {
- return entry[kManifestOrdinalKey] == null && matches(entry);
- }, orElse: () => null);
- }
-
- _InvocationMatcher _getMatcher(Invocation invocation) {
- String name = getSymbolName(invocation.memberName);
- List<dynamic> args =
- encode(invocation.positionalArguments) as List<dynamic>;
- Map<String, dynamic> namedArgs =
- encode(invocation.namedArguments) as Map<String, dynamic>;
-
- if (invocation.isGetter) {
- return (Map<String, dynamic> entry) =>
- entry[kManifestTypeKey] == kGetType &&
- entry[kManifestPropertyKey] == name &&
- entry[kManifestObjectKey] == identifier;
- } else if (invocation.isSetter) {
- return (Map<String, dynamic> entry) =>
- entry[kManifestTypeKey] == kSetType &&
- entry[kManifestPropertyKey] == name &&
- deeplyEqual(entry[kManifestValueKey], args[0]) &&
- entry[kManifestObjectKey] == identifier;
- } else {
- return (Map<String, dynamic> entry) {
- return entry[kManifestTypeKey] == kInvokeType &&
- entry[kManifestMethodKey] == name &&
- deeplyEqual(entry[kManifestPositionalArgumentsKey], args) &&
- deeplyEqual(
- _asNamedArgsType(
- entry[kManifestNamedArgumentsKey] as Map<String, dynamic>),
- namedArgs) &&
- entry[kManifestObjectKey] == identifier;
- };
- }
- }
-
- static Map<String, dynamic> _asNamedArgsType(Map<dynamic, dynamic> map) {
- return Map<String, dynamic>.from(map);
- }
-}
diff --git a/packages/file/lib/src/backends/record_replay/replay_random_access_file.dart b/packages/file/lib/src/backends/record_replay/replay_random_access_file.dart
deleted file mode 100644
index eb4d0cc..0000000
--- a/packages/file/lib/src/backends/record_replay/replay_random_access_file.dart
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:typed_data';
-
-import 'package:file/file.dart';
-
-import 'codecs.dart';
-import 'replay_file_system.dart';
-import 'replay_proxy_mixin.dart';
-
-/// [RandomAccessFile] implementation that replays all invocation activity from a prior
-/// recording.
-class ReplayRandomAccessFile extends Object
- with ReplayProxyMixin
- implements RandomAccessFile {
- /// Creates a new [ReplayRandomAccessFile].
- ReplayRandomAccessFile(this._fileSystem, this.identifier) {
- ToFuture<RandomAccessFile> toFuture = const ToFuture<RandomAccessFile>();
- Converter<String, Future<RandomAccessFile>> reviveRandomAccessFileAsFuture =
- ReviveRandomAccessFile(_fileSystem).fuse(toFuture);
-
- Converter<List<dynamic>, Uint8List> reviveUint8List =
- const CastList<dynamic, int>().fuse(const ToUint8List());
- Converter<List<dynamic>, Future<Uint8List>> reviveUint8ListFuture =
- reviveUint8List.fuse(const ToFuture<Uint8List>());
-
- methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #close: reviveRandomAccessFileAsFuture,
- #closeSync: const Passthrough<Null>(),
- #readByte: const ToFuture<int>(),
- #readByteSync: const Passthrough<int>(),
- #read: reviveUint8ListFuture,
- #readSync: reviveUint8List,
- #readInto: const ToFuture<int>(),
- #readIntoSync: const Passthrough<int>(),
- #writeByte: reviveRandomAccessFileAsFuture,
- #writeByteSync: const Passthrough<int>(),
- #writeFrom: reviveRandomAccessFileAsFuture,
- #writeFromSync: const Passthrough<Null>(),
- #writeString: reviveRandomAccessFileAsFuture,
- #writeStringSync: const Passthrough<Null>(),
- #position: const ToFuture<int>(),
- #positionSync: const Passthrough<int>(),
- #setPosition: reviveRandomAccessFileAsFuture,
- #setPositionSync: const Passthrough<Null>(),
- #truncate: reviveRandomAccessFileAsFuture,
- #truncateSync: const Passthrough<Null>(),
- #length: const ToFuture<int>(),
- #lengthSync: const Passthrough<int>(),
- #flush: reviveRandomAccessFileAsFuture,
- #flushSync: const Passthrough<Null>(),
- #lock: reviveRandomAccessFileAsFuture,
- #lockSync: const Passthrough<Null>(),
- #unlock: reviveRandomAccessFileAsFuture,
- #unlockSync: const Passthrough<Null>(),
- });
-
- properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
- #path: const Passthrough<String>(),
- });
- }
-
- final ReplayFileSystemImpl _fileSystem;
-
- @override
- final String identifier;
-
- @override
- List<Map<String, dynamic>> get manifest => _fileSystem.manifest;
-}
diff --git a/packages/file/lib/src/backends/record_replay/result_reference.dart b/packages/file/lib/src/backends/record_replay/result_reference.dart
deleted file mode 100644
index 3228bce..0000000
--- a/packages/file/lib/src/backends/record_replay/result_reference.dart
+++ /dev/null
@@ -1,174 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-
-import 'package:meta/meta.dart';
-
-import 'codecs.dart';
-import 'events.dart';
-import 'recording_proxy_mixin.dart';
-
-/// Wraps a raw invocation return value for the purpose of recording.
-///
-/// This class is intended for use with [RecordingProxyMixin]. Mixin subclasses
-/// may configure a method or getter to return a [ResultReference] rather than
-/// a raw result, and:
-///
-/// - [RecordingProxyMixin] will automatically return the reference's [value]
-/// to callers (as if the mixin subclass had returned the raw value
-/// directly).
-/// - The recording's [InvocationEvent] will automatically record the
-/// reference's [recordedValue].
-/// - The recording's serialized value (written out during
-/// [LiveRecording.flush]) will automatically serialize the reference's
-/// [serializedValue].
-abstract class ResultReference<T> {
- /// Creates a new `ResultReference`.
- const ResultReference();
-
- /// The raw value to return to callers of the method or getter.
- T get value;
-
- /// The value to record in the recording's [InvocationEvent].
- dynamic get recordedValue;
-
- /// A JSON-serializable representation of this result, suitable for
- /// encoding in a recording manifest.
- ///
- /// The value of this property will be one of the JSON-native types: `num`,
- /// `String`, `bool`, `Null`, `List`, or `Map`.
- ///
- /// This allows for method-specific encoding routines. Take, for example, the
- /// case of a method that returns `List<int>`. This type is natively
- /// serializable by `JSONEncoder`, so if the raw value were directly returned
- /// from an invocation, the recording would happily serialize the result as
- /// a list of integers. However, the method may want to serialize the return
- /// value differently, such as by writing it to file (if it knows the list is
- /// actually a byte array that was read from a file). In this case, the
- /// method can return a `ResultReference` to the list, and it will have a
- /// hook into the serialization process.
- dynamic get serializedValue => encode(recordedValue);
-
- /// A [Future] that completes when [value] has completed.
- ///
- /// If [value] is a [Future], this future will complete when [value] has
- /// completed. If [value] is a [Stream], this future will complete when the
- /// stream sends a "done" event. If value is neither a future nor a stream,
- /// this future will complete immediately.
- Future<void> get complete => Future<void>.value();
-}
-
-/// Wraps a future result.
-class FutureReference<T> extends ResultReference<Future<T>> {
- /// Creates a new `FutureReference` that wraps the specified [future].
- FutureReference(Future<T> future) : _future = future;
-
- final Future<T> _future;
- T _value;
-
- bool get _isVoid => T == const _TypeLiteral<void>().type;
-
- /// The future value to return to callers of the method or getter.
- @override
- Future<T> get value {
- return _future.then(
- (T value) {
- if (_isVoid && value != null) {
- throw StateError(
- 'Unexpected value in $runtimeType: ${_future.runtimeType}');
- }
- _value = value;
- return value;
- },
- onError: (dynamic error) {
- // TODO(tvolkert): Record errors
- throw error;
- },
- );
- }
-
- /// The value returned by the completion of the future.
- ///
- /// If the future threw an error, this value will be `null`.
- @override
- T get recordedValue => _value;
-
- @override
- Future<void> get complete => value.catchError((dynamic _) {});
-}
-
-class _TypeLiteral<T> {
- const _TypeLiteral();
-
- Type get type => T;
-}
-
-/// Wraps a stream result.
-class StreamReference<T> extends ResultReference<Stream<T>> {
- /// Creates a new `StreamReference` that wraps the specified [stream].
- StreamReference(Stream<T> stream)
- : _stream = stream,
- _controller = stream.isBroadcast
- ? StreamController<T>.broadcast()
- : StreamController<T>() {
- _controller.onListen = () {
- assert(_subscription == null);
- _subscription = _listenToStream();
- };
- _controller.onCancel = () async {
- assert(_subscription != null);
- await _subscription.cancel();
- _subscription = null;
- };
- _controller.onPause = () {
- assert(_subscription != null && !_subscription.isPaused);
- _subscription.pause();
- };
- _controller.onResume = () {
- assert(_subscription != null && _subscription.isPaused);
- _subscription.resume();
- };
- }
-
- final Stream<T> _stream;
- final StreamController<T> _controller;
- final Completer<void> _completer = Completer<void>();
- final List<T> _data = <T>[];
- StreamSubscription<T> _subscription;
-
- StreamSubscription<T> _listenToStream() {
- return _stream.listen(
- (T element) {
- _data.add(element);
- onData(element);
- _controller.add(element);
- },
- onError: (dynamic error, StackTrace stackTrace) {
- // TODO(tvolkert): Record errors
- _controller.addError(error, stackTrace);
- },
- onDone: () {
- _completer.complete();
- _controller.close();
- },
- );
- }
-
- /// Called when an event is received from the underlying delegate stream.
- ///
- /// Subclasses may override this method to be notified when events are
- /// fired from the underlying stream.
- @protected
- void onData(T event) {}
-
- @override
- Stream<T> get value => _controller.stream;
-
- @override
- List<T> get recordedValue => _data;
-
- @override
- Future<void> get complete => _completer.future.catchError((dynamic _) {});
-}
diff --git a/packages/file/lib/src/common.dart b/packages/file/lib/src/common.dart
index 95eb1e1..ea415a2 100644
--- a/packages/file/lib/src/common.dart
+++ b/packages/file/lib/src/common.dart
@@ -2,6 +2,7 @@
// 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.10
import 'interface.dart';
/// Returns a 'No such file or directory' [FileSystemException].
diff --git a/packages/file/lib/src/forwarding.dart b/packages/file/lib/src/forwarding.dart
index e413acf..82651aa 100644
--- a/packages/file/lib/src/forwarding.dart
+++ b/packages/file/lib/src/forwarding.dart
@@ -2,6 +2,7 @@
// 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.10
export 'forwarding/forwarding_directory.dart';
export 'forwarding/forwarding_file.dart';
export 'forwarding/forwarding_file_system.dart';
diff --git a/packages/file/lib/src/forwarding/forwarding_directory.dart b/packages/file/lib/src/forwarding/forwarding_directory.dart
index 062e02b..099152f 100644
--- a/packages/file/lib/src/forwarding/forwarding_directory.dart
+++ b/packages/file/lib/src/forwarding/forwarding_directory.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:file/src/io.dart' as io;
@@ -22,11 +23,11 @@
delegate.createSync(recursive: recursive);
@override
- Future<Directory> createTemp([String prefix]) async =>
+ Future<Directory> createTemp([String? prefix]) async =>
wrap(await delegate.createTemp(prefix));
@override
- Directory createTempSync([String prefix]) =>
+ Directory createTempSync([String? prefix]) =>
wrap(delegate.createTempSync(prefix));
@override
diff --git a/packages/file/lib/src/forwarding/forwarding_file.dart b/packages/file/lib/src/forwarding/forwarding_file.dart
index 8f98b50..0cbfd3c 100644
--- a/packages/file/lib/src/forwarding/forwarding_file.dart
+++ b/packages/file/lib/src/forwarding/forwarding_file.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
@@ -72,7 +73,7 @@
delegate.openSync(mode: mode);
@override
- Stream<Uint8List> openRead([int start, int end]) => delegate
+ Stream<Uint8List> openRead([int? start, int? end]) => delegate
.openRead(start, end)
.cast<List<int>>()
.transform(const _ToUint8List());
diff --git a/packages/file/lib/src/forwarding/forwarding_file_system.dart b/packages/file/lib/src/forwarding/forwarding_file_system.dart
index 6d027cf..98fda92 100644
--- a/packages/file/lib/src/forwarding/forwarding_file_system.dart
+++ b/packages/file/lib/src/forwarding/forwarding_file_system.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:file/src/io.dart' as io;
diff --git a/packages/file/lib/src/forwarding/forwarding_file_system_entity.dart b/packages/file/lib/src/forwarding/forwarding_file_system_entity.dart
index 75804a9..7b334b2 100644
--- a/packages/file/lib/src/forwarding/forwarding_file_system_entity.dart
+++ b/packages/file/lib/src/forwarding/forwarding_file_system_entity.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:file/src/io.dart' as io;
diff --git a/packages/file/lib/src/forwarding/forwarding_link.dart b/packages/file/lib/src/forwarding/forwarding_link.dart
index 6dd0403..6082a65 100644
--- a/packages/file/lib/src/forwarding/forwarding_link.dart
+++ b/packages/file/lib/src/forwarding/forwarding_link.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:file/src/io.dart' as io;
diff --git a/packages/file/lib/src/interface.dart b/packages/file/lib/src/interface.dart
index 4662e35..e276fd0 100644
--- a/packages/file/lib/src/interface.dart
+++ b/packages/file/lib/src/interface.dart
@@ -2,6 +2,7 @@
// 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.10
library file.src.interface;
export 'interface/directory.dart';
diff --git a/packages/file/lib/src/interface/directory.dart b/packages/file/lib/src/interface/directory.dart
index aa736cb..f499371 100644
--- a/packages/file/lib/src/interface/directory.dart
+++ b/packages/file/lib/src/interface/directory.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import '../io.dart' as io;
@@ -17,10 +18,10 @@
Future<Directory> create({bool recursive = false});
@override
- Future<Directory> createTemp([String prefix]);
+ Future<Directory> createTemp([String? prefix]);
@override
- Directory createTempSync([String prefix]);
+ Directory createTempSync([String? prefix]);
@override
Future<Directory> rename(String newPath);
diff --git a/packages/file/lib/src/interface/error_codes.dart b/packages/file/lib/src/interface/error_codes.dart
index 4983445..e3e0327 100644
--- a/packages/file/lib/src/interface/error_codes.dart
+++ b/packages/file/lib/src/interface/error_codes.dart
@@ -2,6 +2,7 @@
// 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.10
import 'error_codes_internal.dart'
if (dart.library.io) 'error_codes_dart_io.dart';
@@ -168,7 +169,7 @@
static int get EXDEV => _platform((_Codes codes) => codes.exdev);
static int _platform(int getCode(_Codes codes)) {
- _Codes codes = _platforms[operatingSystem] ?? _platforms['linux'];
+ _Codes codes = (_platforms[operatingSystem] ?? _platforms['linux'])!;
return getCode(codes);
}
}
diff --git a/packages/file/lib/src/interface/error_codes_dart_io.dart b/packages/file/lib/src/interface/error_codes_dart_io.dart
index 3f0a97f..da3e4b5 100644
--- a/packages/file/lib/src/interface/error_codes_dart_io.dart
+++ b/packages/file/lib/src/interface/error_codes_dart_io.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:io' show Platform;
/// If we have `dart:io` available, we pull the current operating system from
diff --git a/packages/file/lib/src/interface/error_codes_internal.dart b/packages/file/lib/src/interface/error_codes_internal.dart
index 0a9d7dc..6082bb0 100644
--- a/packages/file/lib/src/interface/error_codes_internal.dart
+++ b/packages/file/lib/src/interface/error_codes_internal.dart
@@ -2,6 +2,8 @@
// 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.10
+
/// In environments that don't have `dart:io`, we can't access the Platform
/// class to determine what platform we're on, so we just pretend we're on
/// Linux, meaning we'll get errno values that match Linux's errno.h.
diff --git a/packages/file/lib/src/interface/file.dart b/packages/file/lib/src/interface/file.dart
index ad50475..3025d56 100644
--- a/packages/file/lib/src/interface/file.dart
+++ b/packages/file/lib/src/interface/file.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'dart:convert';
diff --git a/packages/file/lib/src/interface/file_system.dart b/packages/file/lib/src/interface/file_system.dart
index b0cc9fd..2198cef 100644
--- a/packages/file/lib/src/interface/file_system.dart
+++ b/packages/file/lib/src/interface/file_system.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import 'package:meta/meta.dart';
diff --git a/packages/file/lib/src/interface/file_system_entity.dart b/packages/file/lib/src/interface/file_system_entity.dart
index 71cb667..b8d1f99 100644
--- a/packages/file/lib/src/interface/file_system_entity.dart
+++ b/packages/file/lib/src/interface/file_system_entity.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import '../io.dart' as io;
diff --git a/packages/file/lib/src/interface/link.dart b/packages/file/lib/src/interface/link.dart
index 433b560..ad1515f 100644
--- a/packages/file/lib/src/interface/link.dart
+++ b/packages/file/lib/src/interface/link.dart
@@ -2,6 +2,7 @@
// 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.10
import 'dart:async';
import '../io.dart' as io;
diff --git a/packages/file/lib/src/io.dart b/packages/file/lib/src/io.dart
index 9d57e78..7bc7d09 100644
--- a/packages/file/lib/src/io.dart
+++ b/packages/file/lib/src/io.dart
@@ -2,6 +2,8 @@
// 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.10
+
/// For internal use only!
///
/// This exposes the subset of the `dart:io` interfaces that are required by
diff --git a/packages/file/pubspec.yaml b/packages/file/pubspec.yaml
index 9b065eb..31d7757 100644
--- a/packages/file/pubspec.yaml
+++ b/packages/file/pubspec.yaml
@@ -1,24 +1,18 @@
name: file
-version: 5.2.2-dev
-authors:
-- Matan Lurey <matanl@google.com>
-- Yegor Jbanov <yjbanov@google.com>
-- Todd Volkert <tvolkert@google.com>
-
+version: 6.0.0-nullsafety
description:
A pluggable, mockable file system abstraction for Dart. Supports local file
system access, as well as in-memory file systems, record-replay file systems,
and chroot file systems.
-
homepage: https://github.com/google/file.dart
+environment:
+ sdk: '>=2.9.0 <3.0.0'
+
dependencies:
- meta: ^1.1.2
- path: ^1.5.1
+ meta: ^1.3.0-nullsafety.2
+ path: ^1.8.0-nullsafety
dev_dependencies:
test: '>=1.0.0 <2.0.0'
file_testing: '>=2.0.0 <3.0.0'
-
-environment:
- sdk: '>=2.2.2 <3.0.0'
diff --git a/packages/file/test/record_replay_matchers.dart b/packages/file/test/record_replay_matchers.dart
deleted file mode 100644
index 6187242..0000000
--- a/packages/file/test/record_replay_matchers.dart
+++ /dev/null
@@ -1,582 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'package:file/record_replay.dart';
-import 'package:file/src/backends/record_replay/common.dart'
- show getSymbolName; // ignore: implementation_imports
-import 'package:test/test.dart';
-
-const Map<Type, String> _kTypeDescriptions = <Type, String>{
- MethodEvent: 'a method invocation',
- PropertyGetEvent: 'a property retrieval',
- PropertySetEvent: 'a property mutation',
-};
-
-const Map<Type, Matcher> _kTypeMatchers = <Type, Matcher>{
- MethodEvent: TypeMatcher<MethodEvent<dynamic>>(),
- PropertyGetEvent: TypeMatcher<PropertyGetEvent<dynamic>>(),
- PropertySetEvent: TypeMatcher<PropertySetEvent<dynamic>>(),
-};
-
-/// Returns a matcher that will match against a [MethodEvent].
-///
-/// If [name] is specified, only method invocations of a matching method name
-/// will successfully match. [name] may be a String, a predicate function,
-/// or a [Matcher].
-///
-/// The returned [MethodInvocation] matcher can be used to further limit the
-/// scope of the match (e.g. by invocation result, target object, etc).
-MethodInvocation invokesMethod([dynamic name]) => MethodInvocation._(name);
-
-/// Returns a matcher that will match against a [PropertyGetEvent].
-///
-/// If [name] is specified, only property retrievals of a matching property name
-/// will successfully match. [name] may be a String, a predicate function,
-/// or a [Matcher].
-///
-/// The returned [PropertyGet] matcher can be used to further limit the
-/// scope of the match (e.g. by property value, target object, etc).
-PropertyGet getsProperty([dynamic name]) => PropertyGet._(name);
-
-/// Returns a matcher that will match against a [PropertySetEvent].
-///
-/// If [name] is specified, only property mutations of a matching property name
-/// will successfully match. [name] may be a String, a predicate function,
-/// or a [Matcher].
-///
-/// The returned [PropertySet] matcher can be used to further limit the
-/// scope of the match (e.g. by property value, target object, etc).
-PropertySet setsProperty([dynamic name]) => PropertySet._(name);
-
-/// A matcher that successfully matches against a future or function
-/// that throws a [NoMatchingInvocationError].
-Matcher throwsNoMatchingInvocationError =
- throwsA(const TypeMatcher<NoMatchingInvocationError>());
-
-/// Base class for matchers that match against generic [InvocationEvent]
-/// instances.
-abstract class RecordedInvocation<T extends RecordedInvocation<T>>
- extends Matcher {
- RecordedInvocation._(Type type) : _typeMatcher = _Type(type);
-
- final _Type _typeMatcher;
- final List<Matcher> _fieldMatchers = <Matcher>[];
-
- /// Limits the scope of the match to invocations that occurred on the
- /// specified target [object].
- ///
- /// [object] may be an instance or a [Matcher]. If it is an instance, it will
- /// be automatically wrapped in an equality matcher.
- ///
- /// Returns this matcher for chaining.
- T on(dynamic object) {
- _fieldMatchers.add(_Target(object));
- return this as T;
- }
-
- /// Limits the scope of the match to invocations that produced the specified
- /// [result].
- ///
- /// For method invocations, this matches against the return value of the
- /// method. For property retrievals, this matches against the value of the
- /// property. Property mutations will always produce a `null` result, so
- /// [PropertySet] will automatically call `withResult(null)` when it is
- /// instantiated.
- ///
- /// [result] may be an instance or a [Matcher]. If it is an instance, it will
- /// be automatically wrapped in an equality matcher.
- ///
- /// Returns this matcher for chaining.
- T withResult(dynamic result) {
- _fieldMatchers.add(_Result(result));
- return this as T;
- }
-
- /// Limits the scope of the match to invocations that were recorded with the
- /// specified [timestamp].
- ///
- /// [timestamp] may be an `int` or a [Matcher]. If it is an `int`, it will
- /// be automatically wrapped in an equality matcher.
- ///
- /// Returns this matcher for chaining.
- T withTimestamp(dynamic timestamp) {
- _fieldMatchers.add(_Timestamp(timestamp));
- return this as T;
- }
-
- /// @nodoc
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
- if (!_typeMatcher.matches(item, matchState)) {
- addStateInfo(matchState, <String, Matcher>{'matcher': _typeMatcher});
- return false;
- }
- for (Matcher matcher in _fieldMatchers) {
- if (!matcher.matches(item, matchState)) {
- addStateInfo(matchState, <String, Matcher>{'matcher': matcher});
- return false;
- }
- }
- return true;
- }
-
- /// @nodoc
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- Matcher matcher = matchState['matcher'] as Matcher;
- matcher.describeMismatch(item, description,
- matchState['state'] as Map<String, dynamic>, verbose);
- return description;
- }
-
- /// @nodoc
- @override
- Description describe(Description description) {
- String divider = '\n - ';
- return _typeMatcher
- .describe(description)
- .add(':')
- .addAll(divider, divider, '', _fieldMatchers);
- }
-}
-
-/// Matchers that matches against [MethodEvent] instances.
-///
-/// Instances of this matcher are obtained by calling [invokesMethod]. Once
-/// instantiated, callers may use this matcher to further qualify the scope
-/// of their match.
-class MethodInvocation extends RecordedInvocation<MethodInvocation> {
- MethodInvocation._(dynamic methodName) : super._(MethodEvent) {
- if (methodName != null) {
- _fieldMatchers.add(_MethodName(methodName));
- }
- }
-
- /// Limits the scope of the match to method invocations that passed the
- /// specified positional [arguments].
- ///
- /// [arguments] may be a list instance or a [Matcher]. If it is a list, it
- /// will be automatically wrapped in an equality matcher.
- ///
- /// Returns this matcher for chaining.
- MethodInvocation withPositionalArguments(dynamic arguments) {
- _fieldMatchers.add(_PositionalArguments(arguments));
- return this;
- }
-
- /// Limits the scope of the match to method invocations that passed the
- /// specified named argument.
- ///
- /// The argument [value] may be an instance or a [Matcher]. If it is an
- /// instance, it will be automatically wrapped in an equality matcher.
- ///
- /// Returns this matcher for chaining.
- MethodInvocation withNamedArgument(String name, dynamic value) {
- _fieldMatchers.add(_NamedArgument(name, value));
- return this;
- }
-
- /// Limits the scope of the match to method invocations that specified no
- /// named arguments.
- ///
- /// Returns this matcher for chaining.
- MethodInvocation withNoNamedArguments() {
- _fieldMatchers.add(const _NoNamedArguments());
- return this;
- }
-}
-
-/// Matchers that matches against [PropertyGetEvent] instances.
-///
-/// Instances of this matcher are obtained by calling [getsProperty]. Once
-/// instantiated, callers may use this matcher to further qualify the scope
-/// of their match.
-class PropertyGet extends RecordedInvocation<PropertyGet> {
- PropertyGet._(dynamic propertyName) : super._(PropertyGetEvent) {
- if (propertyName != null) {
- _fieldMatchers.add(_GetPropertyName(propertyName));
- }
- }
-}
-
-/// Matchers that matches against [PropertySetEvent] instances.
-///
-/// Instances of this matcher are obtained by calling [setsProperty]. Once
-/// instantiated, callers may use this matcher to further qualify the scope
-/// of their match.
-class PropertySet extends RecordedInvocation<PropertySet> {
- PropertySet._(dynamic propertyName) : super._(PropertySetEvent) {
- withResult(null);
- if (propertyName != null) {
- _fieldMatchers.add(_SetPropertyName(propertyName));
- }
- }
-
- /// Limits the scope of the match to property mutations that set the property
- /// to the specified [value].
- ///
- /// [value] may be an instance or a [Matcher]. If it is an instance, it will
- /// be automatically wrapped in an equality matcher.
- ///
- /// Returns this matcher for chaining.
- PropertySet toValue(dynamic value) {
- _fieldMatchers.add(_SetValue(value));
- return this;
- }
-}
-
-class _Target extends Matcher {
- _Target(dynamic target) : _matcher = wrapMatcher(target);
-
- final Matcher _matcher;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(item.object, matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- description.add('was invoked on: ${item.object}');
- Description matcherDesc = StringDescription();
- _matcher.describeMismatch(item.object, matcherDesc, matchState, verbose);
- if (matcherDesc.length > 0) {
- description.add('\n Which: ').add(matcherDesc.toString());
- }
- return description;
- }
-
- @override
- Description describe(Description desc) {
- desc.add('on object: ');
- return _matcher.describe(desc);
- }
-}
-
-class _Result extends Matcher {
- _Result(dynamic result) : _matcher = wrapMatcher(result);
-
- final Matcher _matcher;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(item.result, matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- description.add('returned: ${item.result}');
- Description matcherDesc = StringDescription();
- _matcher.describeMismatch(item.result, matcherDesc, matchState, verbose);
- if (matcherDesc.length > 0) {
- description.add('\n Which: ').add(matcherDesc.toString());
- }
- return description;
- }
-
- @override
- Description describe(Description desc) {
- desc.add('with result: ');
- return _matcher.describe(desc);
- }
-}
-
-class _Timestamp extends Matcher {
- _Timestamp(dynamic timestamp) : _matcher = wrapMatcher(timestamp);
-
- final Matcher _matcher;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(item.timestamp, matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- description.add('has timestamp: ${item.timestamp}');
- Description matcherDesc = StringDescription();
- _matcher.describeMismatch(item.timestamp, matcherDesc, matchState, verbose);
- if (matcherDesc.length > 0) {
- description.add('\n Which: ').add(matcherDesc.toString());
- }
- return description;
- }
-
- @override
- Description describe(Description desc) {
- desc.add('with timestamp: ');
- return _matcher.describe(desc);
- }
-}
-
-class _Type extends Matcher {
- const _Type(this.type);
-
- final Type type;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _kTypeMatchers[type].matches(item, matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- Type type;
- for (Type matchType in _kTypeMatchers.keys) {
- Matcher matcher = _kTypeMatchers[matchType];
- if (matcher.matches(item, <dynamic, dynamic>{})) {
- type = matchType;
- break;
- }
- }
- if (type != null) {
- description.add('is ').add(_kTypeDescriptions[type]);
- } else {
- description.add('is a ${item.runtimeType}');
- }
- return description;
- }
-
- @override
- Description describe(Description desc) => desc.add(_kTypeDescriptions[type]);
-}
-
-class _MethodName extends Matcher {
- _MethodName(dynamic name) : _matcher = wrapMatcher(name);
-
- final Matcher _matcher;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(getSymbolName(item.method as Symbol), matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- String methodName = getSymbolName(item.method as Symbol);
- description.add('invoked method: \'$methodName\'');
- Description matcherDesc = StringDescription();
- _matcher.describeMismatch(methodName, matcherDesc, matchState, verbose);
- if (matcherDesc.length > 0) {
- description.add('\n Which: ').add(matcherDesc.toString());
- }
- return description;
- }
-
- @override
- Description describe(Description desc) {
- desc.add('method: ');
- return _matcher.describe(desc);
- }
-}
-
-class _PositionalArguments extends Matcher {
- _PositionalArguments(dynamic value) : _matcher = wrapMatcher(value);
-
- final Matcher _matcher;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(item.positionalArguments, matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- return _matcher.describeMismatch(
- item.positionalArguments, description, matchState, verbose);
- }
-
- @override
- Description describe(Description desc) {
- desc.add('with positional arguments: ');
- return _matcher.describe(desc);
- }
-}
-
-class _NamedArgument extends Matcher {
- _NamedArgument(this.name, this.value)
- : _matcher = containsPair(Symbol(name), value);
-
- final String name;
- final dynamic value;
- final Matcher _matcher;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(item.namedArguments, matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- return _matcher.describeMismatch(
- item.namedArguments, description, matchState, verbose);
- }
-
- @override
- Description describe(Description description) =>
- description.add('with named argument "$name" = $value');
-}
-
-class _NoNamedArguments extends Matcher {
- const _NoNamedArguments();
-
- Matcher get _matcher => isEmpty;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(item.namedArguments, matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- return _matcher.describeMismatch(
- item.namedArguments, description, matchState, verbose);
- }
-
- @override
- Description describe(Description description) =>
- description.add('with no named arguments');
-}
-
-class _GetPropertyName extends Matcher {
- _GetPropertyName(dynamic _name) : _matcher = wrapMatcher(_name);
-
- final Matcher _matcher;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(getSymbolName(item.property as Symbol), matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- String propertyName = getSymbolName(item.property as Symbol);
- description.add('got property: \'$propertyName\'');
- Description matcherDesc = StringDescription();
- _matcher.describeMismatch(propertyName, matcherDesc, matchState, verbose);
- if (matcherDesc.length > 0) {
- description.add('\n Which: ').add(matcherDesc.toString());
- }
- return description;
- }
-
- @override
- Description describe(Description description) {
- description.add('gets property: ');
- return _matcher.describe(description);
- }
-}
-
-class _SetPropertyName extends Matcher {
- _SetPropertyName(dynamic _name) : _matcher = wrapMatcher(_name);
-
- final Matcher _matcher;
-
- /// Strips the trailing `=` off the symbol name to get the property name.
- String _getPropertyName(dynamic item) {
- String symbolName = getSymbolName(item.property as Symbol);
- return symbolName.substring(0, symbolName.length - 1);
- }
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
- return _matcher.matches(_getPropertyName(item), matchState);
- }
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- String propertyName = _getPropertyName(item);
- description.add('set property: \'$propertyName\'');
- Description matcherDesc = StringDescription();
- _matcher.describeMismatch(propertyName, matcherDesc, matchState, verbose);
- if (matcherDesc.length > 0) {
- description.add('\n Which: ').add(matcherDesc.toString());
- }
- return description;
- }
-
- @override
- Description describe(Description description) {
- description.add('of property: ');
- return _matcher.describe(description);
- }
-}
-
-class _SetValue extends Matcher {
- _SetValue(dynamic value) : _matcher = wrapMatcher(value);
-
- final Matcher _matcher;
-
- @override
- bool matches(dynamic item, Map<dynamic, dynamic> matchState) =>
- _matcher.matches(item.value, matchState);
-
- @override
- Description describeMismatch(
- dynamic item,
- Description description,
- Map<dynamic, dynamic> matchState,
- bool verbose,
- ) {
- description.add('set value: ${item.value}');
- Description matcherDesc = StringDescription();
- _matcher.describeMismatch(item.value, matcherDesc, matchState, verbose);
- if (matcherDesc.length > 0) {
- description.add('\n Which: ').add(matcherDesc.toString());
- }
- return description;
- }
-
- @override
- Description describe(Description description) {
- description.add('to value: ');
- return _matcher.describe(description);
- }
-}
diff --git a/packages/file/test/recording_test.dart b/packages/file/test/recording_test.dart
deleted file mode 100644
index 968dad1..0000000
--- a/packages/file/test/recording_test.dart
+++ /dev/null
@@ -1,944 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-import 'dart:convert';
-import 'dart:io';
-
-import 'package:file/file.dart';
-import 'package:file/memory.dart';
-import 'package:file/record_replay.dart';
-import 'package:file/src/backends/record_replay/codecs.dart';
-import 'package:file/src/backends/record_replay/common.dart' hide TypeMatcher;
-import 'package:file/src/backends/record_replay/events.dart';
-import 'package:file/src/backends/record_replay/mutable_recording.dart';
-import 'package:file/src/backends/record_replay/recording_proxy_mixin.dart';
-import 'package:file_testing/file_testing.dart';
-import 'package:path/path.dart' as p;
-import 'package:test/test.dart';
-
-import 'common_tests.dart';
-import 'record_replay_matchers.dart';
-
-void main() {
- group('SupportingCode', () {
- _BasicClass delegate;
- _RecordingClass rc;
- MutableRecording recording;
-
- setUp(() {
- delegate = _BasicClass();
- rc = _RecordingClass(
- delegate: delegate,
- stopwatch: _FakeStopwatch(10),
- destination: MemoryFileSystem().directory('/tmp')..createSync(),
- );
- recording = rc.recording;
- });
-
- group('InvocationEvent', () {
- test('recordsAllPropertyGetMetadata', () {
- delegate.basicProperty = 'foo';
- String value = rc.basicProperty;
- expect(recording.events, hasLength(1));
- expect(
- recording.events[0],
- getsProperty('basicProperty')
- .on(rc)
- .withResult(value)
- .withTimestamp(10));
- });
-
- test('recordsAllPropertySetMetadata', () {
- rc.basicProperty = 'foo';
- expect(recording.events, hasLength(1));
- expect(
- recording.events[0],
- setsProperty('basicProperty')
- .on(rc)
- .toValue('foo')
- .withTimestamp(10));
- });
-
- test('recordsAllMethodInvocationMetadata', () {
- String result = rc.basicMethod('foo', namedArg: 'bar');
- expect(recording.events, hasLength(1));
- expect(
- recording.events[0],
- invokesMethod('basicMethod')
- .on(rc)
- .withPositionalArguments(<String>['foo'])
- .withNamedArgument('namedArg', 'bar')
- .withResult(result)
- .withTimestamp(10));
- });
-
- test('resultIncompleteUntilFutureCompletes', () async {
- delegate.basicProperty = 'foo';
- rc.futureProperty; // ignore: unawaited_futures
- expect(recording.events, hasLength(1));
- expect(
- recording.events[0],
- getsProperty('futureProperty')
- .on(rc)
- .withResult(isNull)
- .withTimestamp(10));
- await recording.events[0].done;
- expect(
- recording.events[0],
- getsProperty('futureProperty')
- .on(rc)
- .withResult('future.foo')
- .withTimestamp(10));
- });
-
- test('resultIncompleteUntilStreamCompletes', () async {
- Stream<String> stream = rc.streamMethod('foo', namedArg: 'bar');
- stream.listen((_) {});
- expect(recording.events, hasLength(1));
- expect(
- recording.events[0],
- invokesMethod('streamMethod')
- .on(rc)
- .withPositionalArguments(<String>['foo'])
- .withNamedArgument('namedArg', 'bar')
- .withResult(allOf(isList, isEmpty))
- .withTimestamp(10));
- await recording.events[0].done;
- expect(
- recording.events[0],
- invokesMethod('streamMethod')
- .on(rc)
- .withPositionalArguments(<String>['foo'])
- .withNamedArgument('namedArg', 'bar')
- .withResult(<String>['stream', 'foo', 'bar'])
- .withTimestamp(10));
- });
- });
-
- group('MutableRecording', () {
- group('flush', () {
- test('writesManifestToFileSystemAsJson', () async {
- rc.basicProperty = 'foo';
- String value = rc.basicProperty;
- rc.basicMethod(value, namedArg: 'bar');
- await recording.flush();
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest, hasLength(3));
- expect(manifest[0], <String, dynamic>{
- 'type': 'set',
- 'property': 'basicProperty=',
- 'value': 'foo',
- 'object': '_RecordingClass',
- 'result': null,
- 'error': null,
- 'timestamp': 10,
- });
- expect(manifest[1], <String, dynamic>{
- 'type': 'get',
- 'property': 'basicProperty',
- 'object': '_RecordingClass',
- 'result': 'foo',
- 'error': null,
- 'timestamp': 11,
- });
- expect(manifest[2], <String, dynamic>{
- 'type': 'invoke',
- 'method': 'basicMethod',
- 'positionalArguments': <String>['foo'],
- 'namedArguments': <String, dynamic>{'namedArg': 'bar'},
- 'object': '_RecordingClass',
- 'result': 'foo.bar',
- 'error': null,
- 'timestamp': 12
- });
- });
-
- test('awaitsPendingResultsIndefinitelyByDefault', () async {
- rc.veryLongFutureMethod(); // ignore: unawaited_futures
- expect(recording.flush().timeout(const Duration(milliseconds: 50)),
- throwsA(const TypeMatcher<TimeoutException>()));
- });
-
- test('succeedsIfAwaitPendingResultsThatComplete', () async {
- rc.futureMethod('foo', namedArg: 'bar'); // ignore: unawaited_futures
- await recording.flush(
- pendingResultTimeout: const Duration(seconds: 30));
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest[0], containsPair('result', 'future.foo.bar'));
- });
-
- test('succeedsIfAwaitPendingResultsThatTimeout', () async {
- rc.veryLongFutureMethod(); // ignore: unawaited_futures
- DateTime before = DateTime.now();
- await recording.flush(
- pendingResultTimeout: const Duration(milliseconds: 250));
- DateTime after = DateTime.now();
- Duration delta = after.difference(before);
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest[0], containsPair('result', isNull));
- expect(delta.inMilliseconds, greaterThanOrEqualTo(250));
- });
-
- test('throwsIfAlreadyFlushing', () {
- rc.basicProperty = 'foo';
- recording.flush();
- expect(recording.flush(), throwsA(isStateError));
- });
- });
- });
-
- group('encode', () {
- test('performsDeepEncoding', () async {
- rc.basicProperty = 'foo';
- rc.basicProperty; // ignore: unnecessary_statements
- rc.basicMethod('bar', namedArg: 'baz');
- await rc.futureProperty;
- await rc.futureMethod('qux', namedArg: 'quz');
- await rc.streamMethod('quux', namedArg: 'quuz').drain<void>();
- List<Map<String, dynamic>> manifest =
- (await encode(recording.events) as List<dynamic>)
- .cast<Map<String, dynamic>>();
- expect(manifest[0], <String, dynamic>{
- 'type': 'set',
- 'property': 'basicProperty=',
- 'value': 'foo',
- 'object': '_RecordingClass',
- 'result': isNull,
- 'error': null,
- 'timestamp': 10,
- });
- expect(manifest[1], <String, dynamic>{
- 'type': 'get',
- 'property': 'basicProperty',
- 'object': '_RecordingClass',
- 'result': 'foo',
- 'error': null,
- 'timestamp': 11,
- });
- expect(manifest[2], <String, dynamic>{
- 'type': 'invoke',
- 'method': 'basicMethod',
- 'positionalArguments': <String>['bar'],
- 'namedArguments': <String, String>{'namedArg': 'baz'},
- 'object': '_RecordingClass',
- 'result': 'bar.baz',
- 'error': null,
- 'timestamp': 12,
- });
- expect(manifest[3], <String, dynamic>{
- 'type': 'get',
- 'property': 'futureProperty',
- 'object': '_RecordingClass',
- 'result': 'future.foo',
- 'error': null,
- 'timestamp': 13,
- });
- expect(manifest[4], <String, dynamic>{
- 'type': 'invoke',
- 'method': 'futureMethod',
- 'positionalArguments': <String>['qux'],
- 'namedArguments': <String, String>{'namedArg': 'quz'},
- 'object': '_RecordingClass',
- 'result': 'future.qux.quz',
- 'error': null,
- 'timestamp': 14,
- });
- expect(manifest[5], <String, dynamic>{
- 'type': 'invoke',
- 'method': 'streamMethod',
- 'positionalArguments': <String>['quux'],
- 'namedArguments': <String, String>{'namedArg': 'quuz'},
- 'object': '_RecordingClass',
- 'result': <String>['stream', 'quux', 'quuz'],
- 'error': null,
- 'timestamp': 15,
- });
- });
- });
-
- group('deeplyEqual', () {
- Map<String, dynamic> newMap({
- String stringValue = 'foo',
- bool boolValue = true,
- String lastListValue = 'c',
- int lastMapValue = 2,
- }) {
- return <String, dynamic>{
- 'string': stringValue,
- 'bool': boolValue,
- 'list': <String>['a', 'b', lastListValue],
- 'map': <Symbol, int>{
- #foo: 1,
- #bar: lastMapValue,
- },
- };
- }
-
- test('primitives', () {
- expect(deeplyEqual(1, 1), isTrue);
- expect(deeplyEqual(1, 2), isFalse);
- expect(deeplyEqual('1', '1'), isTrue);
- expect(deeplyEqual('1', '2'), isFalse);
- expect(deeplyEqual(true, true), isTrue);
- expect(deeplyEqual(true, false), isFalse);
- expect(deeplyEqual(null, null), isTrue);
- expect(deeplyEqual(1, '1'), isFalse);
- });
-
- test('listOfPrimitives', () {
- expect(deeplyEqual(<int>[], <int>[]), isTrue);
- expect(deeplyEqual(<int>[1, 2, 3], <int>[1, 2, 3]), isTrue);
- expect(deeplyEqual(<int>[1, 2, 3], <int>[1, 3, 2]), isFalse);
- expect(deeplyEqual(<int>[1, 2, 3], <int>[1, 2]), isFalse);
- expect(deeplyEqual(<int>[1, 2, 3], <int>[1, 2, 3, 4]), isFalse);
- expect(deeplyEqual(<String>['a', 'b'], <String>['a', 'b']), isTrue);
- expect(deeplyEqual(<String>['a', 'b'], <String>['b', 'a']), isFalse);
- expect(deeplyEqual(<String>['a', 'b'], <String>['a']), isFalse);
- expect(deeplyEqual(<int>[], <dynamic>[]), isFalse);
- expect(deeplyEqual(<int>[], null), isFalse);
- });
-
- test('mapOfPrimitives', () {
- expect(deeplyEqual(<String, int>{}, <String, int>{}), isTrue);
- expect(deeplyEqual(<int, int>{1: 2}, <int, int>{1: 2}), isTrue);
- expect(deeplyEqual(<int, int>{1: 2}, <int, int>{1: 3}), isFalse);
- expect(deeplyEqual(<int, int>{1: 2}, <int, int>{}), isFalse);
- expect(deeplyEqual(<int, int>{}, <int, int>{1: 2}), isFalse);
- expect(deeplyEqual(<String, int>{}, <int, int>{}), isFalse);
- expect(deeplyEqual(<String, int>{}, <dynamic, dynamic>{}), isFalse);
- expect(deeplyEqual(<String, int>{}, null), isFalse);
- });
-
- test('listOfMaps', () {
- expect(deeplyEqual(newMap(), newMap()), isTrue);
- expect(deeplyEqual(newMap(), newMap(stringValue: 'bar')), isFalse);
- expect(deeplyEqual(newMap(), newMap(boolValue: false)), isFalse);
- expect(deeplyEqual(newMap(), newMap(lastListValue: 'd')), isFalse);
- expect(deeplyEqual(newMap(), newMap(lastMapValue: 3)), isFalse);
- });
- });
- });
-
- group('RecordingFileSystem', () {
- RecordingFileSystem fs;
- MemoryFileSystem delegate;
- LiveRecording recording;
-
- setUp(() {
- delegate = MemoryFileSystem();
- fs = RecordingFileSystem(
- delegate: delegate,
- destination: MemoryFileSystem().directory('/tmp')..createSync(),
- );
- recording = fs.recording;
- });
-
- runCommonTests(() => fs);
-
- group('recording', () {
- test('supportsMultipleActions', () {
- fs.directory('/foo').createSync();
- fs.file('/foo/bar').writeAsStringSync('BAR');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(4));
- expect(events[0], invokesMethod('directory'));
- expect(events[1], invokesMethod('createSync'));
- expect(events[2], invokesMethod('file'));
- expect(events[3], invokesMethod('writeAsStringSync'));
- expect(events[0].result, events[1].object);
- expect(events[2].result, events[3].object);
- });
-
- group('FileSystem', () {
- test('directory', () {
- fs.directory('/foo');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('directory').on(fs).withPositionalArguments(
- <String>['/foo']).withResult(isDirectory),
- );
- });
-
- test('file', () {
- fs.file('/foo');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('file')
- .on(fs)
- .withPositionalArguments(<String>['/foo']).withResult(isFile),
- );
- });
-
- test('link', () {
- fs.link('/foo');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('link')
- .on(fs)
- .withPositionalArguments(<String>['/foo']).withResult(isLink),
- );
- });
-
- test('path', () {
- fs.path;
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- getsProperty('path')
- .on(fs)
- .withResult(const TypeMatcher<p.Context>()),
- );
- });
-
- test('systemTempDirectory', () {
- fs.systemTempDirectory;
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- getsProperty('systemTempDirectory')
- .on(fs)
- .withResult(isDirectory));
- });
-
- group('currentDirectory', () {
- test('get', () {
- fs.currentDirectory;
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- getsProperty('currentDirectory')
- .on(fs)
- .withResult(isDirectory));
- });
-
- test('setToString', () {
- delegate.directory('/foo').createSync();
- fs.currentDirectory = '/foo';
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(events[0],
- setsProperty('currentDirectory').on(fs).toValue('/foo'));
- });
-
- test('setToRecordingDirectory', () {
- delegate.directory('/foo').createSync();
- fs.currentDirectory = fs.directory('/foo');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events.length, greaterThanOrEqualTo(2));
- expect(events[0], invokesMethod().withResult(isDirectory));
- Directory directory = events[0].result as Directory;
- expect(
- events,
- contains(setsProperty('currentDirectory')
- .on(fs)
- .toValue(directory)));
- });
-
- test('setToNonRecordingDirectory', () {
- Directory dir = delegate.directory('/foo');
- dir.createSync();
- fs.currentDirectory = dir;
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(events[0],
- setsProperty('currentDirectory').on(fs).toValue(isDirectory));
- });
- });
-
- test('stat', () async {
- delegate.file('/foo').createSync();
- await fs.stat('/foo');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('stat').on(fs).withPositionalArguments(
- <String>['/foo']).withResult(isFileStat),
- );
- });
-
- test('statSync', () {
- delegate.file('/foo').createSync();
- fs.statSync('/foo');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('statSync').on(fs).withPositionalArguments(
- <String>['/foo']).withResult(isFileStat),
- );
- });
-
- test('identical', () async {
- delegate.file('/foo').createSync();
- delegate.file('/bar').createSync();
- await fs.identical('/foo', '/bar');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('identical').on(fs).withPositionalArguments(
- <String>['/foo', '/bar']).withResult(isFalse));
- });
-
- test('identicalSync', () {
- delegate.file('/foo').createSync();
- delegate.file('/bar').createSync();
- fs.identicalSync('/foo', '/bar');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('identicalSync').on(fs).withPositionalArguments(
- <String>['/foo', '/bar']).withResult(isFalse));
- });
-
- test('isWatchSupported', () {
- fs.isWatchSupported;
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(events[0],
- getsProperty('isWatchSupported').on(fs).withResult(isFalse));
- });
-
- test('type', () async {
- delegate.file('/foo').createSync();
- await fs.type('/foo');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('type').on(fs).withPositionalArguments(
- <String>['/foo']).withResult(FileSystemEntityType.file));
- });
-
- test('typeSync', () {
- delegate.file('/foo').createSync();
- fs.typeSync('/foo');
- List<InvocationEvent<dynamic>> events = recording.events;
- expect(events, hasLength(1));
- expect(
- events[0],
- invokesMethod('typeSync').on(fs).withPositionalArguments(
- <String>['/foo']).withResult(FileSystemEntityType.file));
- });
- });
-
- group('Directory', () {
- test('create', () async {
- await fs.directory('/foo').create();
- expect(
- recording.events,
- contains(invokesMethod('create')
- .on(isDirectory)
- .withNamedArgument('recursive', false)
- .withResult(isDirectory)));
- });
-
- test('createSync', () {
- fs.directory('/foo').createSync();
- expect(
- recording.events,
- contains(invokesMethod('createSync')
- .on(isDirectory)
- .withNamedArgument('recursive', false)
- .withResult(isNull)));
- });
-
- test('list', () async {
- await delegate.directory('/foo').create();
- await delegate.directory('/bar').create();
- await delegate.file('/baz').create();
- Stream<FileSystemEntity> stream = fs.directory('/').list();
- await stream.drain<void>();
- expect(
- recording.events,
- contains(invokesMethod('list')
- .on(isDirectory)
- .withNamedArgument('recursive', false)
- .withNamedArgument('followLinks', true)
- .withResult(hasLength(3))),
- );
- });
- });
-
- group('File', () {
- // TODO(tvolkert): Fill in these test stubs
- test('create', () {});
-
- test('createSync', () {});
-
- test('rename', () {});
-
- test('renameSync', () {});
-
- test('copy', () {});
-
- test('copySync', () {});
-
- test('length', () {});
-
- test('lengthSync', () {});
-
- test('absolute', () {});
-
- test('lastModified', () {});
-
- test('lastModifiedSync', () {});
-
- test('open', () {});
-
- test('openSync', () {});
-
- test('openRead', () async {
- String content = 'Hello\nWorld';
- await delegate.file('/foo').writeAsString(content, flush: true);
- Stream<List<int>> stream = fs.file('/foo').openRead();
- await stream.drain<void>();
- expect(
- recording.events,
- contains(invokesMethod('openRead')
- .on(isFile)
- .withPositionalArguments(<int>[null, null])
- .withNoNamedArguments()
- .withResult(isList)));
- await recording.flush();
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest, hasLength(2));
- expect(
- manifest[1],
- allOf(
- containsPair('type', 'invoke'),
- containsPair('method', 'openRead'),
- containsPair('object', matches(r'^RecordingFile@[0-9]+$')),
- containsPair('positionalArguments', <int>[null, null]),
- containsPair('namedArguments', isEmpty),
- containsPair('result', matches(r'^![0-9]+.foo$')),
- ));
- File file =
- _getRecordingFile(recording, manifest[1]['result'] as String);
- expect(file, exists);
- expect(await file.readAsString(), content);
- });
-
- test('openWrite', () {});
-
- test('readAsBytes', () async {
- String content = 'Hello\nWorld';
- await delegate.file('/foo').writeAsString(content, flush: true);
- await fs.file('/foo').readAsBytes();
- expect(
- recording.events,
- contains(invokesMethod('readAsBytes')
- .on(isFile)
- .withNoNamedArguments()
- .withResult(allOf(isList, hasLength(content.length)))));
- await recording.flush();
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest, hasLength(2));
- expect(
- manifest[1],
- allOf(
- containsPair('type', 'invoke'),
- containsPair('method', 'readAsBytes'),
- containsPair('object', matches(r'^RecordingFile@[0-9]+$')),
- containsPair('positionalArguments', isEmpty),
- containsPair('namedArguments', isEmpty),
- containsPair('result', matches(r'^![0-9]+.foo$')),
- ));
- File file =
- _getRecordingFile(recording, manifest[1]['result'] as String);
- expect(file, exists);
- expect(await file.readAsString(), content);
- });
-
- test('readAsBytesSync', () async {
- String content = 'Hello\nWorld';
- await delegate.file('/foo').writeAsString(content, flush: true);
- fs.file('/foo').readAsBytesSync();
- expect(
- recording.events,
- contains(invokesMethod('readAsBytesSync')
- .on(isFile)
- .withNoNamedArguments()
- .withResult(allOf(isList, hasLength(content.length)))));
- await recording.flush();
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest, hasLength(2));
- expect(
- manifest[1],
- allOf(
- containsPair('type', 'invoke'),
- containsPair('method', 'readAsBytesSync'),
- containsPair('object', matches(r'^RecordingFile@[0-9]+$')),
- containsPair('positionalArguments', isEmpty),
- containsPair('namedArguments', isEmpty),
- containsPair('result', matches(r'^![0-9]+.foo$')),
- ));
- File file =
- _getRecordingFile(recording, manifest[1]['result'] as String);
- expect(file, exists);
- expect(await file.readAsString(), content);
- });
-
- test('readAsString', () async {
- String content = 'Hello\nWorld';
- await delegate
- .file('/foo')
- .writeAsString(content, encoding: latin1, flush: true);
- await fs.file('/foo').readAsString(encoding: latin1);
- expect(
- recording.events,
- contains(invokesMethod('readAsString')
- .on(isFile)
- .withNamedArgument('encoding', latin1)
- .withResult(content)));
- await recording.flush();
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest, hasLength(2));
- expect(
- manifest[1],
- allOf(
- containsPair('type', 'invoke'),
- containsPair('method', 'readAsString'),
- containsPair('object', matches(r'^RecordingFile@[0-9]+$')),
- containsPair('positionalArguments', isEmpty),
- containsPair('result', matches(r'^![0-9]+.foo$')),
- containsPair(
- 'namedArguments',
- allOf(
- hasLength(1),
- containsPair('encoding', 'iso-8859-1'),
- )),
- ));
- File file =
- _getRecordingFile(recording, manifest[1]['result'] as String);
- expect(file, exists);
- expect(await file.readAsString(), content);
- });
-
- test('readAsStringSync', () async {
- String content = 'Hello\nWorld';
- await delegate
- .file('/foo')
- .writeAsString(content, encoding: latin1, flush: true);
- fs.file('/foo').readAsStringSync(encoding: latin1);
- expect(
- recording.events,
- contains(invokesMethod('readAsStringSync')
- .on(isFile)
- .withNamedArgument('encoding', latin1)
- .withResult(content)));
- await recording.flush();
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest, hasLength(2));
- expect(
- manifest[1],
- allOf(
- containsPair('type', 'invoke'),
- containsPair('method', 'readAsStringSync'),
- containsPair('object', matches(r'^RecordingFile@[0-9]+$')),
- containsPair('positionalArguments', isEmpty),
- containsPair('result', matches(r'^![0-9]+.foo$')),
- containsPair(
- 'namedArguments',
- allOf(
- hasLength(1),
- containsPair('encoding', 'iso-8859-1'),
- )),
- ));
- File file =
- _getRecordingFile(recording, manifest[1]['result'] as String);
- expect(file, exists);
- expect(await file.readAsString(), content);
- });
-
- test('readAsLines', () async {
- // [readAsLines] is appropriate only for text files, and POSIX
- // requires that valid text files end with a terminating newline.
- String content = 'Hello\nWorld\n';
- await delegate.file('/foo').writeAsString(content, flush: true);
- await fs.file('/foo').readAsLines();
- expect(
- recording.events,
- contains(invokesMethod('readAsLines')
- .on(isFile)
- .withNamedArgument('encoding', utf8)
- .withResult(<String>['Hello', 'World'])));
- await recording.flush();
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest, hasLength(2));
- expect(
- manifest[1],
- allOf(
- containsPair('type', 'invoke'),
- containsPair('method', 'readAsLines'),
- containsPair('object', matches(r'^RecordingFile@[0-9]+$')),
- containsPair('positionalArguments', isEmpty),
- containsPair('result', matches(r'^![0-9]+.foo$')),
- containsPair(
- 'namedArguments', <String, String>{'encoding': 'utf-8'}),
- ));
- File file =
- _getRecordingFile(recording, manifest[1]['result'] as String);
- expect(file, exists);
- expect(await file.readAsString(), content);
- });
-
- test('readAsLinesSync', () async {
- // [readAsLinesSync] is appropriate only for text files, and POSIX
- // requires that valid text files end with a terminating newline.
- String content = 'Hello\nWorld\n';
- await delegate.file('/foo').writeAsString(content, flush: true);
- fs.file('/foo').readAsLinesSync();
- expect(
- recording.events,
- contains(invokesMethod('readAsLinesSync')
- .on(isFile)
- .withNamedArgument('encoding', utf8)
- .withResult(<String>['Hello', 'World'])));
- await recording.flush();
- List<Map<String, dynamic>> manifest = _loadManifest(recording);
- expect(manifest, hasLength(2));
- expect(
- manifest[1],
- allOf(
- containsPair('type', 'invoke'),
- containsPair('method', 'readAsLinesSync'),
- containsPair('object', matches(r'^RecordingFile@[0-9]+$')),
- containsPair('positionalArguments', isEmpty),
- containsPair('result', matches(r'^![0-9]+.foo$')),
- containsPair(
- 'namedArguments', <String, String>{'encoding': 'utf-8'}),
- ));
- File file =
- _getRecordingFile(recording, manifest[1]['result'] as String);
- expect(file, exists);
- expect(await file.readAsString(), content);
- });
-
- test('writeAsBytes', () {});
-
- test('writeAsBytesSync', () {});
-
- test('writeAsString', () {});
-
- test('writeAsStringSync', () {});
- });
-
- group('Link', () {});
- });
- });
-}
-
-List<Map<String, dynamic>> _loadManifest(LiveRecording recording) {
- List<FileSystemEntity> files = recording.destination.listSync();
- File manifestFile = files.singleWhere(
- (FileSystemEntity entity) => entity.basename == kManifestName) as File;
- return (const JsonDecoder().convert(manifestFile.readAsStringSync())
- as List<dynamic>)
- .cast<Map<String, dynamic>>();
-}
-
-File _getRecordingFile(LiveRecording recording, String manifestReference) {
- expect(manifestReference, startsWith('!'));
- String basename = manifestReference.substring(1);
- String dirname = recording.destination.path;
- String path = recording.destination.fileSystem.path.join(dirname, basename);
- return recording.destination.fileSystem.file(path);
-}
-
-class _BasicClass {
- String basicProperty;
-
- Future<String> get futureProperty async => 'future.$basicProperty';
-
- String basicMethod(String positionalArg, {String namedArg}) =>
- '$positionalArg.$namedArg';
-
- Future<String> futureMethod(String positionalArg, {String namedArg}) async {
- await Future<void>.delayed(const Duration(milliseconds: 500));
- String basicValue = basicMethod(positionalArg, namedArg: namedArg);
- return 'future.$basicValue';
- }
-
- Stream<String> streamMethod(String positionalArg, {String namedArg}) async* {
- yield 'stream';
- yield positionalArg;
- yield namedArg;
- }
-
- Future<String> veryLongFutureMethod() async {
- await Future<void>.delayed(const Duration(seconds: 1));
- return 'future';
- }
-
- Stream<String> infiniteStreamMethod() async* {
- yield 'stream';
- int i = 0;
- while (i >= 0) {
- yield '${i++}';
- await Future<void>.delayed(const Duration(seconds: 1));
- }
- }
-}
-
-class _RecordingClass extends Object
- with RecordingProxyMixin
- implements _BasicClass {
- _RecordingClass({
- this.delegate,
- this.stopwatch,
- Directory destination,
- }) : recording = MutableRecording(destination) {
- methods.addAll(<Symbol, Function>{
- #basicMethod: delegate.basicMethod,
- #futureMethod: delegate.futureMethod,
- #streamMethod: delegate.streamMethod,
- #veryLongFutureMethod: delegate.veryLongFutureMethod,
- #infiniteStreamMethod: delegate.infiniteStreamMethod,
- });
-
- properties.addAll(<Symbol, Function>{
- #basicProperty: () => delegate.basicProperty,
- const Symbol('basicProperty='): (String value) {
- delegate.basicProperty = value;
- },
- #futureProperty: () => delegate.futureProperty,
- });
- }
-
- final _BasicClass delegate;
-
- @override
- String get identifier => '$runtimeType';
-
- @override
- final MutableRecording recording;
-
- @override
- final Stopwatch stopwatch;
-}
-
-class _FakeStopwatch implements Stopwatch {
- _FakeStopwatch(this._value);
-
- int _value;
-
- @override
- int get elapsedMilliseconds => _value++;
-
- @override
- dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
-}
diff --git a/packages/file/test/replay_test.dart b/packages/file/test/replay_test.dart
deleted file mode 100644
index 192d161..0000000
--- a/packages/file/test/replay_test.dart
+++ /dev/null
@@ -1,259 +0,0 @@
-// Copyright (c) 2017, 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.
-
-import 'dart:async';
-
-import 'package:file/file.dart';
-import 'package:file/memory.dart';
-import 'package:file/record_replay.dart';
-import 'package:file/src/backends/record_replay/common.dart'
- show describeInvocation;
-import 'package:file_testing/file_testing.dart';
-import 'package:path/path.dart' as path;
-import 'package:test/test.dart';
-
-import 'common_tests.dart';
-import 'record_replay_matchers.dart';
-
-void main() {
- group('Replay', () {
- RecordingFileSystem recordingFileSystem;
- MemoryFileSystem memoryFileSystem;
- LiveRecording recording;
-
- setUp(() {
- memoryFileSystem = MemoryFileSystem();
- recordingFileSystem = RecordingFileSystem(
- delegate: memoryFileSystem,
- destination: MemoryFileSystem().directory('/tmp')..createSync(),
- );
- recording = recordingFileSystem.recording;
- });
-
- /// Creates a new [ReplayFileSystem] that will replay a recording of the
- /// events that have been recorded within [recordingFileSystem] thus far.
- Future<ReplayFileSystem> replay() async {
- await recording.flush();
- return ReplayFileSystem(recording: recording.destination);
- }
-
- runCommonTests(
- () => recordingFileSystem,
- replay: replay,
- skip: <String>[
- // ReplayFileSystem does not yet support futures & streams that throw
- 'File > openRead > throws.*',
- 'File > openWrite > throws.*',
- 'File > openWrite > ioSink > throwsIfAddError',
- 'File > openWrite > ioSink > addStream > blocks.*',
- 'File > openWrite > ioSink > ignoresDataWrittenAfterClose',
-
- // TODO(jamesderlin): ReplayFileSystem does not yet support functions
- // that mutate arguments, and error-checking for async functions is not
- // implemented (https://github.com/google/file.dart/issues/144)
- 'File > open .* RandomAccessFile .* readInto.*',
- 'File > open .* RandomAccessFile .* throwsIfAsyncUnawaited',
- ],
- );
-
- group('ReplayFileSystem', () {
- test('directory', () async {
- recordingFileSystem.directory('/foo');
- ReplayFileSystem fs = await replay();
- Directory dir = fs.directory('/foo');
- expect(dir, isDirectory);
- expect(() => dir.path, throwsNoMatchingInvocationError);
- expect(() => fs.directory('/foo'), throwsNoMatchingInvocationError);
- });
-
- test('file', () async {
- recordingFileSystem.file('/foo');
- ReplayFileSystem fs = await replay();
- expect(fs.file('/foo'), isFile);
- expect(() => fs.file('/foo'), throwsNoMatchingInvocationError);
- });
-
- test('link', () async {
- recordingFileSystem.link('/foo');
- ReplayFileSystem fs = await replay();
- expect(fs.link('/foo'), isLink);
- expect(() => fs.link('/foo'), throwsNoMatchingInvocationError);
- });
-
- test('path', () async {
- path.Context context = recordingFileSystem.path;
- ReplayFileSystem fs = await replay();
- path.Context replayContext = fs.path;
- expect(() => fs.path, throwsNoMatchingInvocationError);
- expect(replayContext.style, context.style);
- expect(replayContext.current, context.current);
- });
-
- test('systemTempDirectory', () async {
- recordingFileSystem.systemTempDirectory;
- ReplayFileSystem fs = await replay();
- Directory dir = fs.systemTempDirectory;
- expect(dir, isDirectory);
- expect(() => dir.path, throwsNoMatchingInvocationError);
- expect(() => fs.systemTempDirectory, throwsNoMatchingInvocationError);
- });
-
- group('currentDirectory', () {
- test('get', () async {
- recordingFileSystem.currentDirectory;
- ReplayFileSystem fs = await replay();
- Directory dir = fs.currentDirectory;
- expect(dir, isDirectory);
- expect(() => dir.path, throwsNoMatchingInvocationError);
- expect(() => fs.currentDirectory, throwsNoMatchingInvocationError);
- });
-
- test('setToString', () async {
- memoryFileSystem.directory('/foo').createSync();
- recordingFileSystem.currentDirectory = '/foo';
- ReplayFileSystem fs = await replay();
- expect(() => fs.currentDirectory = '/bar',
- throwsNoMatchingInvocationError);
- fs.currentDirectory = '/foo';
- expect(() => fs.currentDirectory = '/foo',
- throwsNoMatchingInvocationError);
- });
-
- test('setToDirectory', () async {
- Directory dir = await recordingFileSystem.directory('/foo').create();
- recordingFileSystem.currentDirectory = dir;
- ReplayFileSystem fs = await replay();
- Directory replayDir = fs.directory('/foo');
- expect(() => fs.directory('/foo'), throwsNoMatchingInvocationError);
- fs.currentDirectory = replayDir;
- expect(() => fs.currentDirectory = replayDir,
- throwsNoMatchingInvocationError);
- });
- });
-
- test('stat', () async {
- FileStat stat = await recordingFileSystem.stat('/');
- ReplayFileSystem fs = await replay();
- Future<FileStat> replayStatFuture = fs.stat('/');
- expect(() => fs.stat('/'), throwsNoMatchingInvocationError);
- expect(replayStatFuture, isFuture);
- FileStat replayStat = await replayStatFuture;
- expect(replayStat.accessed, stat.accessed);
- expect(replayStat.changed, stat.changed);
- expect(replayStat.modified, stat.modified);
- expect(replayStat.mode, stat.mode);
- expect(replayStat.type, stat.type);
- expect(replayStat.size, stat.size);
- expect(replayStat.modeString(), stat.modeString());
- });
-
- test('statSync', () async {
- FileStat stat = recordingFileSystem.statSync('/');
- ReplayFileSystem fs = await replay();
- FileStat replayStat = fs.statSync('/');
- expect(() => fs.statSync('/'), throwsNoMatchingInvocationError);
- expect(replayStat.accessed, stat.accessed);
- expect(replayStat.changed, stat.changed);
- expect(replayStat.modified, stat.modified);
- expect(replayStat.mode, stat.mode);
- expect(replayStat.type, stat.type);
- expect(replayStat.size, stat.size);
- expect(replayStat.modeString(), stat.modeString());
- });
-
- test('identical', () async {
- memoryFileSystem.directory('/foo').createSync();
- bool identical = await recordingFileSystem.identical('/', '/foo');
- ReplayFileSystem fs = await replay();
- Future<bool> replayIdenticalFuture = fs.identical('/', '/foo');
- expect(
- () => fs.identical('/', '/foo'), throwsNoMatchingInvocationError);
- expect(replayIdenticalFuture, isFuture);
- expect(await replayIdenticalFuture, identical);
- });
-
- test('identicalSync', () async {
- memoryFileSystem.directory('/foo').createSync();
- bool identical = recordingFileSystem.identicalSync('/', '/foo');
- ReplayFileSystem fs = await replay();
- bool replayIdentical = fs.identicalSync('/', '/foo');
- expect(() => fs.identicalSync('/', '/foo'),
- throwsNoMatchingInvocationError);
- expect(replayIdentical, identical);
- });
-
- test('isWatchSupported', () async {
- bool isWatchSupported = recordingFileSystem.isWatchSupported;
- ReplayFileSystem fs = await replay();
- expect(fs.isWatchSupported, isWatchSupported);
- expect(() => fs.isWatchSupported, throwsNoMatchingInvocationError);
- });
-
- test('type', () async {
- FileSystemEntityType type = await recordingFileSystem.type('/');
- ReplayFileSystem fs = await replay();
- Future<FileSystemEntityType> replayTypeFuture = fs.type('/');
- expect(() => fs.type('/'), throwsNoMatchingInvocationError);
- expect(replayTypeFuture, isFuture);
- expect(await replayTypeFuture, type);
- });
-
- test('typeSync', () async {
- FileSystemEntityType type = recordingFileSystem.typeSync('/');
- ReplayFileSystem fs = await replay();
- FileSystemEntityType replayType = fs.typeSync('/');
- expect(() => fs.typeSync('/'), throwsNoMatchingInvocationError);
- expect(replayType, type);
- });
- });
- });
-
- group('describeInvocation', () {
- test('methodWithNoArguments', () {
- expect(
- describeInvocation(Invocation.method(#foo, <Object>[])),
- 'foo()',
- );
- });
-
- test('methodWithOnlyPositionalArguments', () {
- expect(
- describeInvocation(Invocation.method(#foo, <Object>[1, 'bar', null])),
- 'foo(1, "bar", null)',
- );
- });
-
- test('methodWithOnlyNamedArguments', () {
- expect(
- describeInvocation(Invocation.method(
- #foo,
- <Object>[],
- <Symbol, Object>{#x: 2, #y: 'baz', #z: null},
- )),
- 'foo(x: 2, y: "baz", z: null)',
- );
- });
-
- test('methodWithPositionalAndNamedArguments', () {
- expect(
- describeInvocation(Invocation.method(
- #foo,
- <Object>[1, 'bar', null],
- <Symbol, Object>{#x: 2, #y: 'baz', #z: null},
- )),
- 'foo(1, "bar", null, x: 2, y: "baz", z: null)',
- );
- });
-
- test('setter', () {
- expect(
- describeInvocation(Invocation.setter(#property, 'value')),
- 'property = "value"',
- );
- });
- });
-}
-
-/// Successfully matches against an instance of [Future].
-const Matcher isFuture = TypeMatcher<Future<dynamic>>();