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

// @dart = 2.8

import 'package:file/memory.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/asset.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/build_info.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/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/run_hot.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart' as vm_service;

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

void main() {
  group('validateReloadReport', () {
    testUsingContext('invalid', () async {
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': false,
        'details': <String, dynamic>{},
      })), false);
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': false,
        'details': <String, dynamic>{
          'notices': <Map<String, dynamic>>[
          ],
        },
      })), false);
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': false,
        'details': <String, dynamic>{
          'notices': <String, dynamic>{
            'message': 'error',
          },
        },
      })), false);
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': false,
        'details': <String, dynamic>{
          'notices': <Map<String, dynamic>>[],
        },
      })), false);
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': false,
        'details': <String, dynamic>{
          'notices': <Map<String, dynamic>>[
            <String, dynamic>{'message': false},
          ],
        },
      })), false);
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': false,
        'details': <String, dynamic>{
          'notices': <Map<String, dynamic>>[
            <String, dynamic>{'message': <String>['error']},
          ],
        },
      })), false);
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': false,
        'details': <String, dynamic>{
          'notices': <Map<String, dynamic>>[
            <String, dynamic>{'message': 'error'},
            <String, dynamic>{'message': <String>['error']},
          ],
        },
      })), false);
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': false,
        'details': <String, dynamic>{
          'notices': <Map<String, dynamic>>[
            <String, dynamic>{'message': 'error'},
          ],
        },
      })), false);
      expect(HotRunner.validateReloadReport(vm_service.ReloadReport.parse(<String, dynamic>{
        'type': 'ReloadReport',
        'success': true,
      })), true);
    });

    testWithoutContext('ReasonForCancelling toString has a hint for specific errors', () {
      final ReasonForCancelling reasonForCancelling = ReasonForCancelling(
        message: 'Const class cannot remove fields',
      );

      expect(reasonForCancelling.toString(), contains('Try performing a hot restart instead.'));
    });
  });

  group('hotRestart', () {
    final FakeResidentCompiler residentCompiler = FakeResidentCompiler();
    FileSystem fileSystem;
    TestUsage testUsage;

    setUp(() {
      fileSystem = MemoryFileSystem.test();
      testUsage = TestUsage();
    });

    group('fails to setup', () {
      TestHotRunnerConfig failingTestingConfig;
      setUp(() {
        failingTestingConfig = TestHotRunnerConfig(
          successfulHotRestartSetup: false,
          successfulHotReloadSetup: false,
        );
      });

      testUsingContext('setupHotRestart function fails', () async {
        fileSystem.file('.packages')
          ..createSync(recursive: true)
          ..writeAsStringSync('\n');
        final FakeDevice device = FakeDevice();
        final List<FlutterDevice> devices = <FlutterDevice>[
          FlutterDevice(device, generator: residentCompiler, buildInfo: BuildInfo.debug, developmentShaderCompiler: const FakeShaderCompiler())
            ..devFS = FakeDevFs(),
        ];
        final OperationResult result = await HotRunner(
          devices,
          debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
          target: 'main.dart',
          devtoolsHandler: createNoOpHandler,
        ).restart(fullRestart: true);
        expect(result.isOk, false);
        expect(result.message, 'setupHotRestart failed');
        expect(failingTestingConfig.updateDevFSCompleteCalled, false);
      }, overrides: <Type, Generator>{
        HotRunnerConfig: () => failingTestingConfig,
        Artifacts: () => Artifacts.test(),
        FileSystem: () => fileSystem,
        Platform: () => FakePlatform(),
        ProcessManager: () => FakeProcessManager.any(),
      });

      testUsingContext('setupHotReload function fails', () async {
        fileSystem.file('.packages')
          ..createSync(recursive: true)
          ..writeAsStringSync('\n');
        final FakeDevice device = FakeDevice();
        final FakeFlutterDevice fakeFlutterDevice = FakeFlutterDevice(device);
        final List<FlutterDevice> devices = <FlutterDevice>[
          fakeFlutterDevice,
        ];
        final OperationResult result = await HotRunner(
          devices,
          debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
          target: 'main.dart',
          devtoolsHandler: createNoOpHandler,
          reassembleHelper: (
            List<FlutterDevice> flutterDevices,
            Map<FlutterDevice, List<FlutterView>> viewCache,
            void Function(String message) onSlow,
            String reloadMessage,
            String fastReassembleClassName,
          ) async => ReassembleResult(
              <FlutterView, FlutterVmService>{null: null},
              false,
              true,
            ),
        ).restart();
        expect(result.isOk, false);
        expect(result.message, 'setupHotReload failed');
        expect(failingTestingConfig.updateDevFSCompleteCalled, false);
      }, overrides: <Type, Generator>{
        HotRunnerConfig: () => failingTestingConfig,
        Artifacts: () => Artifacts.test(),
        FileSystem: () => fileSystem,
        Platform: () => FakePlatform(),
        ProcessManager: () => FakeProcessManager.any(),
      });
    });

    group('shutdown hook tests', () {
      TestHotRunnerConfig shutdownTestingConfig;

      setUp(() {
        shutdownTestingConfig = TestHotRunnerConfig();
      });

      testUsingContext('shutdown hook called after signal', () async {
        fileSystem.file('.packages')
          ..createSync(recursive: true)
          ..writeAsStringSync('\n');
        final FakeDevice device = FakeDevice();
        final List<FlutterDevice> devices = <FlutterDevice>[
          FlutterDevice(device, generator: residentCompiler, buildInfo: BuildInfo.debug, developmentShaderCompiler: const FakeShaderCompiler()),
        ];
        await HotRunner(
          devices,
          debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
          target: 'main.dart',
        ).cleanupAfterSignal();
        expect(shutdownTestingConfig.shutdownHookCalled, true);
      }, overrides: <Type, Generator>{
        HotRunnerConfig: () => shutdownTestingConfig,
        Artifacts: () => Artifacts.test(),
        FileSystem: () => fileSystem,
        Platform: () => FakePlatform(),
        ProcessManager: () => FakeProcessManager.any(),
      });

      testUsingContext('shutdown hook called after app stop', () async {
        fileSystem.file('.packages')
          ..createSync(recursive: true)
          ..writeAsStringSync('\n');
        final FakeDevice device = FakeDevice();
        final List<FlutterDevice> devices = <FlutterDevice>[
          FlutterDevice(device, generator: residentCompiler, buildInfo: BuildInfo.debug, developmentShaderCompiler: const FakeShaderCompiler()),
        ];
        await HotRunner(
          devices,
          debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
          target: 'main.dart',
        ).preExit();
        expect(shutdownTestingConfig.shutdownHookCalled, true);
      }, overrides: <Type, Generator>{
        HotRunnerConfig: () => shutdownTestingConfig,
        Artifacts: () => Artifacts.test(),
        FileSystem: () => fileSystem,
        Platform: () => FakePlatform(),
        ProcessManager: () => FakeProcessManager.any(),
      });
    });

    group('successful hot restart', () {
      TestHotRunnerConfig testingConfig;
      setUp(() {
        testingConfig = TestHotRunnerConfig(
          successfulHotRestartSetup: true,
        );
      });
      testUsingContext('correctly tracks time spent for analytics for hot restart', () async {
        final FakeDevice device = FakeDevice();
        final FakeFlutterDevice fakeFlutterDevice = FakeFlutterDevice(device);
        final List<FlutterDevice> devices = <FlutterDevice>[
          fakeFlutterDevice,
        ];

        fakeFlutterDevice.updateDevFSReportCallback = () async => UpdateFSReport(
          success: true,
          invalidatedSourcesCount: 2,
          syncedBytes: 4,
          scannedSourcesCount: 8,
          compileDuration: const Duration(seconds: 16),
          transferDuration: const Duration(seconds: 32),
        );

        final FakeStopwatchFactory fakeStopwatchFactory = FakeStopwatchFactory(
          stopwatches: <String, Stopwatch>{
            'fullRestartHelper': FakeStopwatch()..elapsed = const Duration(seconds: 64),
            'updateDevFS': FakeStopwatch()..elapsed = const Duration(seconds: 128),
          },
        );

        (fakeFlutterDevice.devFS as FakeDevFs).baseUri = Uri.parse('file:///base_uri');

        final OperationResult result = await HotRunner(
          devices,
          debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
          target: 'main.dart',
          devtoolsHandler: createNoOpHandler,
          stopwatchFactory: fakeStopwatchFactory,
        ).restart(fullRestart: true);

        expect(result.isOk, true);
        expect(testUsage.events, <TestUsageEvent>[
          const TestUsageEvent('hot', 'restart', parameters: CustomDimensions(
            hotEventTargetPlatform: 'flutter-tester',
            hotEventSdkName: 'Tester',
            hotEventEmulator: false,
            hotEventFullRestart: true,
            fastReassemble: false,
            hotEventOverallTimeInMs: 64000,
            hotEventSyncedBytes: 4,
            hotEventInvalidatedSourcesCount: 2,
            hotEventTransferTimeInMs: 32000,
            hotEventCompileTimeInMs: 16000,
            hotEventFindInvalidatedTimeInMs: 128000,
            hotEventScannedSourcesCount: 8,
          )),
        ]);
        expect(testingConfig.updateDevFSCompleteCalled, true);
      }, overrides: <Type, Generator>{
        HotRunnerConfig: () => testingConfig,
        Artifacts: () => Artifacts.test(),
        FileSystem: () => fileSystem,
        Platform: () => FakePlatform(),
        ProcessManager: () => FakeProcessManager.any(),
        Usage: () => testUsage,
      });
    });

    group('successful hot reload', () {
      TestHotRunnerConfig testingConfig;
      setUp(() {
        testingConfig = TestHotRunnerConfig(
          successfulHotReloadSetup: true,
        );
      });
      testUsingContext('correctly tracks time spent for analytics for hot reload', () async {
        final FakeDevice device = FakeDevice();
        final FakeFlutterDevice fakeFlutterDevice = FakeFlutterDevice(device);
        final List<FlutterDevice> devices = <FlutterDevice>[
          fakeFlutterDevice,
        ];

        fakeFlutterDevice.updateDevFSReportCallback = () async => UpdateFSReport(
          success: true,
          invalidatedSourcesCount: 6,
          syncedBytes: 8,
          scannedSourcesCount: 16,
          compileDuration: const Duration(seconds: 16),
          transferDuration: const Duration(seconds: 32),
        );

        final FakeStopwatchFactory fakeStopwatchFactory = FakeStopwatchFactory(
          stopwatches: <String, Stopwatch>{
            'updateDevFS': FakeStopwatch()..elapsed = const Duration(seconds: 64),
            'reloadSources:reload': FakeStopwatch()..elapsed = const Duration(seconds: 128),
            'reloadSources:reassemble': FakeStopwatch()..elapsed = const Duration(seconds: 256),
            'reloadSources:vm': FakeStopwatch()..elapsed = const Duration(seconds: 512),
          },
        );

        (fakeFlutterDevice.devFS as FakeDevFs).baseUri = Uri.parse('file:///base_uri');

        final OperationResult result = await HotRunner(
          devices,
          debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
          target: 'main.dart',
          devtoolsHandler: createNoOpHandler,
          stopwatchFactory: fakeStopwatchFactory,
          reloadSourcesHelper: (
            HotRunner hotRunner,
            List<FlutterDevice> flutterDevices,
            bool pause,
            Map<String, dynamic> firstReloadDetails,
            String targetPlatform,
            String sdkName,
            bool emulator,
            String reason,
          ) async {
            firstReloadDetails['finalLibraryCount'] = 2;
            firstReloadDetails['receivedLibraryCount'] = 3;
            firstReloadDetails['receivedClassesCount'] = 4;
            firstReloadDetails['receivedProceduresCount'] = 5;
            return OperationResult.ok;
          },
          reassembleHelper: (
            List<FlutterDevice> flutterDevices,
            Map<FlutterDevice, List<FlutterView>> viewCache,
            void Function(String message) onSlow,
            String reloadMessage,
            String fastReassembleClassName,
          ) async => ReassembleResult(
              <FlutterView, FlutterVmService>{null: null},
              false,
              true,
            ),
        ).restart();

        expect(result.isOk, true);
        expect(testUsage.events, <TestUsageEvent>[
          const TestUsageEvent('hot', 'reload', parameters: CustomDimensions(
            hotEventFinalLibraryCount: 2,
            hotEventSyncedLibraryCount: 3,
            hotEventSyncedClassesCount: 4,
            hotEventSyncedProceduresCount: 5,
            hotEventSyncedBytes: 8,
            hotEventInvalidatedSourcesCount: 6,
            hotEventTransferTimeInMs: 32000,
            hotEventOverallTimeInMs: 128000,
            hotEventTargetPlatform: 'flutter-tester',
            hotEventSdkName: 'Tester',
            hotEventEmulator: false,
            hotEventFullRestart: false,
            fastReassemble: false,
            hotEventCompileTimeInMs: 16000,
            hotEventFindInvalidatedTimeInMs: 64000,
            hotEventScannedSourcesCount: 16,
            hotEventReassembleTimeInMs: 256000,
            hotEventReloadVMTimeInMs: 512000,
          )),
        ]);
        expect(testingConfig.updateDevFSCompleteCalled, true);
      }, overrides: <Type, Generator>{
        HotRunnerConfig: () => testingConfig,
        Artifacts: () => Artifacts.test(),
        FileSystem: () => fileSystem,
        Platform: () => FakePlatform(),
        ProcessManager: () => FakeProcessManager.any(),
        Usage: () => testUsage,
      });
    });

    group('hot restart that failed to sync dev fs', () {
      TestHotRunnerConfig testingConfig;
      setUp(() {
        testingConfig = TestHotRunnerConfig(
          successfulHotRestartSetup: true,
        );
      });
      testUsingContext('still calls the devfs complete callback', () async {
        final FakeDevice device = FakeDevice();
        final FakeFlutterDevice fakeFlutterDevice = FakeFlutterDevice(device);
        final List<FlutterDevice> devices = <FlutterDevice>[
          fakeFlutterDevice,
        ];
        fakeFlutterDevice.updateDevFSReportCallback = () async => throw Exception('updateDevFS failed');

        final HotRunner runner = HotRunner(
          devices,
          debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
          target: 'main.dart',
          devtoolsHandler: createNoOpHandler,
        );

        await expectLater(runner.restart(fullRestart: true), throwsA(isA<Exception>().having((Exception e) => e.toString(), 'message', 'Exception: updateDevFS failed')));
        expect(testingConfig.updateDevFSCompleteCalled, true);
      }, overrides: <Type, Generator>{
        HotRunnerConfig: () => testingConfig,
        Artifacts: () => Artifacts.test(),
        FileSystem: () => fileSystem,
        Platform: () => FakePlatform(),
        ProcessManager: () => FakeProcessManager.any(),
        Usage: () => testUsage,
      });
    });

    group('hot reload that failed to sync dev fs', () {
      TestHotRunnerConfig testingConfig;
      setUp(() {
        testingConfig = TestHotRunnerConfig(
          successfulHotReloadSetup: true,
        );
      });
      testUsingContext('still calls the devfs complete callback', () async {
        final FakeDevice device = FakeDevice();
        final FakeFlutterDevice fakeFlutterDevice = FakeFlutterDevice(device);
        final List<FlutterDevice> devices = <FlutterDevice>[
          fakeFlutterDevice,
        ];
        fakeFlutterDevice.updateDevFSReportCallback = () async => throw Exception('updateDevFS failed');

        final HotRunner runner = HotRunner(
          devices,
          debuggingOptions: DebuggingOptions.disabled(BuildInfo.debug),
          target: 'main.dart',
          devtoolsHandler: createNoOpHandler,
        );

        await expectLater(runner.restart(), throwsA(isA<Exception>().having((Exception e) => e.toString(), 'message', 'Exception: updateDevFS failed')));
        expect(testingConfig.updateDevFSCompleteCalled, true);
      }, overrides: <Type, Generator>{
        HotRunnerConfig: () => testingConfig,
        Artifacts: () => Artifacts.test(),
        FileSystem: () => fileSystem,
        Platform: () => FakePlatform(),
        ProcessManager: () => FakeProcessManager.any(),
        Usage: () => testUsage,
      });
    });
  });

  group('hot attach', () {
    FileSystem fileSystem;

    setUp(() {
      fileSystem = MemoryFileSystem.test();
    });

    testUsingContext('Exits with code 2 when HttpException is thrown '
      'during VM service connection', () async {
      fileSystem.file('.packages')
        ..createSync(recursive: true)
        ..writeAsStringSync('\n');

      final FakeResidentCompiler residentCompiler = FakeResidentCompiler();
      final FakeDevice device = FakeDevice();
      final List<FlutterDevice> devices = <FlutterDevice>[
        TestFlutterDevice(
          device: device,
          generator: residentCompiler,
          exception: const HttpException('Connection closed before full header was received, '
              'uri = http://127.0.0.1:63394/5ZmLv8A59xY=/ws'),
        ),
      ];

      final int exitCode = await HotRunner(devices,
        debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
        target: 'main.dart',
      ).attach(needsFullRestart: false);
      expect(exitCode, 2);
    }, overrides: <Type, Generator>{
      HotRunnerConfig: () => TestHotRunnerConfig(),
      Artifacts: () => Artifacts.test(),
      FileSystem: () => fileSystem,
      Platform: () => FakePlatform(),
      ProcessManager: () => FakeProcessManager.any(),
    });
  });

  group('hot cleanupAtFinish()', () {
    testUsingContext('disposes each device', () async {
      final FakeDevice device1 = FakeDevice();
      final FakeDevice device2 = FakeDevice();
      final FakeFlutterDevice flutterDevice1 = FakeFlutterDevice(device1);
      final FakeFlutterDevice flutterDevice2 = FakeFlutterDevice(device2);

      final List<FlutterDevice> devices = <FlutterDevice>[
        flutterDevice1,
        flutterDevice2,
      ];

      await HotRunner(devices,
        debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
        target: 'main.dart',
      ).cleanupAtFinish();

      expect(device1.disposed, true);
      expect(device2.disposed, true);

      expect(flutterDevice1.stoppedEchoingDeviceLog, true);
      expect(flutterDevice2.stoppedEchoingDeviceLog, true);
    });
  });
}

class FakeDevFs extends Fake implements DevFS {
  @override
  Future<void> destroy() async { }

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

  @override
  DateTime lastCompiled;

  @override
  PackageConfig lastPackageConfig;

  @override
  Set<String> assetPathsToEvict = <String>{};

  @override
  Set<String> shaderPathsToEvict= <String>{};

  @override
  Uri baseUri;
}

// 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 {
  bool disposed = false;

  @override
  bool isSupported() => true;

  @override
  bool supportsHotReload = true;

  @override
  bool supportsHotRestart = true;

  @override
  bool supportsFlutterExit = true;

  @override
  Future<TargetPlatform> get targetPlatform async => TargetPlatform.tester;

  @override
  Future<String> get sdkNameAndVersion async => 'Tester';

  @override
  Future<bool> get isLocalEmulator async => false;

  @override
  String get name => 'Fake Device';

  @override
  Future<bool> stopApp(
    covariant ApplicationPackage app, {
    String userIdentifier,
  }) async {
    return true;
  }

  @override
  Future<void> dispose() async {
    disposed = true;
  }
}

class FakeFlutterDevice extends Fake implements FlutterDevice {
  FakeFlutterDevice(this.device);

  bool stoppedEchoingDeviceLog = false;
  Future<UpdateFSReport> Function() updateDevFSReportCallback;

  @override
  final FakeDevice device;

  @override
  Future<void> stopEchoingDeviceLog() async {
    stoppedEchoingDeviceLog = true;
  }

  @override
  DevFS devFS = FakeDevFs();

  @override
  FlutterVmService get vmService => FakeFlutterVmService();

  @override
  ResidentCompiler generator;

  @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,
    @required String dillOutputPath,
    @required List<Uri> invalidatedFiles,
    @required PackageConfig packageConfig,
  }) => updateDevFSReportCallback();
}

class TestFlutterDevice extends FlutterDevice {
  TestFlutterDevice({
    @required Device device,
    @required this.exception,
    @required ResidentCompiler generator,
  })  : assert(exception != null),
        super(device, buildInfo: BuildInfo.debug, generator: generator, developmentShaderCompiler: const FakeShaderCompiler());

  /// The exception to throw when the connect method is called.
  final Exception exception;

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

class TestHotRunnerConfig extends HotRunnerConfig {
  TestHotRunnerConfig({this.successfulHotRestartSetup, this.successfulHotReloadSetup});
  bool successfulHotRestartSetup;
  bool successfulHotReloadSetup;
  bool shutdownHookCalled = false;
  bool updateDevFSCompleteCalled = false;

  @override
  Future<bool> setupHotRestart() async {
    assert(successfulHotRestartSetup != null, 'setupHotRestart is not expected to be called in this test.');
    return successfulHotRestartSetup;
  }

  @override
  Future<bool> setupHotReload() async {
    assert(successfulHotReloadSetup != null, 'setupHotReload is not expected to be called in this test.');
    return successfulHotReloadSetup;
  }

  @override
  void updateDevFSComplete() {
    updateDevFSCompleteCalled = true;
  }

  @override
  Future<void> runPreShutdownOperations() async {
    shutdownHookCalled = true;
  }
}

class FakeResidentCompiler extends Fake implements ResidentCompiler {
  @override
  void accept() {}
}

class FakeFlutterVmService extends Fake implements FlutterVmService {
  @override
  vm_service.VmService get service => FakeVmService();

  @override
  Future<List<FlutterView>> getFlutterViews({bool returnEarly = false, Duration delay = const Duration(milliseconds: 50)}) async {
    return <FlutterView>[];
  }
}

class FakeVmService extends Fake implements vm_service.VmService {
  @override
  Future<vm_service.VM> getVM() async => FakeVm();
}

class FakeVm extends Fake implements vm_service.VM {
  @override
  List<vm_service.IsolateRef> get isolates => <vm_service.IsolateRef>[];
}

class FakeShaderCompiler implements DevelopmentShaderCompiler {
  const FakeShaderCompiler();

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

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