Index: test/isolate_test.dart |
diff --git a/test/isolate_test.dart b/test/isolate_test.dart |
index b08bdd9158db4d4326739dbc8fc1e97da022cfe2..9333f18feff93edbc84de47c231fb9aad5a68ad3 100644 |
--- a/test/isolate_test.dart |
+++ b/test/isolate_test.dart |
@@ -5,6 +5,7 @@ |
import 'dart:async'; |
import 'package:async/async.dart'; |
+import 'package:json_rpc_2/json_rpc_2.dart' as rpc; |
import 'package:test/test.dart'; |
import 'package:vm_service_client/vm_service_client.dart'; |
@@ -165,6 +166,108 @@ void main() { |
expect(other.onExit, completes); |
}); |
}); |
+ |
+ test("onServiceExtensionAdded fires when an extension is added", () async { |
+ client = await runAndConnect(main: """ |
+ registerExtension('ext.test', (_, __) {}); |
+ """, flags: ["--pause-isolates-on-start"]); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.loadRunnable(); |
+ await isolate.waitUntilPaused(); |
+ await isolate.resume(); |
+ |
+ String ext = await isolate.onServiceExtensionAdded.first; |
+ expect(ext, 'ext.test'); |
+ }); |
+ |
+ group("onExtensionEvent", () { |
+ test("emits extension events", () async { |
+ client = await runAndConnect(main: """ |
+ postEvent('foo', {'bar': 'baz'}); |
+ """, flags: ["--pause-isolates-on-start"]); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.load(); |
+ await isolate.waitUntilPaused(); |
+ var eventFuture = _onlyEvent(isolate.onExtensionEvent); |
+ await isolate.resume(); |
+ |
+ var event = await eventFuture; |
+ expect(event.kind, 'foo'); |
+ expect(event.data, {'bar': 'baz'}); |
+ }); |
+ }); |
+ |
+ group("selectExtensionEvents", () { |
+ test("chooses by extension kind", () async { |
+ client = await runAndConnect(main: """ |
+ postEvent('foo', {'prefixed': false}); |
+ postEvent('bar.baz', {'prefixed': true}); |
+ postEvent('not.captured', {}); |
+ """, flags: ["--pause-isolates-on-start"]); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.load(); |
+ |
+ var unprefixedEvent = _onlyEvent(isolate.selectExtensionEvents('foo')); |
+ var prefixedEvent = |
+ _onlyEvent(isolate.selectExtensionEvents('bar.', prefix: true)); |
+ |
+ await isolate.waitUntilPaused(); |
+ await isolate.resume(); |
+ |
+ expect((await unprefixedEvent).kind, 'foo'); |
+ expect((await prefixedEvent).kind, 'bar.baz'); |
+ }); |
+ }); |
+ }); |
+ |
+ group("waitForExtension", () { |
+ test("notifies when the extension is already registered", () async { |
+ client = await runAndConnect(main: """ |
+ registerExtension('ext.test', (_, __) {}); |
+ postEvent('registered', {}); |
+ """, flags: ["--pause-isolates-on-start"]); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.load(); |
+ await isolate.waitUntilPaused(); |
+ var whenRegistered = isolate.selectExtensionEvents('registered').first; |
+ await isolate.resume(); |
+ await whenRegistered; |
+ expect(isolate.waitForExtension('ext.test'), completes); |
+ }); |
+ |
+ test("notifies when the extension is registered later", () async { |
+ client = await runAndConnect(main: """ |
+ registerExtension('ext.one', (_, __) { |
+ registerExtension('ext.two', (_, __) { |
+ return new ServiceExtensionResponse.result('''{ |
+ "ext.two": "is ok" |
+ }'''); |
+ }); |
+ }); |
+ """); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.load(); |
+ isolate.waitForExtension('ext.two').then(expectAsync((_) async { |
+ expect(await isolate.invokeExtension('ext.two'), { |
+ 'ext.two': 'is ok', |
+ }); |
+ })); |
+ |
+ await isolate.waitForExtension('ext.one'); |
+ isolate.invokeExtension('ext.one'); |
+ }); |
+ }); |
+ |
+ group("load", () { |
+ test("loads extensionRpcs", () async { |
+ client = await runAndConnect(main: """ |
+ registerExtension('ext.foo', (_, __) {}); |
+ registerExtension('ext.bar', (_, __) {}); |
+ """); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.load(); |
+ expect(isolate.extensionRpcs, unorderedEquals(['ext.foo', 'ext.bar'])); |
+ }); |
}); |
group("loadRunnable", () { |
@@ -375,6 +478,60 @@ void main() { |
expect(breakpoint.number, equals(1)); |
}); |
}); |
+ |
+ group("invokeExtension", () { |
+ test("enforces ext. prefix", () async { |
+ var client = await runAndConnect(); |
+ var isolate = await (await client.getVM()).isolates.first.loadRunnable(); |
+ expect(() => isolate.invokeExtension('noprefix'), throwsArgumentError); |
+ }); |
+ |
+ test("invokes extension", () async { |
+ var client = await runAndConnect(main: r""" |
+ registerExtension('ext.ping', (_, __) async { |
+ return new ServiceExtensionResponse.result('{"type": "pong"}'); |
+ }); |
+ """); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.loadRunnable(); |
+ var response = await isolate.invokeExtension('ext.ping'); |
+ expect(response, {'type': 'pong'}); |
+ }); |
+ |
+ test("passes parameters", () async { |
+ var client = await runAndConnect(main: r""" |
+ registerExtension('ext.params', (_, params) async { |
+ return new ServiceExtensionResponse.result('''{ |
+ "foo": "${params['foo']}" |
+ }'''); |
+ }); |
+ """); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.loadRunnable(); |
+ var response = await isolate.invokeExtension('ext.params', { |
+ 'foo': 'bar', |
+ }); |
+ expect(response, { |
+ 'foo': 'bar', |
+ }); |
+ }); |
+ |
+ test("returns errors", () async { |
+ var client = await runAndConnect(main: r""" |
+ registerExtension('ext.error', (_, __) async { |
+ return new ServiceExtensionResponse.error(-32013, 'some error'); |
+ }); |
+ """); |
+ |
+ var isolate = await (await client.getVM()).isolates.first.loadRunnable(); |
+ await isolate.invokeExtension('ext.error') |
+ .then(expectAsync((_) {}, count: 0)) |
+ .catchError(expectAsync((rpc.RpcException error) { |
+ expect(error.code, -32013); |
+ expect(error.data, {'details': 'some error'}); |
+ })); |
+ }); |
+ }); |
} |
/// Starts a client with two unpaused empty isolates. |
@@ -395,3 +552,18 @@ Future<List<VMRunnableIsolate>> _twoIsolates() async { |
return [main, other]; |
} |
+ |
+Future _onlyEvent(Stream stream) { |
+ var completer = new Completer.sync(); |
+ stream.listen(expectAsync(completer.complete, count: 1), |
+ onError: registerException, |
+ onDone: () { |
+ if (completer.isCompleted) return; |
+ throw "Expected an event."; |
+ }); |
+ |
+ // Hack to cause the test to stick around long enough to receive all events |
+ // from the VM service. |
+ expect(new Future.delayed(new Duration(milliseconds: 200)), completes); |
+ return completer.future; |
+} |