|  | // 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. | 
|  |  | 
|  | part of dart.io; | 
|  |  | 
|  | final _ioOverridesToken = new Object(); | 
|  |  | 
|  | const _asyncRunZoned = runZoned; | 
|  |  | 
|  | /// Facilities for overriding various APIs of `dart:io` with mock | 
|  | /// implementations. | 
|  | /// | 
|  | /// This abstract base class should be extended with overrides for the | 
|  | /// operations needed to construct mocks. The implementations in this base class | 
|  | /// default to the actual `dart:io` implementation. For example: | 
|  | /// | 
|  | /// ```dart | 
|  | /// class MyDirectory implements Directory { | 
|  | ///   ... | 
|  | ///   // An implementation of the Directory interface | 
|  | ///   ... | 
|  | /// } | 
|  | /// | 
|  | /// void main() { | 
|  | ///   IOOverrides.runZoned(() { | 
|  | ///     ... | 
|  | ///     // Operations will use MyDirectory instead of dart:io's Directory | 
|  | ///     // implementation whenever Directory is used. | 
|  | ///     ... | 
|  | ///   }, createDirectory: (String path) => new MyDirectory(path)); | 
|  | /// } | 
|  | /// ``` | 
|  | abstract class IOOverrides { | 
|  | static IOOverrides? _global; | 
|  |  | 
|  | static IOOverrides? get current { | 
|  | return Zone.current[_ioOverridesToken] ?? _global; | 
|  | } | 
|  |  | 
|  | /// The [IOOverrides] to use in the root [Zone]. | 
|  | /// | 
|  | /// These are the [IOOverrides] that will be used in the root [Zone], and in | 
|  | /// [Zone]'s that do not set [IOOverrides] and whose ancestors up to the root | 
|  | /// [Zone] also do not set [IOOverrides]. | 
|  | static set global(IOOverrides? overrides) { | 
|  | _global = overrides; | 
|  | } | 
|  |  | 
|  | /// Runs [body] in a fresh [Zone] using the provided overrides. | 
|  | /// | 
|  | /// See the documentation on the corresponding methods of [IOOverrides] for | 
|  | /// information about what the optional arguments do. | 
|  | static R runZoned<R>(R body(), | 
|  | { | 
|  | // Directory | 
|  | Directory Function(String)? createDirectory, | 
|  | Directory Function()? getCurrentDirectory, | 
|  | void Function(String)? setCurrentDirectory, | 
|  | Directory Function()? getSystemTempDirectory, | 
|  |  | 
|  | // File | 
|  | File Function(String)? createFile, | 
|  |  | 
|  | // FileStat | 
|  | Future<FileStat> Function(String)? stat, | 
|  | FileStat Function(String)? statSync, | 
|  |  | 
|  | // FileSystemEntity | 
|  | Future<bool> Function(String, String)? fseIdentical, | 
|  | bool Function(String, String)? fseIdenticalSync, | 
|  | Future<FileSystemEntityType> Function(String, bool)? fseGetType, | 
|  | FileSystemEntityType Function(String, bool)? fseGetTypeSync, | 
|  |  | 
|  | // _FileSystemWatcher | 
|  | Stream<FileSystemEvent> Function(String, int, bool)? fsWatch, | 
|  | bool Function()? fsWatchIsSupported, | 
|  |  | 
|  | // Link | 
|  | Link Function(String)? createLink, | 
|  |  | 
|  | // Socket | 
|  | Future<Socket> Function(dynamic, int, | 
|  | {dynamic sourceAddress, Duration? timeout})? | 
|  | socketConnect, | 
|  | Future<ConnectionTask<Socket>> Function(dynamic, int, | 
|  | {dynamic sourceAddress})? | 
|  | socketStartConnect, | 
|  |  | 
|  | // ServerSocket | 
|  | Future<ServerSocket> Function(dynamic, int, | 
|  | {int backlog, bool v6Only, bool shared})? | 
|  | serverSocketBind, | 
|  |  | 
|  | // Standard Streams | 
|  | Stdin Function()? stdin, | 
|  | Stdout Function()? stdout, | 
|  | Stdout Function()? stderr}) { | 
|  | IOOverrides overrides = new _IOOverridesScope( | 
|  | // Directory | 
|  | createDirectory, | 
|  | getCurrentDirectory, | 
|  | setCurrentDirectory, | 
|  | getSystemTempDirectory, | 
|  |  | 
|  | // File | 
|  | createFile, | 
|  |  | 
|  | // FileStat | 
|  | stat, | 
|  | statSync, | 
|  |  | 
|  | // FileSystemEntity | 
|  | fseIdentical, | 
|  | fseIdenticalSync, | 
|  | fseGetType, | 
|  | fseGetTypeSync, | 
|  |  | 
|  | // _FileSystemWatcher | 
|  | fsWatch, | 
|  | fsWatchIsSupported, | 
|  |  | 
|  | // Link | 
|  | createLink, | 
|  |  | 
|  | // Socket | 
|  | socketConnect, | 
|  | socketStartConnect, | 
|  |  | 
|  | // ServerSocket | 
|  | serverSocketBind, | 
|  |  | 
|  | // Standard streams | 
|  | stdin, | 
|  | stdout, | 
|  | stderr, | 
|  | ); | 
|  | return _asyncRunZoned<R>(body, zoneValues: {_ioOverridesToken: overrides}); | 
|  | } | 
|  |  | 
|  | /// Runs [body] in a fresh [Zone] using the overrides found in [overrides]. | 
|  | /// | 
|  | /// Note that [overrides] should be an instance of a class that extends | 
|  | /// [IOOverrides]. | 
|  | static R runWithIOOverrides<R>(R body(), IOOverrides overrides) { | 
|  | return _asyncRunZoned<R>(body, zoneValues: {_ioOverridesToken: overrides}); | 
|  | } | 
|  |  | 
|  | // Directory | 
|  |  | 
|  | /// Creates a new [Directory] object for the given [path]. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `new Directory()` and `new Directory.fromUri()`. | 
|  | Directory createDirectory(String path) => new _Directory(path); | 
|  |  | 
|  | /// Returns the current working directory. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// the static getter `Directory.current` | 
|  | Directory getCurrentDirectory() => _Directory.current; | 
|  |  | 
|  | /// Sets the current working directory to be [path]. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// the setter `Directory.current`. | 
|  | void setCurrentDirectory(String path) { | 
|  | _Directory.current = path; | 
|  | } | 
|  |  | 
|  | /// Returns the system temporary directory. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `Directory.systemTemp`. | 
|  | Directory getSystemTempDirectory() => _Directory.systemTemp; | 
|  |  | 
|  | // File | 
|  |  | 
|  | /// Creates a new [File] object for the given [path]. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `new File()` and `new File.fromUri()`. | 
|  | File createFile(String path) => new _File(path); | 
|  |  | 
|  | // FileStat | 
|  |  | 
|  | /// Asynchronously returns [FileStat] information for [path]. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `FileStat.stat()`. | 
|  | Future<FileStat> stat(String path) { | 
|  | return FileStat._stat(path); | 
|  | } | 
|  |  | 
|  | /// Returns [FileStat] information for [path]. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `FileStat.statSync()`. | 
|  | FileStat statSync(String path) { | 
|  | return FileStat._statSyncInternal(path); | 
|  | } | 
|  |  | 
|  | // FileSystemEntity | 
|  |  | 
|  | /// Asynchronously returns `true` if [path1] and [path2] are paths to the | 
|  | /// same file system object. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `FileSystemEntity.identical`. | 
|  | Future<bool> fseIdentical(String path1, String path2) { | 
|  | return FileSystemEntity._identical(path1, path2); | 
|  | } | 
|  |  | 
|  | /// Returns `true` if [path1] and [path2] are paths to the | 
|  | /// same file system object. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `FileSystemEntity.identicalSync`. | 
|  | bool fseIdenticalSync(String path1, String path2) { | 
|  | return FileSystemEntity._identicalSync(path1, path2); | 
|  | } | 
|  |  | 
|  | /// Asynchronously returns the [FileSystemEntityType] for [path]. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `FileSystemEntity.type`. | 
|  | Future<FileSystemEntityType> fseGetType(String path, bool followLinks) { | 
|  | return FileSystemEntity._getTypeRequest( | 
|  | utf8.encoder.convert(path), followLinks); | 
|  | } | 
|  |  | 
|  | /// Returns the [FileSystemEntityType] for [path]. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `FileSystemEntity.typeSync`. | 
|  | FileSystemEntityType fseGetTypeSync(String path, bool followLinks) { | 
|  | return FileSystemEntity._getTypeSyncHelper( | 
|  | utf8.encoder.convert(path), followLinks); | 
|  | } | 
|  |  | 
|  | // _FileSystemWatcher | 
|  |  | 
|  | /// Returns a [Stream] of [FileSystemEvent]s. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `FileSystemEntity.watch()`. | 
|  | Stream<FileSystemEvent> fsWatch(String path, int events, bool recursive) { | 
|  | return _FileSystemWatcher._watch(path, events, recursive); | 
|  | } | 
|  |  | 
|  | /// Returns `true` when [FileSystemEntity.watch] is supported. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `FileSystemEntity.isWatchSupported`. | 
|  | bool fsWatchIsSupported() => _FileSystemWatcher.isSupported; | 
|  |  | 
|  | // Link | 
|  |  | 
|  | /// Returns a new [Link] object for the given [path]. | 
|  | /// | 
|  | /// When this override is installed, this function overrides the behavior of | 
|  | /// `new Link()` and `new Link.fromUri()`. | 
|  | Link createLink(String path) => new _Link(path); | 
|  |  | 
|  | // Socket | 
|  |  | 
|  | /// Asynchronously returns a [Socket] connected to the given host and port. | 
|  | /// | 
|  | /// When this override is installed, this functions overrides the behavior of | 
|  | /// `Socket.connect(...)`. | 
|  | Future<Socket> socketConnect(host, int port, | 
|  | {sourceAddress, Duration? timeout}) { | 
|  | return Socket._connect(host, port, | 
|  | sourceAddress: sourceAddress, timeout: timeout); | 
|  | } | 
|  |  | 
|  | /// Asynchronously returns a [ConnectionTask] that connects to the given host | 
|  | /// and port when successful. | 
|  | /// | 
|  | /// When this override is installed, this functions overrides the behavior of | 
|  | /// `Socket.startConnect(...)`. | 
|  | Future<ConnectionTask<Socket>> socketStartConnect(host, int port, | 
|  | {sourceAddress}) { | 
|  | return Socket._startConnect(host, port, sourceAddress: sourceAddress); | 
|  | } | 
|  |  | 
|  | // ServerSocket | 
|  |  | 
|  | /// Asynchronously returns a [ServerSocket] that connects to the given address | 
|  | /// and port when successful. | 
|  | /// | 
|  | /// When this override is installed, this functions overrides the behavior of | 
|  | /// `ServerSocket.bind(...)`. | 
|  | Future<ServerSocket> serverSocketBind(address, int port, | 
|  | {int backlog = 0, bool v6Only = false, bool shared = false}) { | 
|  | return ServerSocket._bind(address, port, | 
|  | backlog: backlog, v6Only: v6Only, shared: shared); | 
|  | } | 
|  |  | 
|  | // Standard streams | 
|  |  | 
|  | /// The standard input stream of data read by this program. | 
|  | /// | 
|  | /// When this override is installed, this getter overrides the behavior of | 
|  | /// the top-level `stdin` getter. | 
|  | Stdin get stdin { | 
|  | return _stdin; | 
|  | } | 
|  |  | 
|  | /// The standard output stream of data written by this program. | 
|  | /// | 
|  | /// When this override is installed, this getter overrides the behavior of | 
|  | /// the top-level `stdout` getter. | 
|  | Stdout get stdout { | 
|  | return _stdout; | 
|  | } | 
|  |  | 
|  | /// The standard output stream of errors written by this program. | 
|  | /// | 
|  | /// When this override is installed, this getter overrides the behavior of | 
|  | /// the top-level `stderr` getter. | 
|  | Stdout get stderr { | 
|  | return _stderr; | 
|  | } | 
|  | } | 
|  |  | 
|  | class _IOOverridesScope extends IOOverrides { | 
|  | final IOOverrides? _previous = IOOverrides.current; | 
|  |  | 
|  | // Directory | 
|  | Directory Function(String)? _createDirectory; | 
|  | Directory Function()? _getCurrentDirectory; | 
|  | void Function(String)? _setCurrentDirectory; | 
|  | Directory Function()? _getSystemTempDirectory; | 
|  |  | 
|  | // File | 
|  | File Function(String)? _createFile; | 
|  |  | 
|  | // FileStat | 
|  | Future<FileStat> Function(String)? _stat; | 
|  | FileStat Function(String)? _statSync; | 
|  |  | 
|  | // FileSystemEntity | 
|  | Future<bool> Function(String, String)? _fseIdentical; | 
|  | bool Function(String, String)? _fseIdenticalSync; | 
|  | Future<FileSystemEntityType> Function(String, bool)? _fseGetType; | 
|  | FileSystemEntityType Function(String, bool)? _fseGetTypeSync; | 
|  |  | 
|  | // _FileSystemWatcher | 
|  | Stream<FileSystemEvent> Function(String, int, bool)? _fsWatch; | 
|  | bool Function()? _fsWatchIsSupported; | 
|  |  | 
|  | // Link | 
|  | Link Function(String)? _createLink; | 
|  |  | 
|  | // Socket | 
|  | Future<Socket> Function(dynamic, int, | 
|  | {dynamic sourceAddress, Duration? timeout})? _socketConnect; | 
|  | Future<ConnectionTask<Socket>> Function(dynamic, int, | 
|  | {dynamic sourceAddress})? _socketStartConnect; | 
|  |  | 
|  | // ServerSocket | 
|  | Future<ServerSocket> Function(dynamic, int, | 
|  | {int backlog, bool v6Only, bool shared})? _serverSocketBind; | 
|  |  | 
|  | // Standard streams | 
|  | Stdin Function()? _stdin; | 
|  | Stdout Function()? _stdout; | 
|  | Stdout Function()? _stderr; | 
|  |  | 
|  | _IOOverridesScope( | 
|  | // Directory | 
|  | this._createDirectory, | 
|  | this._getCurrentDirectory, | 
|  | this._setCurrentDirectory, | 
|  | this._getSystemTempDirectory, | 
|  |  | 
|  | // File | 
|  | this._createFile, | 
|  |  | 
|  | // FileStat | 
|  | this._stat, | 
|  | this._statSync, | 
|  |  | 
|  | // FileSystemEntity | 
|  | this._fseIdentical, | 
|  | this._fseIdenticalSync, | 
|  | this._fseGetType, | 
|  | this._fseGetTypeSync, | 
|  |  | 
|  | // _FileSystemWatcher | 
|  | this._fsWatch, | 
|  | this._fsWatchIsSupported, | 
|  |  | 
|  | // Link | 
|  | this._createLink, | 
|  |  | 
|  | // Socket | 
|  | this._socketConnect, | 
|  | this._socketStartConnect, | 
|  |  | 
|  | // ServerSocket | 
|  | this._serverSocketBind, | 
|  |  | 
|  | // Standard streams | 
|  | this._stdin, | 
|  | this._stdout, | 
|  | this._stderr, | 
|  | ); | 
|  |  | 
|  | // Directory | 
|  | @override | 
|  | Directory createDirectory(String path) { | 
|  | if (_createDirectory != null) return _createDirectory!(path); | 
|  | if (_previous != null) return _previous!.createDirectory(path); | 
|  | return super.createDirectory(path); | 
|  | } | 
|  |  | 
|  | @override | 
|  | Directory getCurrentDirectory() { | 
|  | if (_getCurrentDirectory != null) return _getCurrentDirectory!(); | 
|  | if (_previous != null) return _previous!.getCurrentDirectory(); | 
|  | return super.getCurrentDirectory(); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void setCurrentDirectory(String path) { | 
|  | if (_setCurrentDirectory != null) | 
|  | _setCurrentDirectory!(path); | 
|  | else if (_previous != null) | 
|  | _previous!.setCurrentDirectory(path); | 
|  | else | 
|  | super.setCurrentDirectory(path); | 
|  | } | 
|  |  | 
|  | @override | 
|  | Directory getSystemTempDirectory() { | 
|  | if (_getSystemTempDirectory != null) return _getSystemTempDirectory!(); | 
|  | if (_previous != null) return _previous!.getSystemTempDirectory(); | 
|  | return super.getSystemTempDirectory(); | 
|  | } | 
|  |  | 
|  | // File | 
|  | @override | 
|  | File createFile(String path) { | 
|  | if (_createFile != null) return _createFile!(path); | 
|  | if (_previous != null) return _previous!.createFile(path); | 
|  | return super.createFile(path); | 
|  | } | 
|  |  | 
|  | // FileStat | 
|  | @override | 
|  | Future<FileStat> stat(String path) { | 
|  | if (_stat != null) return _stat!(path); | 
|  | if (_previous != null) return _previous!.stat(path); | 
|  | return super.stat(path); | 
|  | } | 
|  |  | 
|  | @override | 
|  | FileStat statSync(String path) { | 
|  | if (_stat != null) return _statSync!(path); | 
|  | if (_previous != null) return _previous!.statSync(path); | 
|  | return super.statSync(path); | 
|  | } | 
|  |  | 
|  | // FileSystemEntity | 
|  | @override | 
|  | Future<bool> fseIdentical(String path1, String path2) { | 
|  | if (_fseIdentical != null) return _fseIdentical!(path1, path2); | 
|  | if (_previous != null) return _previous!.fseIdentical(path1, path2); | 
|  | return super.fseIdentical(path1, path2); | 
|  | } | 
|  |  | 
|  | @override | 
|  | bool fseIdenticalSync(String path1, String path2) { | 
|  | if (_fseIdenticalSync != null) return _fseIdenticalSync!(path1, path2); | 
|  | if (_previous != null) return _previous!.fseIdenticalSync(path1, path2); | 
|  | return super.fseIdenticalSync(path1, path2); | 
|  | } | 
|  |  | 
|  | @override | 
|  | Future<FileSystemEntityType> fseGetType(String path, bool followLinks) { | 
|  | if (_fseGetType != null) return _fseGetType!(path, followLinks); | 
|  | if (_previous != null) return _previous!.fseGetType(path, followLinks); | 
|  | return super.fseGetType(path, followLinks); | 
|  | } | 
|  |  | 
|  | @override | 
|  | FileSystemEntityType fseGetTypeSync(String path, bool followLinks) { | 
|  | if (_fseGetTypeSync != null) return _fseGetTypeSync!(path, followLinks); | 
|  | if (_previous != null) return _previous!.fseGetTypeSync(path, followLinks); | 
|  | return super.fseGetTypeSync(path, followLinks); | 
|  | } | 
|  |  | 
|  | // _FileSystemWatcher | 
|  | @override | 
|  | Stream<FileSystemEvent> fsWatch(String path, int events, bool recursive) { | 
|  | if (_fsWatch != null) return _fsWatch!(path, events, recursive); | 
|  | if (_previous != null) return _previous!.fsWatch(path, events, recursive); | 
|  | return super.fsWatch(path, events, recursive); | 
|  | } | 
|  |  | 
|  | @override | 
|  | bool fsWatchIsSupported() { | 
|  | if (_fsWatchIsSupported != null) return _fsWatchIsSupported!(); | 
|  | if (_previous != null) return _previous!.fsWatchIsSupported(); | 
|  | return super.fsWatchIsSupported(); | 
|  | } | 
|  |  | 
|  | // Link | 
|  | @override | 
|  | Link createLink(String path) { | 
|  | if (_createLink != null) return _createLink!(path); | 
|  | if (_previous != null) return _previous!.createLink(path); | 
|  | return super.createLink(path); | 
|  | } | 
|  |  | 
|  | // Socket | 
|  | @override | 
|  | Future<Socket> socketConnect(host, int port, | 
|  | {sourceAddress, Duration? timeout}) { | 
|  | if (_socketConnect != null) { | 
|  | return _socketConnect!(host, port, | 
|  | sourceAddress: sourceAddress, timeout: timeout); | 
|  | } | 
|  | if (_previous != null) { | 
|  | return _previous!.socketConnect(host, port, | 
|  | sourceAddress: sourceAddress, timeout: timeout); | 
|  | } | 
|  | return super.socketConnect(host, port, | 
|  | sourceAddress: sourceAddress, timeout: timeout); | 
|  | } | 
|  |  | 
|  | @override | 
|  | Future<ConnectionTask<Socket>> socketStartConnect(host, int port, | 
|  | {sourceAddress}) { | 
|  | if (_socketStartConnect != null) { | 
|  | return _socketStartConnect!(host, port, sourceAddress: sourceAddress); | 
|  | } | 
|  | if (_previous != null) { | 
|  | return _previous! | 
|  | .socketStartConnect(host, port, sourceAddress: sourceAddress); | 
|  | } | 
|  | return super.socketStartConnect(host, port, sourceAddress: sourceAddress); | 
|  | } | 
|  |  | 
|  | // ServerSocket | 
|  |  | 
|  | @override | 
|  | Future<ServerSocket> serverSocketBind(address, int port, | 
|  | {int backlog = 0, bool v6Only = false, bool shared = false}) { | 
|  | if (_serverSocketBind != null) { | 
|  | return _serverSocketBind!(address, port, | 
|  | backlog: backlog, v6Only: v6Only, shared: shared); | 
|  | } | 
|  | if (_previous != null) { | 
|  | return _previous!.serverSocketBind(address, port, | 
|  | backlog: backlog, v6Only: v6Only, shared: shared); | 
|  | } | 
|  | return super.serverSocketBind(address, port, | 
|  | backlog: backlog, v6Only: v6Only, shared: shared); | 
|  | } | 
|  |  | 
|  | // Standard streams | 
|  |  | 
|  | @override | 
|  | Stdin get stdin { | 
|  | return _stdin?.call() ?? _previous?.stdin ?? super.stdin; | 
|  | } | 
|  |  | 
|  | @override | 
|  | Stdout get stdout { | 
|  | return _stdout?.call() ?? _previous?.stdout ?? super.stdout; | 
|  | } | 
|  |  | 
|  | @override | 
|  | Stdout get stderr { | 
|  | return _stderr?.call() ?? _previous?.stderr ?? super.stderr; | 
|  | } | 
|  | } |