// 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);
}
