// Copyright 2017 The Chromium 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:file/memory.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart' as io;
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.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/features.dart';
import 'package:flutter_tools/src/globals.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/resident_runner.dart';
import 'package:flutter_tools/src/run_cold.dart';
import 'package:flutter_tools/src/run_hot.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:json_rpc_2/json_rpc_2.dart';
import 'package:mockito/mockito.dart';

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

void main() {
  final Uri testUri = Uri.parse('foo://bar');
  Testbed testbed;
  MockFlutterDevice mockFlutterDevice;
  MockVMService mockVMService;
  MockDevFS mockDevFS;
  MockFlutterView mockFlutterView;
  ResidentRunner residentRunner;
  MockDevice mockDevice;
  MockIsolate mockIsolate;

  setUp(() {
    testbed = Testbed(setup: () {
      fs.file(fs.path.join('build', 'app.dill'))
        ..createSync(recursive: true)
        ..writeAsStringSync('ABC');
      residentRunner = HotRunner(
        <FlutterDevice>[
          mockFlutterDevice,
        ],
        stayResident: false,
        debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      );
    });
    mockFlutterDevice = MockFlutterDevice();
    mockDevice = MockDevice();
    mockVMService = MockVMService();
    mockDevFS = MockDevFS();
    mockFlutterView = MockFlutterView();
    mockIsolate = MockIsolate();
    // DevFS Mocks
    when(mockDevFS.lastCompiled).thenReturn(DateTime(2000));
    when(mockDevFS.sources).thenReturn(<Uri>[]);
    when(mockDevFS.baseUri).thenReturn(Uri());
    when(mockDevFS.destroy()).thenAnswer((Invocation invocation) async { });
    when(mockDevFS.assetPathsToEvict).thenReturn(<String>{});
    // FlutterDevice Mocks.
    when(mockFlutterDevice.updateDevFS(
      // Intentionally provide empty list to match above mock.
      invalidatedFiles: <Uri>[],
      mainPath: anyNamed('mainPath'),
      target: anyNamed('target'),
      bundle: anyNamed('bundle'),
      firstBuildTime: anyNamed('firstBuildTime'),
      bundleFirstUpload: anyNamed('bundleFirstUpload'),
      bundleDirty: anyNamed('bundleDirty'),
      fullRestart: anyNamed('fullRestart'),
      projectRootPath: anyNamed('projectRootPath'),
      pathToReload: anyNamed('pathToReload'),
      dillOutputPath: anyNamed('dillOutputPath'),
    )).thenAnswer((Invocation invocation) async {
      return UpdateFSReport(
        success: true,
        syncedBytes: 0,
        invalidatedSourcesCount: 0,
      );
    });
    when(mockFlutterDevice.devFS).thenReturn(mockDevFS);
    when(mockFlutterDevice.views).thenReturn(<FlutterView>[
      mockFlutterView,
    ]);
    when(mockFlutterDevice.device).thenReturn(mockDevice);
    when(mockFlutterView.uiIsolate).thenReturn(mockIsolate);
    when(mockFlutterView.runFromSource(any, any, any)).thenAnswer((Invocation invocation) async {});
    when(mockFlutterDevice.stopEchoingDeviceLog()).thenAnswer((Invocation invocation) async { });
    when(mockFlutterDevice.observatoryUris).thenAnswer((_) => Stream<Uri>.value(testUri));
    when(mockFlutterDevice.connect(
      reloadSources: anyNamed('reloadSources'),
      restart: anyNamed('restart'),
      compileExpression: anyNamed('compileExpression'),
    )).thenAnswer((Invocation invocation) async { });
    when(mockFlutterDevice.setupDevFS(any, any, packagesFilePath: anyNamed('packagesFilePath')))
      .thenAnswer((Invocation invocation) async {
        return testUri;
      });
    when(mockFlutterDevice.vmServices).thenReturn(<VMService>[
      mockVMService,
    ]);
    when(mockFlutterDevice.refreshViews()).thenAnswer((Invocation invocation) async { });
    when(mockFlutterDevice.reloadSources(any, pause: anyNamed('pause'))).thenReturn(<Future<Map<String, dynamic>>>[
      Future<Map<String, dynamic>>.value(<String, dynamic>{
        'type': 'ReloadReport',
        'success': true,
        'details': <String, dynamic>{
          'loadedLibraryCount': 1,
          'finalLibraryCount': 1,
          'receivedLibraryCount': 1,
          'receivedClassesCount': 1,
          'receivedProceduresCount': 1,
        },
      }),
    ]);
    // VMService mocks.
    when(mockVMService.wsAddress).thenReturn(testUri);
    when(mockVMService.done).thenAnswer((Invocation invocation) {
      final Completer<void> result = Completer<void>.sync();
      return result.future;
    });
    when(mockIsolate.resume()).thenAnswer((Invocation invocation) {
      return Future<Map<String, Object>>.value(null);
    });
    when(mockIsolate.flutterExit()).thenAnswer((Invocation invocation) {
      return Future<Map<String, Object>>.value(null);
    });
    when(mockIsolate.reload()).thenAnswer((Invocation invocation) {
      return Future<ServiceObject>.value(null);
    });
  });

  test('ResidentRunner can attach to device successfully', () => testbed.run(() async {
    final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
    final Completer<void> onAppStart = Completer<void>.sync();
    final Future<int> result = residentRunner.attach(
      appStartedCompleter: onAppStart,
      connectionInfoCompleter: onConnectionInfo,
    );
    final Future<DebugConnectionInfo> connectionInfo = onConnectionInfo.future;

    expect(await result, 0);

    verify(mockFlutterDevice.initLogReader()).called(1);

    expect(onConnectionInfo.isCompleted, true);
    expect((await connectionInfo).baseUri, 'foo://bar');
    expect(onAppStart.isCompleted, true);
  }));

  test('ResidentRunner can handle an RPC exception from hot reload', () => testbed.run(() async {
    when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
      return 'Example';
    });
    when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
      return TargetPlatform.android_arm;
    });
    when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
      return false;
    });
    final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
    final Completer<void> onAppStart = Completer<void>.sync();
    unawaited(residentRunner.attach(
      appStartedCompleter: onAppStart,
      connectionInfoCompleter: onConnectionInfo,
    ));
    await onAppStart.future;
    when(mockFlutterDevice.updateDevFS(
      mainPath: anyNamed('mainPath'),
      target: anyNamed('target'),
      bundle: anyNamed('bundle'),
      firstBuildTime: anyNamed('firstBuildTime'),
      bundleFirstUpload: anyNamed('bundleFirstUpload'),
      bundleDirty: anyNamed('bundleDirty'),
      fullRestart: anyNamed('fullRestart'),
      projectRootPath: anyNamed('projectRootPath'),
      pathToReload: anyNamed('pathToReload'),
      invalidatedFiles: anyNamed('invalidatedFiles'),
      dillOutputPath: anyNamed('dillOutputPath'),
    )).thenThrow(RpcException(666, 'something bad happened'));

    final OperationResult result = await residentRunner.restart(fullRestart: false);
    expect(result.fatal, true);
    expect(result.code, 1);
    verify(flutterUsage.sendEvent('hot', 'exception', parameters: <String, String>{
      cdKey(CustomDimensions.hotEventTargetPlatform):
        getNameForTargetPlatform(TargetPlatform.android_arm),
      cdKey(CustomDimensions.hotEventSdkName): 'Example',
      cdKey(CustomDimensions.hotEventEmulator): 'false',
      cdKey(CustomDimensions.hotEventFullRestart): 'false',
    })).called(1);
  }, overrides: <Type, Generator>{
    Usage: () => MockUsage(),
  }));

  test('ResidentRunner copies dill file from build output into temp directory', () => testbed.run(() async {
    expect(residentRunner.artifactDirectory.childFile('app.dill').readAsStringSync(), 'ABC');
  }));

  test('ResidentRunner can send target platform to analytics from hot reload', () => testbed.run(() async {
    when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
      return 'Example';
    });
    when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
      return TargetPlatform.android_arm;
    });
    when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
      return false;
    });
    final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
    final Completer<void> onAppStart = Completer<void>.sync();
    unawaited(residentRunner.attach(
      appStartedCompleter: onAppStart,
      connectionInfoCompleter: onConnectionInfo,
    ));

    final OperationResult result = await residentRunner.restart(fullRestart: false);
    expect(result.fatal, false);
    expect(result.code, 0);
    expect(verify(flutterUsage.sendEvent('hot', 'reload',
                  parameters: captureAnyNamed('parameters'))).captured[0],
      containsPair(cdKey(CustomDimensions.hotEventTargetPlatform),
                   getNameForTargetPlatform(TargetPlatform.android_arm)),
    );
  }, overrides: <Type, Generator>{
    Usage: () => MockUsage(),
  }));

  test('ResidentRunner can send target platform to analytics from full restart', () => testbed.run(() async {
    when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
      return 'Example';
    });
    when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
      return TargetPlatform.android_arm;
    });
    when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
      return false;
    });
    when(mockDevice.supportsHotRestart).thenReturn(true);
    final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
    final Completer<void> onAppStart = Completer<void>.sync();
    unawaited(residentRunner.attach(
      appStartedCompleter: onAppStart,
      connectionInfoCompleter: onConnectionInfo,
    ));

    final OperationResult result = await residentRunner.restart(fullRestart: true);
    expect(result.fatal, false);
    expect(result.code, 0);
    expect(verify(flutterUsage.sendEvent('hot', 'restart',
                  parameters: captureAnyNamed('parameters'))).captured[0],
      containsPair(cdKey(CustomDimensions.hotEventTargetPlatform),
                   getNameForTargetPlatform(TargetPlatform.android_arm)),
    );
  }, overrides: <Type, Generator>{
    Usage: () => MockUsage(),
  }));

  test('ResidentRunner Can handle an RPC exception from hot restart', () => testbed.run(() async {
    when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
      return 'Example';
    });
    when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
      return TargetPlatform.android_arm;
    });
    when(mockDevice.isLocalEmulator).thenAnswer((Invocation invocation) async {
      return false;
    });
    when(mockDevice.supportsHotRestart).thenReturn(true);
    final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
    final Completer<void> onAppStart = Completer<void>.sync();
    unawaited(residentRunner.attach(
      appStartedCompleter: onAppStart,
      connectionInfoCompleter: onConnectionInfo,
    ));
    await onAppStart.future;
    when(mockFlutterDevice.updateDevFS(
      mainPath: anyNamed('mainPath'),
      target: anyNamed('target'),
      bundle: anyNamed('bundle'),
      firstBuildTime: anyNamed('firstBuildTime'),
      bundleFirstUpload: anyNamed('bundleFirstUpload'),
      bundleDirty: anyNamed('bundleDirty'),
      fullRestart: anyNamed('fullRestart'),
      projectRootPath: anyNamed('projectRootPath'),
      pathToReload: anyNamed('pathToReload'),
      invalidatedFiles: anyNamed('invalidatedFiles'),
      dillOutputPath: anyNamed('dillOutputPath'),
    )).thenThrow(RpcException(666, 'something bad happened'));

    final OperationResult result = await residentRunner.restart(fullRestart: true);
    expect(result.fatal, true);
    expect(result.code, 1);
    verify(flutterUsage.sendEvent('hot', 'exception', parameters: <String, String>{
      cdKey(CustomDimensions.hotEventTargetPlatform):
        getNameForTargetPlatform(TargetPlatform.android_arm),
      cdKey(CustomDimensions.hotEventSdkName): 'Example',
      cdKey(CustomDimensions.hotEventEmulator): 'false',
      cdKey(CustomDimensions.hotEventFullRestart): 'true',
    })).called(1);
  }, overrides: <Type, Generator>{
    Usage: () => MockUsage(),
  }));

  test('ResidentRunner uses temp directory when there is no output dill path', () => testbed.run(() {
    expect(residentRunner.artifactDirectory.path, contains('flutter_tool.'));

    final ResidentRunner otherRunner = HotRunner(
      <FlutterDevice>[
        mockFlutterDevice,
      ],
      stayResident: false,
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug),
      dillOutputPath: fs.path.join('foobar', 'app.dill'),
    );
    expect(otherRunner.artifactDirectory.path, contains('foobar'));
  }));

  test('ResidentRunner printHelpDetails', () => testbed.run(() {
    when(mockDevice.supportsHotRestart).thenReturn(true);
    when(mockDevice.supportsScreenshot).thenReturn(true);

    residentRunner.printHelp(details: true);
    final BufferLogger bufferLogger = context.get<Logger>();

    // supports service protocol
    expect(residentRunner.supportsServiceProtocol, true);
    expect(bufferLogger.statusText, contains('"w"'));
    expect(bufferLogger.statusText, contains('"t"'));
    expect(bufferLogger.statusText, contains('"P"'));
    expect(bufferLogger.statusText, contains('"a"'));
    // isRunningDebug
    expect(residentRunner.isRunningDebug, true);
    expect(bufferLogger.statusText, contains('"L"'));
    expect(bufferLogger.statusText, contains('"S"'));
    expect(bufferLogger.statusText, contains('"U"'));
    expect(bufferLogger.statusText, contains('"i"'));
    expect(bufferLogger.statusText, contains('"p"'));
    expect(bufferLogger.statusText, contains('"o"'));
    expect(bufferLogger.statusText, contains('"z"'));
    // screenshot
    expect(bufferLogger.statusText, contains('"s"'));
  }));

  test('ResidentRunner can take screenshot on debug device', () => testbed.run(() async {
    when(mockDevice.supportsScreenshot).thenReturn(true);
    when(mockDevice.takeScreenshot(any))
      .thenAnswer((Invocation invocation) async {
        final File file = invocation.positionalArguments.first;
        file.writeAsBytesSync(List<int>.generate(1024, (int i) => i));
      });
    final BufferLogger bufferLogger = context.get<Logger>();

    await residentRunner.screenshot(mockFlutterDevice);

    // disables debug banner.
    verify(mockIsolate.flutterDebugAllowBanner(false)).called(1);
    // Enables debug banner.
    verify(mockIsolate.flutterDebugAllowBanner(true)).called(1);
    expect(bufferLogger.statusText, contains('1kB'));
  }));

  test('ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws pre', () => testbed.run(() async {
    when(mockDevice.supportsScreenshot).thenReturn(true);
    when(mockIsolate.flutterDebugAllowBanner(false)).thenThrow(Exception());
    final BufferLogger bufferLogger = context.get<Logger>();

    await residentRunner.screenshot(mockFlutterDevice);

    expect(bufferLogger.errorText, contains('Error'));
  }));

  test('ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws post', () => testbed.run(() async {
    when(mockDevice.supportsScreenshot).thenReturn(true);
    when(mockIsolate.flutterDebugAllowBanner(true)).thenThrow(Exception());
    final BufferLogger bufferLogger = context.get<Logger>();

    await residentRunner.screenshot(mockFlutterDevice);

    expect(bufferLogger.errorText, contains('Error'));
  }));

  test('ResidentRunner bails taking screenshot on debug device if takeScreenshot throws', () => testbed.run(() async {
    when(mockDevice.supportsScreenshot).thenReturn(true);
    when(mockDevice.takeScreenshot(any)).thenThrow(Exception());
    final BufferLogger bufferLogger = context.get<Logger>();

    await residentRunner.screenshot(mockFlutterDevice);

    expect(bufferLogger.errorText, contains('Error'));
  }));

  test('ResidentRunner can\'t take screenshot on device without support', () => testbed.run(() {
    when(mockDevice.supportsScreenshot).thenReturn(false);

    expect(() => residentRunner.screenshot(mockFlutterDevice),
        throwsA(isInstanceOf<AssertionError>()));
  }));

  test('ResidentRunner does not toggle banner in non-debug mode', () => testbed.run(() async {
    residentRunner = HotRunner(
      <FlutterDevice>[
        mockFlutterDevice,
      ],
      stayResident: false,
      debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
    );
    when(mockDevice.supportsScreenshot).thenReturn(true);
    when(mockDevice.takeScreenshot(any))
      .thenAnswer((Invocation invocation) async {
        final File file = invocation.positionalArguments.first;
        file.writeAsBytesSync(List<int>.generate(1024, (int i) => i));
      });
    final BufferLogger bufferLogger = context.get<Logger>();

    await residentRunner.screenshot(mockFlutterDevice);

    // doesn't disabled debug banner.
    verifyNever(mockIsolate.flutterDebugAllowBanner(false));
    // doesn't enable debug banner.
    verifyNever(mockIsolate.flutterDebugAllowBanner(true));
    expect(bufferLogger.statusText, contains('1kB'));
  }));

  test('FlutterDevice will not exit a paused isolate', () => testbed.run(() async {
    final TestFlutterDevice flutterDevice = TestFlutterDevice(
      mockDevice,
      <FlutterView>[ mockFlutterView ],
    );
    final MockServiceEvent mockServiceEvent = MockServiceEvent();
    when(mockServiceEvent.isPauseEvent).thenReturn(true);
    when(mockIsolate.pauseEvent).thenReturn(mockServiceEvent);
    when(mockDevice.supportsFlutterExit).thenReturn(true);

    await flutterDevice.exitApps();

    verifyNever(mockIsolate.flutterExit());
    verify(mockDevice.stopApp(any)).called(1);
  }));

  test('FlutterDevice will exit an un-paused isolate', () => testbed.run(() async {
    final TestFlutterDevice flutterDevice = TestFlutterDevice(
      mockDevice,
      <FlutterView> [mockFlutterView ],
    );

    final MockServiceEvent mockServiceEvent = MockServiceEvent();
    when(mockServiceEvent.isPauseEvent).thenReturn(false);
    when(mockIsolate.pauseEvent).thenReturn(mockServiceEvent);
    when(mockDevice.supportsFlutterExit).thenReturn(true);

    await flutterDevice.exitApps();

    verify(mockIsolate.flutterExit()).called(1);
  }));

  test('ResidentRunner refreshViews calls flutter device', () => testbed.run(() async {
    await residentRunner.refreshViews();

    verify(mockFlutterDevice.refreshViews()).called(1);
  }));

  test('ResidentRunner debugDumpApp calls flutter device', () => testbed.run(() async {
    await residentRunner.debugDumpApp();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.debugDumpApp()).called(1);
  }));

  test('ResidentRunner debugDumpRenderTree calls flutter device', () => testbed.run(() async {
    await residentRunner.debugDumpRenderTree();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.debugDumpRenderTree()).called(1);
  }));

  test('ResidentRunner debugDumpLayerTree calls flutter device', () => testbed.run(() async {
    await residentRunner.debugDumpLayerTree();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.debugDumpLayerTree()).called(1);
  }));

  test('ResidentRunner debugDumpSemanticsTreeInTraversalOrder calls flutter device', () => testbed.run(() async {
    await residentRunner.debugDumpSemanticsTreeInTraversalOrder();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.debugDumpSemanticsTreeInTraversalOrder()).called(1);
  }));

  test('ResidentRunner debugDumpSemanticsTreeInInverseHitTestOrder calls flutter device', () => testbed.run(() async {
    await residentRunner.debugDumpSemanticsTreeInInverseHitTestOrder();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.debugDumpSemanticsTreeInInverseHitTestOrder()).called(1);
  }));

  test('ResidentRunner debugToggleDebugPaintSizeEnabled calls flutter device', () => testbed.run(() async {
    await residentRunner.debugToggleDebugPaintSizeEnabled();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.toggleDebugPaintSizeEnabled()).called(1);
  }));

  test('ResidentRunner debugToggleDebugCheckElevationsEnabled calls flutter device', () => testbed.run(() async {
    await residentRunner.debugToggleDebugCheckElevationsEnabled();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.toggleDebugCheckElevationsEnabled()).called(1);
  }));

  test('ResidentRunner debugTogglePerformanceOverlayOverride calls flutter device', () => testbed.run(()async {
    await residentRunner.debugTogglePerformanceOverlayOverride();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.debugTogglePerformanceOverlayOverride()).called(1);
  }));

  test('ResidentRunner debugToggleWidgetInspector calls flutter device', () => testbed.run(() async {
    await residentRunner.debugToggleWidgetInspector();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.toggleWidgetInspector()).called(1);
  }));

  test('ResidentRunner debugToggleProfileWidgetBuilds calls flutter device', () => testbed.run(() async {
    await residentRunner.debugToggleProfileWidgetBuilds();

    verify(mockFlutterDevice.refreshViews()).called(1);
    verify(mockFlutterDevice.toggleProfileWidgetBuilds()).called(1);
  }));

  test('HotRunner writes vm service file when providing debugging option', () => testbed.run(() async {
    fs.file(fs.path.join('lib', 'main.dart')).createSync(recursive: true);
    residentRunner = HotRunner(
      <FlutterDevice>[
        mockFlutterDevice,
      ],
      stayResident: false,
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, vmserviceOutFile: 'foo'),
    );
    when(mockFlutterDevice.runHot(
      hotRunner: anyNamed('hotRunner'),
      route: anyNamed('route'),
    )).thenAnswer((Invocation invocation) async {
      return 0;
    });
    await residentRunner.run();

    expect(await fs.file('foo').readAsString(), testUri.toString());
  }));

  test('HotRunner handles failure to write vmservice file', () => testbed.run(() async {
    final BufferLogger bufferLogger = logger;
    fs.file(fs.path.join('lib', 'main.dart')).createSync(recursive: true);
    residentRunner = HotRunner(
      <FlutterDevice>[
        mockFlutterDevice,
      ],
      stayResident: false,
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.debug, vmserviceOutFile: 'foo'),
    );
    when(mockFlutterDevice.runHot(
      hotRunner: anyNamed('hotRunner'),
      route: anyNamed('route'),
    )).thenAnswer((Invocation invocation) async {
      return 0;
    });
    await residentRunner.run();

    expect(bufferLogger.errorText, contains('Failed to write vmservice-out-file at foo'));
  }, overrides: <Type, Generator>{
    FileSystem: () => ThrowingForwardingFileSystem(MemoryFileSystem()),
  }));


  test('ColdRunner writes vm service file when providing debugging option', () => testbed.run(() async {
    fs.file(fs.path.join('lib', 'main.dart')).createSync(recursive: true);
    residentRunner = ColdRunner(
      <FlutterDevice>[
        mockFlutterDevice,
      ],
      stayResident: false,
      debuggingOptions: DebuggingOptions.enabled(BuildInfo.profile, vmserviceOutFile: 'foo'),
    );
    when(mockFlutterDevice.runCold(
      coldRunner: anyNamed('coldRunner'),
      route: anyNamed('route'),
    )).thenAnswer((Invocation invocation) async {
      return 0;
    });
    await residentRunner.run();

    expect(await fs.file('foo').readAsString(), testUri.toString());
  }));

  test('FlutterDevice uses dartdevc configuration when targeting web', () => testbed.run(() async {
    final MockDevice mockDevice = MockDevice();
    when(mockDevice.targetPlatform).thenAnswer((Invocation invocation) async {
      return TargetPlatform.web_javascript;
    });

    final DefaultResidentCompiler residentCompiler = (await FlutterDevice.create(
      mockDevice,
      buildMode: BuildMode.debug,
      flutterProject: FlutterProject.current(),
      target: null,
      trackWidgetCreation: true,
    )).generator;

    expect(residentCompiler.targetModel, TargetModel.dartdevc);
    expect(residentCompiler.sdkRoot,
      artifacts.getArtifactPath(Artifact.flutterWebSdk, mode: BuildMode.debug) + '/');
    expect(residentCompiler.platformDill,
      artifacts.getArtifactPath(Artifact.webPlatformKernelDill, mode: BuildMode.debug));
  }, overrides: <Type, Generator>{
    FeatureFlags: () => TestFeatureFlags(isWebIncrementalCompilerEnabled: true),
  }));

  test('connect sets up log reader', () => testbed.run(() async {
    final MockDevice mockDevice = MockDevice();
    final MockDeviceLogReader mockLogReader = MockDeviceLogReader();
    when(mockDevice.getLogReader(app: anyNamed('app'))).thenReturn(mockLogReader);

    final TestFlutterDevice flutterDevice = TestFlutterDevice(
      mockDevice,
      <FlutterView>[],
      observatoryUris: Stream<Uri>.value(testUri),
    );

    await flutterDevice.connect();
    verify(mockLogReader.connectedVMServices = <VMService>[ mockVMService ]);
  }, overrides: <Type, Generator>{
    VMServiceConnector: () => (Uri httpUri, { ReloadSources reloadSources, Restart restart, CompileExpression compileExpression, io.CompressionOptions compression }) async => mockVMService,
  }));
}

class MockFlutterDevice extends Mock implements FlutterDevice {}
class MockFlutterView extends Mock implements FlutterView {}
class MockVMService extends Mock implements VMService {}
class MockDevFS extends Mock implements DevFS {}
class MockIsolate extends Mock implements Isolate {}
class MockDevice extends Mock implements Device {}
class MockDeviceLogReader extends Mock implements DeviceLogReader {}
class MockUsage extends Mock implements Usage {}
class MockProcessManager extends Mock implements ProcessManager {}
class MockServiceEvent extends Mock implements ServiceEvent {}
class TestFlutterDevice extends FlutterDevice {
  TestFlutterDevice(Device device, this.views, { Stream<Uri> observatoryUris })
    : super(device, buildMode: BuildMode.debug, trackWidgetCreation: false) {
    _observatoryUris = observatoryUris;
  }

  @override
  final List<FlutterView> views;

  @override
  Stream<Uri> get observatoryUris => _observatoryUris;
  Stream<Uri> _observatoryUris;
}

class ThrowingForwardingFileSystem extends ForwardingFileSystem {
  ThrowingForwardingFileSystem(FileSystem delegate) : super(delegate);

  @override
  File file(dynamic path) {
    if (path == 'foo') {
      throw const FileSystemException();
    }
    return delegate.file(path);
  }
}
