blob: 1f70d5f829627d9cbcf3a36296615226e0c6523c [file] [log] [blame]
// Copyright (c) 2018, 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:stream_channel/stream_channel.dart';
/// The key used to look up [SuiteChannelManager.current] in a zone.
final _currentKey = Object();
/// A class that connects incoming and outgoing channels with the same names.
class SuiteChannelManager {
/// Connections from the test runner that have yet to connect to corresponding
/// calls to [suiteChannel] within this worker.
final _incomingConnections = <String, StreamChannel>{};
/// Connections from calls to [suiteChannel] that have yet to connect to
/// corresponding connections from the test runner.
final _outgoingConnections = <String, StreamChannelCompleter>{};
/// The channel names that have already been used.
final _names = <String>{};
/// Returns the current manager, or `null` if this isn't called within a call
/// to [asCurrent].
static SuiteChannelManager get current =>
Zone.current[_currentKey] as SuiteChannelManager;
/// Runs [body] with [this] as [SuiteChannelManager.current].
///
/// This is zone-scoped, so [this] will be the current configuration in any
/// asynchronous callbacks transitively created by [body].
T asCurrent<T>(T Function() body) =>
runZoned(body, zoneValues: {_currentKey: this});
/// Creates a connection to the test runnner's channel with the given [name].
StreamChannel connectOut(String name) {
if (_incomingConnections.containsKey(name)) {
return _incomingConnections[name];
} else if (_names.contains(name)) {
throw StateError('Duplicate suiteChannel() connection "$name".');
} else {
_names.add(name);
var completer = StreamChannelCompleter();
_outgoingConnections[name] = completer;
return completer.channel;
}
}
/// Connects [channel] to this worker's channel with the given [name].
void connectIn(String name, StreamChannel channel) {
if (_outgoingConnections.containsKey(name)) {
_outgoingConnections.remove(name).setChannel(channel);
} else if (_incomingConnections.containsKey(name)) {
throw StateError('Duplicate RunnerSuite.channel() connection "$name".');
} else {
_incomingConnections[name] = channel;
}
}
}