// 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 'dart:convert';
import 'dart:io';

import 'package:dwds/dwds.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/base/dds.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/time.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/targets/scene_importer.dart';
import 'package:flutter_tools/src/build_system/targets/shader_compiler.dart';
import 'package:flutter_tools/src/compile.dart';
import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/isolated/devfs_web.dart';
import 'package:flutter_tools/src/isolated/resident_web_runner.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/resident_devtools_handler.dart';
import 'package:flutter_tools/src/resident_runner.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:flutter_tools/src/web/chrome.dart';
import 'package:flutter_tools/src/web/web_device.dart';
import 'package:package_config/package_config.dart';
import 'package:package_config/package_config_types.dart';
import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart' as vm_service;
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';

import '../src/common.dart';
import '../src/context.dart';
import '../src/fake_vm_services.dart';

const List<VmServiceExpectation> kAttachLogExpectations =
    <VmServiceExpectation>[
  FakeVmServiceRequest(
    method: 'streamListen',
    args: <String, Object>{
      'streamId': 'Stdout',
    },
  ),
  FakeVmServiceRequest(
    method: 'streamListen',
    args: <String, Object>{
      'streamId': 'Stderr',
    },
  ),
];

const List<VmServiceExpectation> kAttachIsolateExpectations =
    <VmServiceExpectation>[
  FakeVmServiceRequest(method: 'streamListen', args: <String, Object>{
    'streamId': 'Isolate',
  }),
  FakeVmServiceRequest(method: 'registerService', args: <String, Object>{
    'service': 'reloadSources',
    'alias': 'Flutter Tools',
  }),
  FakeVmServiceRequest(method: 'registerService', args: <String, Object>{
    'service': 'flutterVersion',
    'alias': 'Flutter Tools',
  }),
  FakeVmServiceRequest(method: 'registerService', args: <String, Object>{
    'service': 'flutterMemoryInfo',
    'alias': 'Flutter Tools',
  }),
  FakeVmServiceRequest(
    method: 'streamListen',
    args: <String, Object>{
      'streamId': 'Extension',
    },
  ),
];

const List<VmServiceExpectation> kAttachExpectations = <VmServiceExpectation>[
  ...kAttachLogExpectations,
  ...kAttachIsolateExpectations,
];

void main() {
  late FakeDebugConnection debugConnection;
  late FakeChromeDevice chromeDevice;
  late FakeAppConnection appConnection;
  late FakeFlutterDevice flutterDevice;
  late FakeWebDevFS webDevFS;
  late FakeResidentCompiler residentCompiler;
  late FakeChromeConnection chromeConnection;
  late FakeChromeTab chromeTab;
  late FakeWebServerDevice webServerDevice;
  late FakeDevice mockDevice;
  late FakeVmServiceHost fakeVmServiceHost;
  late FileSystem fileSystem;
  late ProcessManager processManager;
  late TestUsage testUsage;

  setUp(() {
    testUsage = TestUsage();
    fileSystem = MemoryFileSystem.test();
    processManager = FakeProcessManager.any();
    debugConnection = FakeDebugConnection();
    mockDevice = FakeDevice();
    appConnection = FakeAppConnection();
    webDevFS = FakeWebDevFS();
    residentCompiler = FakeResidentCompiler();
    chromeDevice = FakeChromeDevice();
    chromeConnection = FakeChromeConnection();
    chromeTab = FakeChromeTab('index.html');
    webServerDevice = FakeWebServerDevice();
    flutterDevice = FakeFlutterDevice()
      .._devFS = webDevFS
      ..device = mockDevice
      ..generator = residentCompiler;
    fileSystem.file('.packages').writeAsStringSync('\n');
  });

  void setupMocks() {
    fileSystem.file('pubspec.yaml').createSync();
    fileSystem.file('lib/main.dart').createSync(recursive: true);
    fileSystem.file('web/index.html').createSync(recursive: true);
    webDevFS.report = UpdateFSReport(success: true);
    debugConnection.fakeVmServiceHost = () => fakeVmServiceHost;
    webDevFS.result = ConnectionResult(
      appConnection,
      debugConnection,
      debugConnection.vmService,
    );
    debugConnection.uri = 'ws://127.0.0.1/abcd/';
    chromeConnection.tabs.add(chromeTab);
  }

  testUsingContext(
      'runner with web server device does not support debugging without --start-paused',
      () {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    flutterDevice.device = WebServerDevice(
      logger: BufferLogger.test(),
    );
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    final ResidentRunner profileResidentWebRunner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      ipv6: true,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );

    expect(profileResidentWebRunner.debuggingEnabled, false);

    flutterDevice.device = chromeDevice;

    expect(residentWebRunner.debuggingEnabled, true);
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext(
      'runner with web server device supports debugging with --start-paused',
      () {
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    setupMocks();
    flutterDevice.device = WebServerDevice(
      logger: BufferLogger.test(),
    );
    final ResidentRunner profileResidentWebRunner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions:
          DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
      ipv6: true,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );

    expect(profileResidentWebRunner.uri, webDevFS.baseUri);
    expect(profileResidentWebRunner.debuggingEnabled, true);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });
  testUsingContext('profile does not supportsServiceProtocol', () {
    final ResidentRunner residentWebRunner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      ipv6: true,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    flutterDevice.device = chromeDevice;
    final ResidentRunner profileResidentWebRunner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile),
      ipv6: true,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );

    expect(profileResidentWebRunner.supportsServiceProtocol, false);
    expect(residentWebRunner.supportsServiceProtocol, true);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Can successfully run and connect to vmservice', () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, logger: logger);
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();

    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    final DebugConnectionInfo debugConnectionInfo =
        await connectionInfoCompleter.future;

    expect(appConnection.ranMain, true);
    expect(logger.statusText,
        contains('Debug service listening on ws://127.0.0.1/abcd/'));
    expect(debugConnectionInfo.wsUri.toString(), 'ws://127.0.0.1/abcd/');
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('WebRunner copies compiled app.dill to cache during startup',
      () async {
    final DebuggingOptions debuggingOptions = DebuggingOptions.enabled(
      const BuildInfo(BuildMode.debug, null, treeShakeIcons: false),
    );
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, debuggingOptions: debuggingOptions);
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();

    residentWebRunner.artifactDirectory
        .childFile('app.dill')
        .writeAsStringSync('ABC');
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    expect(
        await fileSystem
            .file(fileSystem.path.join('build', 'cache.dill'))
            .readAsString(),
        'ABC');
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext(
      'WebRunner copies compiled app.dill to cache during startup with track-widget-creation',
      () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();

    residentWebRunner.artifactDirectory
        .childFile('app.dill')
        .writeAsStringSync('ABC');
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    expect(
        await fileSystem
            .file(fileSystem.path.join('build', 'cache.dill.track.dill'))
            .readAsString(),
        'ABC');
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  // Regression test for https://github.com/flutter/flutter/issues/60613
  testUsingContext(
      'ResidentWebRunner calls appFailedToStart if initial compilation fails',
      () async {
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fileSystem
        .file(globals.fs.path.join('lib', 'main.dart'))
        .createSync(recursive: true);
    webDevFS.report = UpdateFSReport();

    expect(await residentWebRunner.run(), 1);
    // Completing this future ensures that the daemon can exit correctly.
    expect(await residentWebRunner.waitForAppToFinish(), 1);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext(
      'Can successfully run without an index.html including status warning',
      () async {
    final BufferLogger logger = BufferLogger.test();
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();
    fileSystem.directory('web').deleteSync(recursive: true);
    final ResidentWebRunner residentWebRunner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      ipv6: true,
      stayResident: false,
      fileSystem: fileSystem,
      logger: logger,
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );

    expect(await residentWebRunner.run(), 0);
    expect(logger.statusText,
        contains('This application is not configured to build on the web'));
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Can successfully run and disconnect with --no-resident',
      () async {
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();
    final ResidentRunner residentWebRunner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      ipv6: true,
      stayResident: false,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );

    expect(await residentWebRunner.run(), 0);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Listens to stdout and stderr streams before running main',
      () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, logger: logger);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachLogExpectations,
      FakeVmServiceStreamResponse(
        streamId: 'Stdout',
        event: vm_service.Event(
            timestamp: 0,
            kind: vm_service.EventStreams.kStdout,
            bytes: base64.encode(utf8.encode('THIS MESSAGE IS IMPORTANT'))),
      ),
      FakeVmServiceStreamResponse(
        streamId: 'Stderr',
        event: vm_service.Event(
            timestamp: 0,
            kind: vm_service.EventStreams.kStderr,
            bytes: base64.encode(utf8.encode('SO IS THIS'))),
      ),
      ...kAttachIsolateExpectations,
    ]);
    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    expect(logger.statusText, contains('THIS MESSAGE IS IMPORTANT'));
    expect(logger.statusText, contains('SO IS THIS'));
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Listens to extension events with structured errors',
      () async {
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, logger: testLogger);
    final Map<String, String> extensionData = <String, String>{
      'test': 'data',
      'renderedErrorText': 'error text',
    };
    final Map<String, String> emptyExtensionData = <String, String>{
      'test': 'data',
      'renderedErrorText': '',
    };
    final Map<String, String> nonStructuredErrorData = <String, String>{
      'other': 'other stuff',
    };
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachExpectations,
      FakeVmServiceStreamResponse(
        streamId: 'Extension',
        event: vm_service.Event(
          timestamp: 0,
          extensionKind: 'Flutter.Error',
          extensionData: vm_service.ExtensionData.parse(extensionData),
          kind: vm_service.EventStreams.kExtension,
        ),
      ),
      // Empty error text should not break anything.
      FakeVmServiceStreamResponse(
        streamId: 'Extension',
        event: vm_service.Event(
          timestamp: 0,
          extensionKind: 'Flutter.Error',
          extensionData: vm_service.ExtensionData.parse(emptyExtensionData),
          kind: vm_service.EventStreams.kExtension,
        ),
      ),
      // This is not Flutter.Error kind data, so it should not be logged.
      FakeVmServiceStreamResponse(
        streamId: 'Extension',
        event: vm_service.Event(
          timestamp: 0,
          extensionKind: 'Other',
          extensionData: vm_service.ExtensionData.parse(nonStructuredErrorData),
          kind: vm_service.EventStreams.kExtension,
        ),
      ),
    ]);

    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    await null;

    expect(testLogger.statusText, contains('\nerror text'));
    expect(testLogger.statusText, isNot(contains('other stuff')));
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Does not run main with --start-paused', () async {
    final ResidentRunner residentWebRunner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions:
          DebuggingOptions.enabled(BuildInfo.debug, startPaused: true),
      ipv6: true,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();

    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    expect(appConnection.ranMain, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Can hot reload after attaching', () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner = setUpResidentRunner(
      flutterDevice,
      logger: logger,
      systemClock: SystemClock.fixed(DateTime(2001)),
    );
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachExpectations,
      const FakeVmServiceRequest(
          method: 'hotRestart',
          jsonResponse: <String, Object>{
            'type': 'Success',
          }),
      const FakeVmServiceRequest(
        method: 'streamListen',
        args: <String, Object>{
          'streamId': 'Isolate',
        },
      ),
    ]);
    setupMocks();
    final TestChromiumLauncher chromiumLauncher = TestChromiumLauncher();
    final Chromium chrome =
        Chromium(1, chromeConnection, chromiumLauncher: chromiumLauncher);
    chromiumLauncher.setInstance(chrome);

    flutterDevice.device = GoogleChromeDevice(
      fileSystem: fileSystem,
      chromiumLauncher: chromiumLauncher,
      logger: BufferLogger.test(),
      platform: FakePlatform(),
      processManager: FakeProcessManager.any(),
    );
    webDevFS.report = UpdateFSReport(success: true);

    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    final DebugConnectionInfo debugConnectionInfo =
        await connectionInfoCompleter.future;

    expect(debugConnectionInfo, isNotNull);

    final OperationResult result = await residentWebRunner.restart();

    expect(logger.statusText, contains('Restarted application in'));
    expect(result.code, 0);
    expect(webDevFS.mainUri.toString(), contains('entrypoint.dart'));

    // ensure that analytics are sent.
    expect(testUsage.events, <TestUsageEvent>[
      TestUsageEvent('hot', 'restart',
          parameters: CustomDimensions.fromMap(<String, String>{
            'cd27': 'web-javascript',
            'cd28': '',
            'cd29': 'false',
            'cd30': 'true',
            'cd13': '0',
            'cd48': 'false'
          })),
    ]);
    expect(testUsage.timings, const <TestTimingEvent>[
      TestTimingEvent('hot', 'web-incremental-restart', Duration.zero),
    ]);
  }, overrides: <Type, Generator>{
    Usage: () => testUsage,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Can hot restart after attaching', () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner = setUpResidentRunner(
      flutterDevice,
      logger: logger,
      systemClock: SystemClock.fixed(DateTime(2001)),
    );
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachExpectations,
      const FakeVmServiceRequest(
          method: 'hotRestart',
          jsonResponse: <String, Object>{
            'type': 'Success',
          }),
    ]);
    setupMocks();
    final TestChromiumLauncher chromiumLauncher = TestChromiumLauncher();
    final Chromium chrome =
        Chromium(1, chromeConnection, chromiumLauncher: chromiumLauncher);
    chromiumLauncher.setInstance(chrome);

    flutterDevice.device = GoogleChromeDevice(
      fileSystem: fileSystem,
      chromiumLauncher: chromiumLauncher,
      logger: BufferLogger.test(),
      platform: FakePlatform(),
      processManager: FakeProcessManager.any(),
    );
    webDevFS.report = UpdateFSReport(success: true);

    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    final OperationResult result =
        await residentWebRunner.restart(fullRestart: true);

    // Ensure that generated entrypoint is generated correctly.
    expect(webDevFS.mainUri, isNotNull);
    final String entrypointContents =
        fileSystem.file(webDevFS.mainUri).readAsStringSync();
    expect(entrypointContents, contains('// Flutter web bootstrap script'));
    expect(entrypointContents, contains("import 'dart:ui' as ui;"));
    expect(entrypointContents, contains('await ui.webOnlyWarmupEngine('));

    expect(logger.statusText, contains('Restarted application in'));
    expect(result.code, 0);

    // ensure that analytics are sent.
    expect(testUsage.events, <TestUsageEvent>[
      TestUsageEvent('hot', 'restart',
          parameters: CustomDimensions.fromMap(<String, String>{
            'cd27': 'web-javascript',
            'cd28': '',
            'cd29': 'false',
            'cd30': 'true',
            'cd13': '0',
            'cd48': 'false'
          })),
    ]);
    expect(testUsage.timings, const <TestTimingEvent>[
      TestTimingEvent('hot', 'web-incremental-restart', Duration.zero),
    ]);
  }, overrides: <Type, Generator>{
    Usage: () => testUsage,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Can hot restart after attaching with web-server device',
      () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner = setUpResidentRunner(
      flutterDevice,
      logger: logger,
      systemClock: SystemClock.fixed(DateTime(2001)),
    );
    fakeVmServiceHost = FakeVmServiceHost(requests: kAttachExpectations);
    setupMocks();
    flutterDevice.device = webServerDevice;
    webDevFS.report = UpdateFSReport(success: true);

    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    final OperationResult result =
        await residentWebRunner.restart(fullRestart: true);

    expect(logger.statusText, contains('Restarted application in'));
    expect(result.code, 0);

    // web-server device does not send restart analytics
    expect(testUsage.events, isEmpty);
    expect(testUsage.timings, isEmpty);
  }, overrides: <Type, Generator>{
    Usage: () => testUsage,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('web resident runner is debuggable', () {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());

    expect(residentWebRunner.debuggingEnabled, true);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Exits when initial compile fails', () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    setupMocks();
    webDevFS.report = UpdateFSReport();

    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));

    expect(await residentWebRunner.run(), 1);
    expect(testUsage.events, isEmpty);
    expect(testUsage.timings, isEmpty);
  }, overrides: <Type, Generator>{
    Usage: () => testUsage,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext(
      'Faithfully displays stdout messages with leading/trailing spaces',
      () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, logger: logger);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachLogExpectations,
      FakeVmServiceStreamResponse(
        streamId: 'Stdout',
        event: vm_service.Event(
          timestamp: 0,
          kind: vm_service.EventStreams.kStdout,
          bytes: base64.encode(
            utf8.encode(
                '    This is a message with 4 leading and trailing spaces    '),
          ),
        ),
      ),
      ...kAttachIsolateExpectations,
    ]);
    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    expect(
        logger.statusText,
        contains(
            '    This is a message with 4 leading and trailing spaces    '));
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Fails on compilation errors in hot restart', () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    webDevFS.report = UpdateFSReport();

    final OperationResult result =
        await residentWebRunner.restart(fullRestart: true);

    expect(result.code, 1);
    expect(result.message, contains('Failed to recompile application.'));
    expect(testUsage.events, isEmpty);
    expect(testUsage.timings, isEmpty);
  }, overrides: <Type, Generator>{
    Usage: () => testUsage,
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext(
      'Fails non-fatally on vmservice response error for hot restart',
      () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachExpectations,
      const FakeVmServiceRequest(
        method: 'hotRestart',
        jsonResponse: <String, Object>{
          'type': 'Failed',
        },
      ),
    ]);
    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    final OperationResult result = await residentWebRunner.restart();

    expect(result.code, 0);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Fails fatally on Vm Service error response', () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachExpectations,
      const FakeVmServiceRequest(
        method: 'hotRestart',
        // Failed response,
        errorCode: RPCErrorCodes.kInternalError,
      ),
    ]);
    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    final OperationResult result = await residentWebRunner.restart();

    expect(result.code, 1);
    expect(result.message, contains(RPCErrorCodes.kInternalError.toString()));
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('printHelp without details shows hot restart help message',
      () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, logger: logger);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    residentWebRunner.printHelp(details: false);

    expect(logger.statusText, contains('To hot restart changes'));
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('cleanup of resources is safe to call multiple times',
      () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    mockDevice.dds = DartDevelopmentService();
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachExpectations,
    ]);
    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    await residentWebRunner.exit();
    await residentWebRunner.exit();

    expect(debugConnection.didClose, false);
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('cleans up Chrome if tab is closed', () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachExpectations,
    ]);
    setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    final Future<int?> result = residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    );
    await connectionInfoCompleter.future;
    debugConnection.completer.complete();

    await result;
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Prints target and device name on run', () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, logger: logger);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachExpectations,
    ]);
    setupMocks();
    mockDevice.name = 'Chromez';
    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    expect(
        logger.statusText,
        contains(
          'Launching ${fileSystem.path.join('lib', 'main.dart')} on '
          'Chromez in debug mode',
        ));
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Sends launched app.webLaunchUrl event for Chrome device',
      () async {
    final BufferLogger logger = BufferLogger.test();
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[
      ...kAttachLogExpectations,
      ...kAttachIsolateExpectations,
    ]);
    setupMocks();
    final FakeChromeConnection chromeConnection = FakeChromeConnection();
    final TestChromiumLauncher chromiumLauncher = TestChromiumLauncher();
    final Chromium chrome =
        Chromium(1, chromeConnection, chromiumLauncher: chromiumLauncher);
    chromiumLauncher.setInstance(chrome);

    flutterDevice.device = GoogleChromeDevice(
      fileSystem: fileSystem,
      chromiumLauncher: chromiumLauncher,
      logger: logger,
      platform: FakePlatform(),
      processManager: FakeProcessManager.any(),
    );
    webDevFS.baseUri = Uri.parse('http://localhost:8765/app/');

    final FakeChromeTab chromeTab = FakeChromeTab('index.html');
    chromeConnection.tabs.add(chromeTab);

    final ResidentWebRunner runner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      ipv6: true,
      fileSystem: fileSystem,
      logger: logger,
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );

    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(runner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    // Ensure we got the URL and that it was already launched.
    expect(
        logger.eventText,
        contains(json.encode(
          <String, Object>{
            'name': 'app.webLaunchUrl',
            'args': <String, Object>{
              'url': 'http://localhost:8765/app/',
              'launched': true,
            },
          },
        )));
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext(
      'Sends unlaunched app.webLaunchUrl event for Web Server device',
      () async {
    final BufferLogger logger = BufferLogger.test();
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    setupMocks();
    flutterDevice.device = WebServerDevice(
      logger: logger,
    );
    webDevFS.baseUri = Uri.parse('http://localhost:8765/app/');

    final ResidentWebRunner runner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      ipv6: true,
      fileSystem: fileSystem,
      logger: logger,
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );

    final Completer<DebugConnectionInfo> connectionInfoCompleter =
        Completer<DebugConnectionInfo>();
    unawaited(runner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;

    // Ensure we got the URL and that it was not already launched.
    expect(
        logger.eventText,
        contains(json.encode(
          <String, Object>{
            'name': 'app.webLaunchUrl',
            'args': <String, Object>{
              'url': 'http://localhost:8765/app/',
              'launched': false,
            },
          },
        )));
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('ResidentWebRunner generates files when l10n.yaml exists', () async {
    fakeVmServiceHost =
        FakeVmServiceHost(requests: kAttachExpectations.toList());
    setupMocks();
    final ResidentRunner residentWebRunner = ResidentWebRunner(
      flutterDevice,
      flutterProject:
          FlutterProject.fromDirectoryTest(fileSystem.currentDirectory),
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      ipv6: true,
      stayResident: false,
      fileSystem: fileSystem,
      logger: BufferLogger.test(),
      usage: globals.flutterUsage,
      systemClock: globals.systemClock,
    );

    // Create necessary files.
    globals.fs.file(globals.fs.path.join('lib', 'main.dart'))
      .createSync(recursive: true);
    globals.fs.file(globals.fs.path.join('lib', 'l10n', 'app_en.arb'))
      ..createSync(recursive: true)
      ..writeAsStringSync('''
{
  "helloWorld": "Hello, World!",
  "@helloWorld": {
    "description": "Sample description"
  }
}''');
    globals.fs.file('l10n.yaml').createSync();
    globals.fs.file('pubspec.yaml').writeAsStringSync('''
flutter:
  generate: true
''');
    globals.fs.directory('.dart_tool')
      .childFile('package_config.json')
      ..createSync(recursive: true)
      ..writeAsStringSync('''
{
  "configVersion": 2,
  "packages": [
    {
      "name": "path_provider_linux",
      "rootUri": "../../../path_provider_linux",
      "packageUri": "lib/",
      "languageVersion": "2.12"
    }
  ]
}
''');
    expect(await residentWebRunner.run(), 0);
    final File generatedLocalizationsFile = globals.fs.directory('.dart_tool')
      .childDirectory('flutter_gen')
      .childDirectory('gen_l10n')
      .childFile('app_localizations.dart');
    expect(generatedLocalizationsFile.existsSync(), isTrue);
    // Completing this future ensures that the daemon can exit correctly.
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  // While this file should be ignored on web, generating it here will cause a
  // perf regression in hot restart.
  testUsingContext('Does not generate dart_plugin_registrant.dart', () async {
    // Create necessary files for [DartPluginRegistrantTarget]
    final File packageConfig =
        globals.fs.directory('.dart_tool').childFile('package_config.json');
    packageConfig.createSync(recursive: true);
    packageConfig.writeAsStringSync('''
{
  "configVersion": 2,
  "packages": [
    {
      "name": "path_provider_linux",
      "rootUri": "../../../path_provider_linux",
      "packageUri": "lib/",
      "languageVersion": "2.12"
    }
  ]
}
''');
    // Start with a dart_plugin_registrant.dart file.
    globals.fs
        .directory('.dart_tool')
        .childDirectory('flutter_build')
        .childFile('dart_plugin_registrant.dart')
        .createSync(recursive: true);

    final FlutterProject project =
        FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);

    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    await residentWebRunner.runSourceGenerators();

    // dart_plugin_registrant.dart should be untouched, indicating that its
    // generation didn't run. If it had run, the file would have been removed as
    // there are no plugins in the project.
    expect(project.dartPluginRegistrant.existsSync(), true);
    expect(project.dartPluginRegistrant.readAsStringSync(), '');
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Successfully turns WebSocketException into ToolExit',
      () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, logger: logger);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    setupMocks();
    webDevFS.exception = const WebSocketException();

    await expectLater(residentWebRunner.run, throwsToolExit());
    expect(logger.errorText, contains('WebSocketException'));
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Successfully turns AppConnectionException into ToolExit',
      () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    setupMocks();
    webDevFS.exception = AppConnectionException('');

    await expectLater(residentWebRunner.run, throwsToolExit());
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Successfully turns ChromeDebugError into ToolExit',
      () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    setupMocks();

    webDevFS.exception = ChromeDebugException(<String, Object?>{
      'text': 'error',
    });

    await expectLater(residentWebRunner.run, throwsToolExit());
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Rethrows unknown Exception type from dwds', () async {
    final ResidentRunner residentWebRunner = setUpResidentRunner(flutterDevice);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    setupMocks();
    webDevFS.exception = Exception();

    await expectLater(residentWebRunner.run, throwsException);
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });

  testUsingContext('Rethrows unknown Error type from dwds tooling', () async {
    final BufferLogger logger = BufferLogger.test();
    final ResidentRunner residentWebRunner =
        setUpResidentRunner(flutterDevice, logger: logger);
    fakeVmServiceHost = FakeVmServiceHost(requests: <VmServiceExpectation>[]);
    setupMocks();
    webDevFS.exception = StateError('');

    await expectLater(residentWebRunner.run, throwsStateError);
    expect(fakeVmServiceHost.hasRemainingExpectations, false);
  }, overrides: <Type, Generator>{
    FileSystem: () => fileSystem,
    ProcessManager: () => processManager,
  });
}

ResidentRunner setUpResidentRunner(
  FlutterDevice flutterDevice, {
  Logger? logger,
  SystemClock? systemClock,
  DebuggingOptions? debuggingOptions,
}) {
  return ResidentWebRunner(
    flutterDevice,
    flutterProject:
        FlutterProject.fromDirectoryTest(globals.fs.currentDirectory),
    debuggingOptions:
        debuggingOptions ?? DebuggingOptions.enabled(BuildInfo.debug),
    ipv6: true,
    usage: globals.flutterUsage,
    systemClock: systemClock ?? SystemClock.fixed(DateTime.now()),
    fileSystem: globals.fs,
    logger: logger ?? BufferLogger.test(),
    devtoolsHandler: createNoOpHandler,
  );
}

// Unfortunately Device, despite not being immutable, has an `operator ==`.
// Until we fix that, we have to also ignore related lints here.
// ignore: avoid_implementing_value_types
class FakeWebServerDevice extends FakeDevice implements WebServerDevice {}

// Unfortunately Device, despite not being immutable, has an `operator ==`.
// Until we fix that, we have to also ignore related lints here.
// ignore: avoid_implementing_value_types
class FakeDevice extends Fake implements Device {
  @override
  String name = 'FakeDevice';

  int count = 0;

  @override
  Future<String> get sdkNameAndVersion async => 'SDK Name and Version';

  @override
  late DartDevelopmentService dds;

  @override
  Future<LaunchResult> startApp(
    ApplicationPackage? package, {
    String? mainPath,
    String? route,
    DebuggingOptions? debuggingOptions,
    Map<String, dynamic>? platformArgs,
    bool prebuiltApplication = false,
    bool ipv6 = false,
    String? userIdentifier,
  }) async {
    return LaunchResult.succeeded();
  }

  @override
  Future<bool> stopApp(
    ApplicationPackage? app, {
    String? userIdentifier,
  }) async {
    if (count > 0) {
      throw StateError('stopApp called more than once.');
    }
    count += 1;
    return true;
  }
}

class FakeDebugConnection extends Fake implements DebugConnection {
  late FakeVmServiceHost Function() fakeVmServiceHost;

  @override
  vm_service.VmService get vmService =>
      fakeVmServiceHost.call().vmService.service;

  @override
  late String uri;

  final Completer<void> completer = Completer<void>();
  bool didClose = false;

  @override
  Future<void> get onDone => completer.future;

  @override
  Future<void> close() async {
    didClose = true;
  }
}

class FakeAppConnection extends Fake implements AppConnection {
  bool ranMain = false;

  @override
  void runMain() {
    ranMain = true;
  }
}

// Unfortunately Device, despite not being immutable, has an `operator ==`.
// Until we fix that, we have to also ignore related lints here.
// ignore: avoid_implementing_value_types
class FakeChromeDevice extends Fake implements ChromiumDevice {}

class FakeWipDebugger extends Fake implements WipDebugger {}

class FakeResidentCompiler extends Fake implements ResidentCompiler {
  @override
  Future<CompilerOutput> recompile(
    Uri mainUri,
    List<Uri>? invalidatedFiles, {
    required String outputPath,
    required PackageConfig packageConfig,
    required FileSystem fs,
    String? projectRootPath,
    bool suppressErrors = false,
    bool checkDartPluginRegistry = false,
    File? dartPluginRegistrant,
  }) async {
    return const CompilerOutput('foo.dill', 0, <Uri>[]);
  }

  @override
  void accept() {}

  @override
  void reset() {}

  @override
  Future<CompilerOutput> reject() async {
    return const CompilerOutput('foo.dill', 0, <Uri>[]);
  }

  @override
  void addFileSystemRoot(String root) {}
}

class FakeWebDevFS extends Fake implements WebDevFS {
  Object? exception;
  ConnectionResult? result;
  late UpdateFSReport report;

  Uri? mainUri;

  @override
  List<Uri> sources = <Uri>[];

  @override
  Uri baseUri = Uri.parse('http://localhost:12345');

  @override
  DateTime? lastCompiled = DateTime.now();

  @override
  PackageConfig? lastPackageConfig = PackageConfig.empty;

  @override
  Future<Uri> create() async {
    return baseUri;
  }

  @override
  Future<UpdateFSReport> update({
    required Uri mainUri,
    required ResidentCompiler generator,
    required bool trackWidgetCreation,
    required String pathToReload,
    required List<Uri> invalidatedFiles,
    required PackageConfig packageConfig,
    required String dillOutputPath,
    required DevelopmentShaderCompiler shaderCompiler,
    DevelopmentSceneImporter? sceneImporter,
    DevFSWriter? devFSWriter,
    String? target,
    AssetBundle? bundle,
    DateTime? firstBuildTime,
    bool bundleFirstUpload = false,
    bool fullRestart = false,
    String? projectRootPath,
    File? dartPluginRegistrant,
  }) async {
    this.mainUri = mainUri;
    return report;
  }

  @override
  Future<ConnectionResult?> connect(bool useDebugExtension, {VmServiceFactory vmServiceFactory = createVmServiceDelegate}) async {
    if (exception != null) {
      assert(exception is Exception || exception is Error);
      // ignore: only_throw_errors, exception is either Error or Exception here.
      throw exception!;
    }
    return result;
  }
}

class FakeChromeConnection extends Fake implements ChromeConnection {
  final List<ChromeTab> tabs = <ChromeTab>[];

  @override
  Future<ChromeTab> getTab(bool Function(ChromeTab tab) accept,
      {Duration? retryFor}) async {
    return tabs.firstWhere(accept);
  }

  @override
  Future<List<ChromeTab>> getTabs({Duration? retryFor}) async {
    return tabs;
  }
}

class FakeChromeTab extends Fake implements ChromeTab {
  FakeChromeTab(this.url);

  @override
  final String url;
  final FakeWipConnection connection = FakeWipConnection();

  @override
  Future<WipConnection> connect({Function? onError}) async {
    return connection;
  }
}

class FakeWipConnection extends Fake implements WipConnection {
  @override
  final WipDebugger debugger = FakeWipDebugger();
}

/// A test implementation of the [ChromiumLauncher] that launches a fixed instance.
class TestChromiumLauncher implements ChromiumLauncher {
  TestChromiumLauncher();

  bool _hasInstance = false;
  void setInstance(Chromium chromium) {
    _hasInstance = true;
    currentCompleter.complete(chromium);
  }

  @override
  Completer<Chromium> currentCompleter = Completer<Chromium>();

  @override
  bool canFindExecutable() {
    return true;
  }

  @override
  Future<Chromium> get connectedInstance => currentCompleter.future;

  @override
  String findExecutable() {
    return 'chrome';
  }

  @override
  bool get hasChromeInstance => _hasInstance;

  @override
  Future<Chromium> launch(
    String url, {
    bool headless = false,
    int? debugPort,
    bool skipCheck = false,
    Directory? cacheDir,
    List<String> webBrowserFlags = const <String>[],
  }) async {
    return currentCompleter.future;
  }

  @override
  Future<Chromium> connect(Chromium chrome, bool skipCheck) {
    return currentCompleter.future;
  }
}

class FakeFlutterDevice extends Fake implements FlutterDevice {
  Uri? testUri;
  UpdateFSReport report = UpdateFSReport(
    success: true,
    invalidatedSourcesCount: 1,
  );
  Exception? reportError;

  @override
  ResidentCompiler? generator;

  @override
  Stream<Uri?> get observatoryUris => Stream<Uri?>.value(testUri);

  @override
  DevelopmentShaderCompiler get developmentShaderCompiler => const FakeShaderCompiler();

  @override
  FlutterVmService? vmService;

  DevFS? _devFS;

  @override
  DevFS? get devFS => _devFS;

  @override
  set devFS(DevFS? value) {}

  @override
  Device? device;

  @override
  Future<void> stopEchoingDeviceLog() async {}

  @override
  Future<void> initLogReader() async {}

  @override
  Future<Uri?> setupDevFS(String fsName, Directory rootDirectory) async {
    return testUri;
  }

  @override
  Future<void> exitApps(
      {Duration timeoutDelay = const Duration(seconds: 10)}) async {}

  @override
  Future<void> connect({
    ReloadSources? reloadSources,
    Restart? restart,
    CompileExpression? compileExpression,
    GetSkSLMethod? getSkSLMethod,
    PrintStructuredErrorLogMethod? printStructuredErrorLogMethod,
    int? hostVmServicePort,
    int? ddsPort,
    bool disableServiceAuthCodes = false,
    bool enableDds = true,
    bool cacheStartupProfile = false,
    required bool allowExistingDdsInstance,
    bool? ipv6 = false,
  }) async {}

  @override
  Future<UpdateFSReport> updateDevFS({
    Uri? mainUri,
    String? target,
    AssetBundle? bundle,
    DateTime? firstBuildTime,
    bool bundleFirstUpload = false,
    bool bundleDirty = false,
    bool fullRestart = false,
    String? projectRootPath,
    String? pathToReload,
    String? dillOutputPath,
    List<Uri>? invalidatedFiles,
    PackageConfig? packageConfig,
    File? dartPluginRegistrant,
  }) async {
    if (reportError != null) {
      throw reportError!;
    }
    return report;
  }

  @override
  Future<void> updateReloadStatus(bool wasReloadSuccessful) async {}
}

class FakeShaderCompiler implements DevelopmentShaderCompiler {
  const FakeShaderCompiler();

  @override
  void configureCompiler(TargetPlatform? platform, { required bool enableImpeller }) { }

  @override
  Future<DevFSContent> recompileShader(DevFSContent inputShader) {
    throw UnimplementedError();
  }
}
