| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This is a minimal dependency heart beat test for the Dart VM Service. |
| |
| // ignore_for_file: avoid_print |
| |
| import 'dart:async'; |
| import 'dart:convert'; |
| import 'dart:io'; |
| |
| import 'launcher.dart'; |
| import 'service_client.dart'; |
| |
| class Expect { |
| static void equals(Object? actual, Object? expected) { |
| if (actual != expected) { |
| throw AssertionError('Expected $actual == $expected'); |
| } |
| } |
| } |
| |
| Future<String> readResponse(HttpClientResponse response) { |
| final Completer<String> completer = Completer<String>(); |
| final StringBuffer contents = StringBuffer(); |
| response.transform(utf8.decoder).listen((String data) { |
| contents.write(data); |
| }, onDone: () => completer.complete(contents.toString())); |
| return completer.future; |
| } |
| |
| // Test accessing the service protocol over http. |
| Future<void> testHttpProtocolRequest(Uri uri) async { |
| uri = uri.replace(path: 'getVM'); |
| final HttpClient client = HttpClient(); |
| final HttpClientRequest request = await client.getUrl(uri); |
| final HttpClientResponse response = await request.close(); |
| Expect.equals(response.statusCode, 200); |
| final responseAsMap = |
| json.decode(await readResponse(response)) as Map<String, Object?>; |
| Expect.equals(responseAsMap['jsonrpc'], '2.0'); |
| client.close(); |
| } |
| |
| // Test accessing the service protocol over ws. |
| Future<void> testWebSocketProtocolRequest(Uri uri) async { |
| uri = uri.replace(scheme: 'ws', path: 'ws'); |
| final WebSocket webSocketClient = await WebSocket.connect(uri.toString()); |
| final ServiceClient serviceClient = ServiceClient(webSocketClient); |
| final Map<String, dynamic> response = await serviceClient.invokeRPC('getVM'); |
| Expect.equals(response['type'], 'VM'); |
| try { |
| await serviceClient.invokeRPC('BART_SIMPSON'); |
| throw AssertionError('Unreachable'); |
| } catch (e) { |
| // Method not found. |
| Expect.equals((e as Map<String, dynamic>)['code'], -32601); |
| } |
| } |
| |
| // Test accessing an Observatory UI asset. |
| Future<void> testHttpAssetRequest(Uri uri) async { |
| uri = uri.replace(path: 'third_party/trace_viewer_full.html'); |
| final HttpClient client = HttpClient(); |
| final HttpClientRequest request = await client.getUrl(uri); |
| final HttpClientResponse response = await request.close(); |
| Expect.equals(response.statusCode, 200); |
| await response.drain<void>(); |
| client.close(); |
| } |
| |
| typedef TestFunction = Future<void> Function(Uri uri); |
| |
| final List<TestFunction> basicTests = <TestFunction>[ |
| testHttpProtocolRequest, |
| testWebSocketProtocolRequest, |
| testHttpAssetRequest |
| ]; |
| |
| Future<bool> runTests(ShellLauncher launcher, List<TestFunction> tests) async { |
| final ShellProcess? process = await launcher.launch(); |
| if (process == null) { |
| return false; |
| } |
| final Uri uri = await process.waitForVMService(); |
| try { |
| for (int i = 0; i < tests.length; i++) { |
| print('Executing test ${i + 1}/${tests.length}'); |
| await tests[i](uri); |
| } |
| } catch (e, st) { |
| print('Dart VM Service test failure: $e\n$st'); |
| exitCode = -1; |
| } |
| await process.kill(); |
| return exitCode == 0; |
| } |
| |
| Future<void> main(List<String> args) async { |
| if (args.length < 2) { |
| print('Usage: dart ${Platform.script} ' |
| '<sky_shell_executable> <main_dart> ...'); |
| return; |
| } |
| final String shellExecutablePath = args[0]; |
| final String mainDartPath = args[1]; |
| final List<String> extraArgs = |
| args.length <= 2 ? <String>[] : args.sublist(2); |
| |
| final ShellLauncher launcher = |
| ShellLauncher(shellExecutablePath, mainDartPath, false, extraArgs); |
| |
| await runTests(launcher, basicTests); |
| } |