// Copyright 2014 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.

import 'dart:async';

import 'package:dds/dap.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/debug_adapters/flutter_adapter.dart';
import 'package:flutter_tools/src/debug_adapters/flutter_adapter_args.dart';
import 'package:flutter_tools/src/globals.dart' as globals show fs, platform;
import 'package:test/fake.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';

import 'mocks.dart';

void main() {
  // Use the real platform as a base so that Windows bots test paths.
  final FakePlatform platform = FakePlatform.fromPlatform(globals.platform);
  final FileSystemStyle fsStyle = platform.isWindows ? FileSystemStyle.windows : FileSystemStyle.posix;
  final String flutterRoot = platform.isWindows
                                ? r'C:\fake\flutter'
                                : '/fake/flutter';

  group('flutter adapter', () {
    final String expectedFlutterExecutable = platform.isWindows
        ? r'C:\fake\flutter\bin\flutter.bat'
        : '/fake/flutter/bin/flutter';

    setUpAll(() {
      Cache.flutterRoot = flutterRoot;
    });

    group('launchRequest', () {
      test('runs "flutter run" with --machine', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.processArgs, containsAllInOrder(<String>['run', '--machine']));
      });

      test('includes env variables', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
          env: <String, String>{
            'MY_TEST_ENV': 'MY_TEST_VALUE',
          },
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.env!['MY_TEST_ENV'], 'MY_TEST_VALUE');
      });

      test('does not record the VMs PID for terminating', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        // Trigger a fake debuggerConnected with a pid that we expect the
        // adapter _not_ to record, because it may be on another device.
        await adapter.debuggerConnected(_FakeVm(pid: 123));

        // Ensure the VM's pid was not recorded.
        expect(adapter.pidsToTerminate, isNot(contains(123)));
      });


      group('supportsRestartRequest', () {
        void testRestartSupport(bool supportsRestart) {
          test('notifies client for supportsRestart: $supportsRestart', () async {
            final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
              fileSystem: MemoryFileSystem.test(style: fsStyle),
              platform: platform,
              supportsRestart: supportsRestart,
            );

            final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
              cwd: '.',
              program: 'foo.dart',
            );

            // Listen for a Capabilities event that modifies 'supportsRestartRequest'.
            final Future<CapabilitiesEventBody> capabilitiesUpdate = adapter
                .dapToClientMessages
                .where((Map<String, Object?> message) => message['event'] == 'capabilities')
                .map((Map<String, Object?> message) => message['body'] as Map<String, Object?>?)
                .where((Map<String, Object?>? body) => body != null).cast<Map<String, Object?>>()
                .map(CapabilitiesEventBody.fromJson)
                .firstWhere((CapabilitiesEventBody body) => body.capabilities.supportsRestartRequest != null);

            await adapter.configurationDoneRequest(MockRequest(), null, () {});
            final Completer<void> launchCompleter = Completer<void>();
            await adapter.launchRequest(MockRequest(), args, launchCompleter.complete);
            await launchCompleter.future;

            // Ensure the Capabilities update has the expected value.
            expect((await capabilitiesUpdate).capabilities.supportsRestartRequest, supportsRestart);
          });
        }

        testRestartSupport(true);
        testRestartSupport(false);
      });

      test('calls "app.stop" on terminateRequest', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        final Completer<void> launchCompleter = Completer<void>();
        await adapter.launchRequest(MockRequest(), args, launchCompleter.complete);
        await launchCompleter.future;

        final Completer<void> terminateCompleter = Completer<void>();
        await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
        await terminateCompleter.future;

        expect(adapter.dapToFlutterRequests, contains('app.stop'));
      });

      test('does not call "app.stop" on terminateRequest if app was not started', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
          simulateAppStarted: false,
        );

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        final Completer<void> launchCompleter = Completer<void>();
        await adapter.launchRequest(MockRequest(), args, launchCompleter.complete);
        await launchCompleter.future;

        final Completer<void> terminateCompleter = Completer<void>();
        await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
        await terminateCompleter.future;

        expect(adapter.dapToFlutterRequests, isNot(contains('app.stop')));
      });

      test('does not call "app.restart" before app has been started', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
          simulateAppStarted: false,
        );

        final Completer<void> launchCompleter = Completer<void>();
         final FlutterLaunchRequestArguments launchArgs = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
        );
        final Completer<void> restartCompleter = Completer<void>();
        final RestartArguments restartArgs = RestartArguments();

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), launchArgs, launchCompleter.complete);
        await launchCompleter.future;
        await adapter.restartRequest(MockRequest(), restartArgs, restartCompleter.complete);
        await restartCompleter.future;

        expect(adapter.dapToFlutterRequests, isNot(contains('app.restart')));
      });

      test('includes build progress updates', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
        );

        // Begin listening for progress events up until `progressEnd` (but don't await yet).
        final Future<List<List<Object?>>> progressEventsFuture =
            adapter.dapToClientProgressEvents
              .takeWhile((Map<String, Object?> message) => message['event'] != 'progressEnd')
              .map((Map<String, Object?> message) => <Object?>[message['event'], (message['body']! as Map<String, Object?>)['message']])
              .toList();

        // Initialize with progress support.
        await adapter.initializeRequest(
          MockRequest(),
          DartInitializeRequestArguments(adapterID: 'test', supportsProgressReporting: true, ),
          (_) {},
        );
        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        // Ensure we got the expected events prior to the progressEnd.
        final List<List<Object?>> progressEvents = await progressEventsFuture;
        expect(progressEvents, containsAllInOrder(<List<String?>>[
          <String?>['progressStart', 'Launching…'],
          <String?>['progressUpdate', 'Step 1…'],
          <String?>['progressUpdate', 'Step 2…'],
          // progressEnd isn't included because we used takeWhile to stop when it arrived above.
        ]));
      });

      test('includes Dart Debug extension progress update', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
          preAppStart: (MockFlutterDebugAdapter adapter) {
            adapter.simulateRawStdout('Waiting for connection from Dart debug extension…');
          }
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
        );

        // Begin listening for progress events up until `progressEnd` (but don't await yet).
        final Future<List<List<Object?>>> progressEventsFuture =
            adapter.dapToClientProgressEvents
              .takeWhile((Map<String, Object?> message) => message['event'] != 'progressEnd')
              .map((Map<String, Object?> message) => <Object?>[message['event'], (message['body']! as Map<String, Object?>)['message']])
              .toList();

        // Initialize with progress support.
        await adapter.initializeRequest(
          MockRequest(),
          DartInitializeRequestArguments(adapterID: 'test', supportsProgressReporting: true, ),
          (_) {},
        );
        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        // Ensure we got the expected events prior to the progressEnd.
        final List<List<Object?>> progressEvents = await progressEventsFuture;
        expect(progressEvents, containsAllInOrder(<List<String>>[
          <String>['progressStart', 'Launching…'],
          <String>['progressUpdate', 'Please click the Dart Debug extension button in the spawned browser window'],
          // progressEnd isn't included because we used takeWhile to stop when it arrived above.
        ]));
      });
    });

    group('attachRequest', () {
      test('runs "flutter attach" with --machine', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterAttachRequestArguments args = FlutterAttachRequestArguments(
          cwd: '.',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.attachRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.processArgs, containsAllInOrder(<String>['attach', '--machine']));
      });

      test('runs "flutter attach" with program if passed in', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterAttachRequestArguments args =
            FlutterAttachRequestArguments(
          cwd: '.',
          program: 'program/main.dart',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.attachRequest(
            MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(
            adapter.processArgs,
            containsAllInOrder(<String>[
              'attach',
              '--machine',
              '--target',
              'program/main.dart'
            ]));
      });

      test('runs "flutter attach" with --debug-uri if vmServiceUri is passed', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterAttachRequestArguments args =
            FlutterAttachRequestArguments(
          cwd: '.',
          program: 'program/main.dart',
          vmServiceUri: 'ws://1.2.3.4/ws'
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.attachRequest(
            MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(
            adapter.processArgs,
            containsAllInOrder(<String>[
              'attach',
              '--machine',
              '--debug-uri',
              'ws://1.2.3.4/ws',
              '--target',
              'program/main.dart',
            ]));
      });

      test('runs "flutter attach" with --debug-uri if vmServiceInfoFile exists', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();
        final File serviceInfoFile = globals.fs.systemTempDirectory.createTempSync('dap_flutter_attach_vmServiceInfoFile').childFile('vmServiceInfo.json');

        final FlutterAttachRequestArguments args =
            FlutterAttachRequestArguments(
          cwd: '.',
          program: 'program/main.dart',
          vmServiceInfoFile: serviceInfoFile.path,
        );

        // Write the service info file before trying to attach:
        serviceInfoFile.writeAsStringSync('{ "uri": "ws://1.2.3.4/ws" }');

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.attachRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(
            adapter.processArgs,
            containsAllInOrder(<String>[
              'attach',
              '--machine',
              '--debug-uri',
              'ws://1.2.3.4/ws',
              '--target',
              'program/main.dart',
            ]));
      });

      test('runs "flutter attach" with --debug-uri if vmServiceInfoFile is created later', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();
        final File serviceInfoFile = globals.fs.systemTempDirectory.createTempSync('dap_flutter_attach_vmServiceInfoFile').childFile('vmServiceInfo.json');

        final FlutterAttachRequestArguments args =
            FlutterAttachRequestArguments(
          cwd: '.',
          program: 'program/main.dart',
          vmServiceInfoFile: serviceInfoFile.path,
        );


        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        final Future<void> attachResponseFuture = adapter.attachRequest(MockRequest(), args, responseCompleter.complete);
        // Write the service info file a little later to ensure we detect it:
        await pumpEventQueue(times:5000);
        serviceInfoFile.writeAsStringSync('{ "uri": "ws://1.2.3.4/ws" }');
        await attachResponseFuture;
        await responseCompleter.future;

        expect(
            adapter.processArgs,
            containsAllInOrder(<String>[
              'attach',
              '--machine',
              '--debug-uri',
              'ws://1.2.3.4/ws',
              '--target',
              'program/main.dart',
            ]));
      });

      test('does not record the VMs PID for terminating', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterAttachRequestArguments args = FlutterAttachRequestArguments(
          cwd: '.',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.attachRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        // Trigger a fake debuggerConnected with a pid that we expect the
        // adapter _not_ to record, because it may be on another device.
        await adapter.debuggerConnected(_FakeVm(pid: 123));

        // Ensure the VM's pid was not recorded.
        expect(adapter.pidsToTerminate, isNot(contains(123)));
      });

      test('calls "app.detach" on terminateRequest', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );

        final FlutterAttachRequestArguments args = FlutterAttachRequestArguments(
          cwd: '.',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        final Completer<void> attachCompleter = Completer<void>();
        await adapter.attachRequest(MockRequest(), args, attachCompleter.complete);
        await attachCompleter.future;

        final Completer<void> terminateCompleter = Completer<void>();
        await adapter.terminateRequest(MockRequest(), TerminateArguments(restart: false), terminateCompleter.complete);
        await terminateCompleter.future;

        expect(adapter.dapToFlutterRequests, contains('app.detach'));
      });
    });

    group('forwards events', () {
      test('app.webLaunchUrl', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );

        // Start listening for the forwarded event (don't await it yet, it won't
        // be triggered until the call below).
        final Future<Map<String, Object?>> forwardedEvent = adapter.dapToClientMessages
            .firstWhere((Map<String, Object?> data) => data['event'] == 'flutter.forwardedEvent');

        // Simulate Flutter asking for a URL to be launched.
        adapter.simulateStdoutMessage(<String, Object?>{
          'event': 'app.webLaunchUrl',
          'params': <String, Object?>{
            'url': 'http://localhost:123/',
            'launched': false,
          }
        });

        // Wait for the forwarded event.
        final Map<String, Object?> message = await forwardedEvent;
        // Ensure the body of the event matches the original event sent by Flutter.
        expect(message['body'], <String, Object?>{
          'event': 'app.webLaunchUrl',
          'params': <String, Object?>{
            'url': 'http://localhost:123/',
            'launched': false,
          }
        });
      });
    });

    group('handles reverse requests', () {
      test('app.exposeUrl', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );

        // Pretend to be the client, handling any reverse-requests for exposeUrl
        // and mapping the host to 'mapped-host'.
        adapter.exposeUrlHandler = (String url) => Uri.parse(url).replace(host: 'mapped-host').toString();

        // Simulate Flutter asking for a URL to be exposed.
        const int requestId = 12345;
        adapter.simulateStdoutMessage(<String, Object?>{
          'id': requestId,
          'method': 'app.exposeUrl',
          'params': <String, Object?>{
            'url': 'http://localhost:123/',
          }
        });

        // Allow the handler to be processed.
        await pumpEventQueue(times: 5000);

        final Map<String, Object?> message = adapter.dapToFlutterMessages.singleWhere((Map<String, Object?> data) => data['id'] == requestId);
        expect(message['result'], 'http://mapped-host:123/');
      });
    });

    group('--start-paused', () {
      test('is passed for debug mode', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.processArgs, contains('--start-paused'));
      });

      test('is not passed for noDebug mode', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
          noDebug: true,
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.processArgs, isNot(contains('--start-paused')));
      });

      test('is not passed if toolArgs contains --profile', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
          toolArgs: <String>['--profile'],
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.processArgs, isNot(contains('--start-paused')));
      });

      test('is not passed if toolArgs contains --release', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final Completer<void> responseCompleter = Completer<void>();

        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
          toolArgs: <String>['--release'],
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.processArgs, isNot(contains('--start-paused')));
      });
    });

    test('includes toolArgs', () async {
      final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
        fileSystem: MemoryFileSystem.test(style: fsStyle),
        platform: platform,
      );
      final Completer<void> responseCompleter = Completer<void>();

      final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
        cwd: '.',
        program: 'foo.dart',
        toolArgs: <String>['tool_arg'],
        noDebug: true,
      );

      await adapter.configurationDoneRequest(MockRequest(), null, () {});
      await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
      await responseCompleter.future;

      expect(adapter.executable, equals(expectedFlutterExecutable));
      expect(adapter.processArgs, contains('tool_arg'));
    });

    group('maps org-dartlang-sdk paths', () {
      late FileSystem fs;
      late FlutterDebugAdapter adapter;
      setUp(() {
        fs = MemoryFileSystem.test(style: fsStyle);
        adapter = MockFlutterDebugAdapter(
          fileSystem: fs,
          platform: platform,
        );
      });

      test('dart:ui URI to file path', () async {
        expect(
          adapter.convertOrgDartlangSdkToPath(Uri.parse('org-dartlang-sdk:///flutter/lib/ui/ui.dart')),
          Uri.file(fs.path.join(flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui', 'ui.dart')),
        );
      });

      test('dart:ui file path to URI', () async {
        expect(
          adapter.convertUriToOrgDartlangSdk(Uri.file(fs.path.join(flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'ui', 'ui.dart'))),
          Uri.parse('org-dartlang-sdk:///flutter/lib/ui/ui.dart'),
        );
      });

      test('dart:core URI to file path', () async {
        expect(
          adapter.convertOrgDartlangSdkToPath(Uri.parse('org-dartlang-sdk:///third_party/dart/sdk/lib/core/core.dart')),
          Uri.file(fs.path.join(flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'core', 'core.dart')),
        );
      });

      test('dart:core file path to URI', () async {
        expect(
          adapter.convertUriToOrgDartlangSdk(Uri.file(fs.path.join(flutterRoot, 'bin', 'cache', 'pkg', 'sky_engine', 'lib', 'core', 'core.dart'))),
          Uri.parse('org-dartlang-sdk:///third_party/dart/sdk/lib/core/core.dart'),
        );
      });
    });

    group('includes customTool', () {
      test('with no args replaced', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
          customTool: '/custom/flutter',
          noDebug: true,
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        final Completer<void> responseCompleter = Completer<void>();
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.executable, equals('/custom/flutter'));
        // args should be in-tact
        expect(adapter.processArgs, contains('--machine'));
      });

      test('with all args replaced', () async {
        final MockFlutterDebugAdapter adapter = MockFlutterDebugAdapter(
          fileSystem: MemoryFileSystem.test(style: fsStyle),
          platform: platform,
        );
        final FlutterLaunchRequestArguments args = FlutterLaunchRequestArguments(
          cwd: '.',
          program: 'foo.dart',
          customTool: '/custom/flutter',
          customToolReplacesArgs: 9999, // replaces all built-in args
          noDebug: true,
          toolArgs: <String>['tool_args'], // should still be in args
        );

        await adapter.configurationDoneRequest(MockRequest(), null, () {});
        final Completer<void> responseCompleter = Completer<void>();
        await adapter.launchRequest(MockRequest(), args, responseCompleter.complete);
        await responseCompleter.future;

        expect(adapter.executable, equals('/custom/flutter'));
        // normal built-in args are replaced by customToolReplacesArgs, but
        // user-provided toolArgs are not.
        expect(adapter.processArgs, isNot(contains('--machine')));
        expect(adapter.processArgs, contains('tool_args'));
      });
    });
  });
}

class _FakeVm extends Fake implements VM {
  _FakeVm({this.pid = 1});

  @override
  final int pid;
}
