LCOV - code coverage report
Current view: top level - test_api-0.4.8/lib/src/scaffolding - spawn_hybrid.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 21 0.0 %
Date: 2021-11-28 14:37:50 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
       2             : // for details. All rights reserved. Use of this source code is governed by a
       3             : // BSD-style license that can be found in the LICENSE file.
       4             : 
       5             : import 'dart:async';
       6             : import 'dart:convert';
       7             : 
       8             : import 'package:async/async.dart';
       9             : import 'package:stream_channel/stream_channel.dart';
      10             : 
      11             : import '../backend/remote_exception.dart';
      12             : import '../utils.dart';
      13             : import 'test_structure.dart' show addTearDown;
      14             : 
      15             : /// A transformer that handles messages from the spawned isolate and ensures
      16             : /// that messages sent to it are JSON-encodable.
      17             : ///
      18             : /// The spawned isolate sends three kinds of messages. Data messages are emitted
      19             : /// as data events, error messages are emitted as error events, and print
      20             : /// messages are printed using `print()`.
      21             : // package:test will only send a `Map` across this channel, but users of
      22             : // `hybridMain` can send any json encodeable type.
      23           0 : final _transformer = StreamChannelTransformer<dynamic, dynamic>(
      24             :     StreamTransformer.fromHandlers(handleData: (message, sink) {
      25             :   switch (message['type'] as String) {
      26             :     case 'data':
      27             :       sink.add(message['data']);
      28             :       break;
      29             : 
      30             :     case 'print':
      31             :       print(message['line']);
      32             :       break;
      33             : 
      34             :     case 'error':
      35             :       var error = RemoteException.deserialize(message['error']);
      36             :       sink.addError(error.error, error.stackTrace);
      37             :       break;
      38             :   }
      39             : }), StreamSinkTransformer.fromHandlers(handleData: (message, sink) {
      40             :   // This is called synchronously from the user's `Sink.add()` call, so if
      41             :   // [ensureJsonEncodable] throws here they'll get a helpful stack trace.
      42             :   ensureJsonEncodable(message);
      43             :   sink.add(message);
      44             : }));
      45             : 
      46             : /// Spawns a VM isolate for the given [uri], which may be a [Uri] or a [String].
      47             : ///
      48             : /// This allows browser tests to spawn servers with which they can communicate
      49             : /// to test client/server interactions. It can also be used by VM tests to
      50             : /// easily spawn an isolate.
      51             : ///
      52             : /// The Dart file at [uri] must define a top-level `hybridMain()` function that
      53             : /// takes a `StreamChannel` argument and, optionally, an `Object` argument to
      54             : /// which [message] will be passed. Note that [message] must be JSON-encodable.
      55             : /// For example:
      56             : ///
      57             : /// ```dart
      58             : /// import "package:stream_channel/stream_channel.dart";
      59             : ///
      60             : /// hybridMain(StreamChannel channel, Object message) {
      61             : ///   // ...
      62             : /// }
      63             : /// ```
      64             : ///
      65             : /// If [uri] is relative, it will be interpreted relative to the `file:` URL for
      66             : /// the test suite being executed. If it's root-relative (that is, if it begins
      67             : /// with `/`) it will be interpreted relative to the root of the package (the
      68             : /// directory that contains `pubspec.yaml`, *not* the `test/` directory). If
      69             : /// it's a `package:` URL, it will be resolved using the current package's
      70             : /// dependency constellation.
      71             : ///
      72             : /// Returns a [StreamChannel] that's connected to the channel passed to
      73             : /// `hybridMain()`. Only JSON-encodable objects may be sent through this
      74             : /// channel. If the channel is closed, the hybrid isolate is killed. If the
      75             : /// isolate is killed, the channel's stream will emit a "done" event.
      76             : ///
      77             : /// Any unhandled errors loading or running the hybrid isolate will be emitted
      78             : /// as errors over the channel's stream. Any calls to `print()` in the hybrid
      79             : /// isolate will be printed as though they came from the test that created the
      80             : /// isolate.
      81             : ///
      82             : /// Code in the hybrid isolate is not considered to be running in a test
      83             : /// context, so it can't access test functions like `expect()` and
      84             : /// `expectAsync()`.
      85             : ///
      86             : /// By default, the hybrid isolate is automatically killed when the test
      87             : /// finishes running. If [stayAlive] is `true`, it won't be killed until the
      88             : /// entire test suite finishes running.
      89             : ///
      90             : /// **Note**: If you use this API, be sure to add a dependency on the
      91             : /// **`stream_channel` package, since you're using its API as well!
      92           0 : StreamChannel spawnHybridUri(uri, {Object? message, bool stayAlive = false}) {
      93           0 :   if (uri is String) {
      94             :     // Ensure that it can be parsed as a uri.
      95           0 :     Uri.parse(uri);
      96           0 :   } else if (uri is! Uri) {
      97           0 :     throw ArgumentError.value(uri, 'uri', 'must be a Uri or a String.');
      98             :   }
      99           0 :   return _spawn(uri.toString(), message, stayAlive: stayAlive);
     100             : }
     101             : 
     102             : /// Spawns a VM isolate that runs the given [dartCode], which is loaded as the
     103             : /// contents of a Dart library.
     104             : ///
     105             : /// This allows browser tests to spawn servers with which they can communicate
     106             : /// to test client/server interactions. It can also be used by VM tests to
     107             : /// easily spawn an isolate.
     108             : ///
     109             : /// The [dartCode] must define a top-level `hybridMain()` function that takes a
     110             : /// `StreamChannel` argument and, optionally, an `Object` argument to which
     111             : /// [message] will be passed. Note that [message] must be JSON-encodable. For
     112             : /// example:
     113             : ///
     114             : /// ```dart
     115             : /// import "package:stream_channel/stream_channel.dart";
     116             : ///
     117             : /// hybridMain(StreamChannel channel, Object message) {
     118             : ///   // ...
     119             : /// }
     120             : /// ```
     121             : ///
     122             : /// Returns a [StreamChannel] that's connected to the channel passed to
     123             : /// `hybridMain()`. Only JSON-encodable objects may be sent through this
     124             : /// channel. If the channel is closed, the hybrid isolate is killed. If the
     125             : /// isolate is killed, the channel's stream will emit a "done" event.
     126             : ///
     127             : /// Any unhandled errors loading or running the hybrid isolate will be emitted
     128             : /// as errors over the channel's stream. Any calls to `print()` in the hybrid
     129             : /// isolate will be printed as though they came from the test that created the
     130             : /// isolate.
     131             : ///
     132             : /// Code in the hybrid isolate is not considered to be running in a test
     133             : /// context, so it can't access test functions like `expect()` and
     134             : /// `expectAsync()`.
     135             : ///
     136             : /// By default, the hybrid isolate is automatically killed when the test
     137             : /// finishes running. If [stayAlive] is `true`, it won't be killed until the
     138             : /// entire test suite finishes running.
     139             : ///
     140             : /// **Note**: If you use this API, be sure to add a dependency on the
     141             : /// **`stream_channel` package, since you're using its API as well!
     142           0 : StreamChannel spawnHybridCode(String dartCode,
     143             :     {Object? message, bool stayAlive = false}) {
     144           0 :   var uri = Uri.dataFromString(dartCode,
     145             :       encoding: utf8, mimeType: 'application/dart');
     146           0 :   return _spawn(uri.toString(), message, stayAlive: stayAlive);
     147             : }
     148             : 
     149             : /// Like [spawnHybridUri], but doesn't take [Uri] objects.
     150           0 : StreamChannel _spawn(String uri, Object? message, {bool stayAlive = false}) {
     151           0 :   var channel = Zone.current[#test.runner.test_channel] as MultiChannel?;
     152             :   if (channel == null) {
     153           0 :     throw UnsupportedError("Can't connect to the test runner.\n"
     154             :         'spawnHybridUri() is currently only supported within "dart test".');
     155             :   }
     156             : 
     157           0 :   ensureJsonEncodable(message);
     158             : 
     159           0 :   var virtualChannel = channel.virtualChannel();
     160             :   StreamChannel isolateChannel = virtualChannel;
     161           0 :   channel.sink.add({
     162             :     'type': 'spawn-hybrid-uri',
     163             :     'url': uri,
     164             :     'message': message,
     165           0 :     'channel': virtualChannel.id
     166             :   });
     167             : 
     168             :   if (!stayAlive) {
     169           0 :     var disconnector = Disconnector();
     170           0 :     addTearDown(() => disconnector.disconnect());
     171           0 :     isolateChannel = isolateChannel.transform(disconnector);
     172             :   }
     173             : 
     174           0 :   return isolateChannel.transform(_transformer);
     175             : }

Generated by: LCOV version 1.14