// 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 'dart:async';
import 'dart:io' as io;
import 'dart:typed_data';

import 'package:fake_async/fake_async.dart';
import 'package:file/src/interface/file.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/android/android_workflow.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/utils.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/commands/daemon.dart';
import 'package:flutter_tools/src/daemon.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/features.dart';
import 'package:flutter_tools/src/fuchsia/fuchsia_workflow.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/ios/ios_workflow.dart';
import 'package:flutter_tools/src/resident_runner.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:test/fake.dart';

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

/// Runs a callback using FakeAsync.run while continually pumping the
/// microtask queue. This avoids a deadlock when tests `await` a Future
/// which queues a microtask that will not be processed unless the queue
/// is flushed.
Future<T> _runFakeAsync<T>(Future<T> Function(FakeAsync time) f) async {
  return FakeAsync().run((FakeAsync time) async {
    bool pump = true;
    final Future<T> future = f(time).whenComplete(() => pump = false);
    while (pump) {
      time.flushMicrotasks();
    }
    return future;
  });
}

class FakeDaemonStreams implements DaemonStreams {
  final StreamController<DaemonMessage> inputs = StreamController<DaemonMessage>();
  final StreamController<DaemonMessage> outputs = StreamController<DaemonMessage>();

  @override
  Stream<DaemonMessage> get inputStream {
    return inputs.stream;
  }

  @override
  void send(Map<String, dynamic> message, [ List<int> binary ]) {
    outputs.add(DaemonMessage(message, binary != null ? Stream<List<int>>.value(binary) : null));
  }

  @override
  Future<void> dispose() async {
    await inputs.close();
    // In some tests, outputs have no listeners. We don't wait for outputs to close.
    unawaited(outputs.close());
  }
}

void main() {
  Daemon daemon;
  NotifyingLogger notifyingLogger;

  group('daemon', () {
    FakeDaemonStreams daemonStreams;
    DaemonConnection daemonConnection;
    setUp(() {
      BufferLogger bufferLogger;
      bufferLogger = BufferLogger.test();
      notifyingLogger = NotifyingLogger(verbose: false, parent: bufferLogger);
      daemonStreams = FakeDaemonStreams();
      daemonConnection = DaemonConnection(
        daemonStreams: daemonStreams,
        logger: bufferLogger,
      );
    });

    tearDown(() async {
      if (daemon != null) {
        return daemon.shutdown();
      }
      notifyingLogger.dispose();
      await daemonConnection.dispose();
    });

    testUsingContext('daemon.version command should succeed', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'daemon.version'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['result'], isNotEmpty);
      expect(response.data['result'], isA<String>());
    });

    testUsingContext('daemon.getSupportedPlatforms command should succeed', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      // Use the flutter_gallery project which has a known set of supported platforms.
      final String projectPath = globals.fs.path.join(getFlutterRoot(), 'dev', 'integration_tests', 'flutter_gallery');

      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{
        'id': 0,
        'method': 'daemon.getSupportedPlatforms',
        'params': <String, Object>{'projectRoot': projectPath},
      }));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);

      expect(response.data['id'], 0);
      expect(response.data['result'], isNotEmpty);
      expect((response.data['result'] as Map<String, dynamic>)['platforms'], <String>{'macos'});
    }, overrides: <Type, Generator>{
      // Disable Android/iOS and enable macOS to make sure result is consistent and defaults are tested off.
      FeatureFlags: () => TestFeatureFlags(isAndroidEnabled: false, isIOSEnabled: false, isMacOSEnabled: true),
    });

    testUsingContext('printError should send daemon.logMessage event', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      globals.printError('daemon.logMessage test');
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere((DaemonMessage message) {
        return message.data['event'] == 'daemon.logMessage' && (message.data['params'] as Map<String, dynamic>)['level'] == 'error';
      });
      expect(response.data['id'], isNull);
      expect(response.data['event'], 'daemon.logMessage');
      final Map<String, String> logMessage = castStringKeyedMap(response.data['params']).cast<String, String>();
      expect(logMessage['level'], 'error');
      expect(logMessage['message'], 'daemon.logMessage test');
    }, overrides: <Type, Generator>{
      Logger: () => notifyingLogger,
    });

    testUsingContext('printWarning should send daemon.logMessage event', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      globals.printWarning('daemon.logMessage test');
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere((DaemonMessage message) {
        return message.data['event'] == 'daemon.logMessage' && (message.data['params'] as Map<String, dynamic>)['level'] == 'warning';
      });
      expect(response.data['id'], isNull);
      expect(response.data['event'], 'daemon.logMessage');
      final Map<String, String> logMessage = castStringKeyedMap(response.data['params']).cast<String, String>();
      expect(logMessage['level'], 'warning');
      expect(logMessage['message'], 'daemon.logMessage test');
    }, overrides: <Type, Generator>{
      Logger: () => notifyingLogger,
    });

    testUsingContext('printStatus should log to stdout when logToStdout is enabled', () async {
      final StringBuffer buffer = await capturedConsolePrint(() {
        daemon = Daemon(
          daemonConnection,
          notifyingLogger: notifyingLogger,
          logToStdout: true,
        );
        globals.printStatus('daemon.logMessage test');
        return Future<void>.value();
      });

      expect(buffer.toString().trim(), 'daemon.logMessage test');
    }, overrides: <Type, Generator>{
      Logger: () => notifyingLogger,
    });

    testUsingContext('printBox should log to stdout when logToStdout is enabled', () async {
      final StringBuffer buffer = await capturedConsolePrint(() {
        daemon = Daemon(
          daemonConnection,
          notifyingLogger: notifyingLogger,
          logToStdout: true,
        );
        globals.printBox('This is the box message', title: 'Sample title');
        return Future<void>.value();
      });

      expect(buffer.toString().trim(), contains('Sample title: This is the box message'));
    }, overrides: <Type, Generator>{
      Logger: () => notifyingLogger,
    });

    testUsingContext('daemon.shutdown command should stop daemon', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'daemon.shutdown'}));
      return daemon.onExit.then<void>((int code) async {
        await daemonStreams.inputs.close();
        expect(code, 0);
      });
    });

    testUsingContext('app.restart without an appId should report an error', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );

      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'app.restart'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['error'], contains('appId is required'));
    });

    testUsingContext('ext.flutter.debugPaint via service extension without an appId should report an error', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );

      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{
        'id': 0,
        'method': 'app.callServiceExtension',
        'params': <String, String>{
          'methodName': 'ext.flutter.debugPaint',
        },
      }));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['error'], contains('appId is required'));
    });

    testUsingContext('app.stop without appId should report an error', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );

      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'app.stop'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['error'], contains('appId is required'));
    });

    testUsingContext('device.getDevices should respond with list', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'device.getDevices'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['result'], isList);
    });

    testUsingContext('device.getDevices reports available devices', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
      daemon.deviceDomain.addDeviceDiscoverer(discoverer);
      discoverer.addDevice(FakeAndroidDevice());
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'device.getDevices'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      final dynamic result = response.data['result'];
      expect(result, isList);
      expect(result, isNotEmpty);
    });

    testUsingContext('should send device.added event when device is discovered', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );

      final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
      daemon.deviceDomain.addDeviceDiscoverer(discoverer);
      discoverer.addDevice(FakeAndroidDevice());

      return daemonStreams.outputs.stream.skipWhile(_isConnectedEvent).first.then<void>((DaemonMessage response) async {
        expect(response.data['event'], 'device.added');
        expect(response.data['params'], isMap);

        final Map<String, dynamic> params = castStringKeyedMap(response.data['params']);
        expect(params['platform'], isNotEmpty); // the fake device has a platform of 'android-arm'
      });
    }, overrides: <Type, Generator>{
      AndroidWorkflow: () => FakeAndroidWorkflow(),
      IOSWorkflow: () => FakeIOSWorkflow(),
      FuchsiaWorkflow: () => FakeFuchsiaWorkflow(),
    });

    testUsingContext('device.discoverDevices should respond with list', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'device.discoverDevices'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['result'], isList);
    });

    testUsingContext('device.discoverDevices reports available devices', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
      daemon.deviceDomain.addDeviceDiscoverer(discoverer);
      discoverer.addDevice(FakeAndroidDevice());
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'device.discoverDevices'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      final dynamic result = response.data['result'];
      expect(result, isList);
      expect(result, isNotEmpty);
      expect(discoverer.discoverDevicesCalled, true);
    });

    testUsingContext('device.supportsRuntimeMode returns correct value', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
      daemon.deviceDomain.addDeviceDiscoverer(discoverer);
      final FakeAndroidDevice device = FakeAndroidDevice();
      discoverer.addDevice(device);
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{
        'id': 0,
        'method': 'device.supportsRuntimeMode',
        'params': <String, dynamic>{
          'deviceId': 'device',
          'buildMode': 'profile',
        },
      }));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      final dynamic result = response.data['result'];
      expect(result, true);
      expect(device.supportsRuntimeModeCalledBuildMode, BuildMode.profile);
    });

    testUsingContext('device.logReader.start and .stop starts and stops log reader', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
      daemon.deviceDomain.addDeviceDiscoverer(discoverer);
      final FakeAndroidDevice device = FakeAndroidDevice();
      discoverer.addDevice(device);
      final FakeDeviceLogReader logReader = FakeDeviceLogReader();
      device.logReader = logReader;
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{
        'id': 0,
        'method': 'device.logReader.start',
        'params': <String, dynamic>{
          'deviceId': 'device',
        },
      }));
      final Stream<DaemonMessage> broadcastOutput = daemonStreams.outputs.stream.asBroadcastStream();
      final DaemonMessage firstResponse = await broadcastOutput.firstWhere(_notEvent);
      expect(firstResponse.data['id'], 0);
      final String logReaderId = firstResponse.data['result'] as String;
      expect(logReaderId, isNotNull);

      // Try sending logs.
      logReader.logLinesController.add('Sample log line');
      final DaemonMessage logEvent = await broadcastOutput.firstWhere(
        (DaemonMessage message) => message.data['event'] != null && message.data['event'] != 'device.added',
      );
      expect(logEvent.data['params'], 'Sample log line');

      // Now try to stop the log reader.
      expect(logReader.disposeCalled, false);
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{
        'id': 1,
        'method': 'device.logReader.stop',
        'params': <String, dynamic>{
          'id': logReaderId,
        },
      }));
      final DaemonMessage stopResponse = await broadcastOutput.firstWhere(_notEvent);
      expect(stopResponse.data['id'], 1);
      expect(logReader.disposeCalled, true);
    });

    group('device.startApp and .stopApp', () {
      FakeApplicationPackageFactory applicationPackageFactory;
      setUp(() {
        applicationPackageFactory = FakeApplicationPackageFactory();
      });

      testUsingContext('device.startApp and .stopApp starts and stops an app', () async {
        daemon = Daemon(
          daemonConnection,
          notifyingLogger: notifyingLogger,
        );
        final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
        daemon.deviceDomain.addDeviceDiscoverer(discoverer);
        final FakeAndroidDevice device = FakeAndroidDevice();
        discoverer.addDevice(device);
        final Stream<DaemonMessage> broadcastOutput = daemonStreams.outputs.stream.asBroadcastStream();

        // First upload the application package.
        final FakeApplicationPackage applicationPackage = FakeApplicationPackage();
        applicationPackageFactory.applicationPackage = applicationPackage;
        daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{
          'id': 0,
          'method': 'device.uploadApplicationPackage',
          'params': <String, dynamic>{
            'targetPlatform': 'android',
            'applicationBinary': 'test_file',
          },
        }));
        final DaemonMessage applicationPackageIdResponse = await broadcastOutput.firstWhere(_notEvent);
        expect(applicationPackageIdResponse.data['id'], 0);
        expect(applicationPackageFactory.applicationBinaryRequested.basename, 'test_file');
        expect(applicationPackageFactory.platformRequested, TargetPlatform.android);
        final String applicationPackageId = applicationPackageIdResponse.data['result'] as String;

        // Try starting the app.
        final Uri observatoryUri = Uri.parse('http://127.0.0.1:12345/observatory');
        device.launchResult = LaunchResult.succeeded(observatoryUri: observatoryUri);
        daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{
          'id': 1,
          'method': 'device.startApp',
          'params': <String, dynamic>{
            'deviceId': 'device',
            'applicationPackageId': applicationPackageId,
            'debuggingOptions': DebuggingOptions.enabled(BuildInfo.debug).toJson(),
          },
        }));
        final DaemonMessage startAppResponse = await broadcastOutput.firstWhere(_notEvent);
        expect(startAppResponse.data['id'], 1);
        expect(device.startAppPackage, applicationPackage);
        final Map<String, dynamic> startAppResult = startAppResponse.data['result'] as Map<String, dynamic>;
        expect(startAppResult['started'], true);
        expect(startAppResult['observatoryUri'], observatoryUri.toString());

        // Try stopping the app.
        daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{
          'id': 2,
          'method': 'device.stopApp',
          'params': <String, dynamic>{
            'deviceId': 'device',
            'applicationPackageId': applicationPackageId,
          },
        }));
        final DaemonMessage stopAppResponse = await broadcastOutput.firstWhere(_notEvent);
        expect(stopAppResponse.data['id'], 2);
        expect(device.stopAppPackage, applicationPackage);
        final bool stopAppResult = stopAppResponse.data['result'] as bool;
        expect(stopAppResult, true);
      }, overrides: <Type, Generator>{
        ApplicationPackageFactory: () => applicationPackageFactory,
      });
    });

    testUsingContext('emulator.launch without an emulatorId should report an error', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );

      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'emulator.launch'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['error'], contains('emulatorId is required'));
    });

    testUsingContext('emulator.launch coldboot parameter must be boolean', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      final Map<String, dynamic> params = <String, dynamic>{'emulatorId': 'device', 'coldBoot': 1};
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'emulator.launch', 'params': params}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['error'], contains('coldBoot is not a bool'));
    });

    testUsingContext('emulator.getEmulators should respond with list', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );
      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'emulator.getEmulators'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere(_notEvent);
      expect(response.data['id'], 0);
      expect(response.data['result'], isList);
    });

    testUsingContext('daemon can send exposeUrl requests to the client', () async {
      const String originalUrl = 'http://localhost:1234/';
      const String mappedUrl = 'https://publichost:4321/';

      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );

      // Respond to any requests from the daemon to expose a URL.
      unawaited(daemonStreams.outputs.stream
        .firstWhere((DaemonMessage request) => request.data['method'] == 'app.exposeUrl')
        .then((DaemonMessage request) {
          expect((request.data['params'] as Map<String, dynamic>)['url'], equals(originalUrl));
          daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': request.data['id'], 'result': <String, dynamic>{'url': mappedUrl}}));
        })
      );

      final String exposedUrl = await daemon.daemonDomain.exposeUrl(originalUrl);
      expect(exposedUrl, equals(mappedUrl));
    });

    testUsingContext('devtools.serve command should return host and port on success', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );

      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'devtools.serve'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere((DaemonMessage response) => response.data['id'] == 0);
      final Map<String, dynamic> result = response.data['result'] as Map<String, dynamic>;
      expect(result, isNotEmpty);
      expect(result['host'], '127.0.0.1');
      expect(result['port'], 1234);
    }, overrides: <Type, Generator>{
      DevtoolsLauncher: () => FakeDevtoolsLauncher(DevToolsServerAddress('127.0.0.1', 1234)),
    });

    testUsingContext('devtools.serve command should return null fields if null returned', () async {
      daemon = Daemon(
        daemonConnection,
        notifyingLogger: notifyingLogger,
      );

      daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'devtools.serve'}));
      final DaemonMessage response = await daemonStreams.outputs.stream.firstWhere((DaemonMessage response) => response.data['id'] == 0);
      final Map<String, dynamic> result = response.data['result'] as Map<String, dynamic>;
      expect(result, isNotEmpty);
      expect(result['host'], null);
      expect(result['port'], null);
    }, overrides: <Type, Generator>{
      DevtoolsLauncher: () => FakeDevtoolsLauncher(null),
    });

    testUsingContext('proxy.connect tries to connect to an ipv4 address and proxies the connection correctly', () async {
      final TestIOOverrides ioOverrides = TestIOOverrides();
      await io.IOOverrides.runWithIOOverrides(() async {
        final FakeSocket socket = FakeSocket();
        bool connectCalled = false;
        int connectPort;
        ioOverrides.connectCallback = (dynamic host, int port) async {
          connectCalled = true;
          connectPort = port;
          if (host == io.InternetAddress.loopbackIPv4) {
            return socket;
          }
          throw const io.SocketException('fail');
        };

        daemon = Daemon(
          daemonConnection,
          notifyingLogger: notifyingLogger,
        );
        daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'proxy.connect', 'params': <String, dynamic>{'port': 123}}));

        final Stream<DaemonMessage> broadcastOutput = daemonStreams.outputs.stream.asBroadcastStream();
        final DaemonMessage firstResponse = await broadcastOutput.firstWhere(_notEvent);
        expect(firstResponse.data['id'], 0);
        expect(firstResponse.data['result'], isNotNull);
        expect(connectCalled, true);
        expect(connectPort, 123);

        final Object id = firstResponse.data['result'];

        // Can send received data as event.
        socket.controller.add(Uint8List.fromList(<int>[10, 11, 12]));
        final DaemonMessage dataEvent = await broadcastOutput.firstWhere(
          (DaemonMessage message) => message.data['event'] != null && message.data['event'] == 'proxy.data.$id',
        );
        expect(dataEvent.binary, isNotNull);
        final List<List<int>> data = await dataEvent.binary.toList();
        expect(data[0], <int>[10, 11, 12]);

        // Can proxy data to the socket.
        daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'proxy.write', 'params': <String, dynamic>{'id': id}}, Stream<List<int>>.value(<int>[21, 22, 23])));
        await pumpEventQueue();
        expect(socket.addedData[0], <int>[21, 22, 23]);

        // Closes the connection when disconnect request received.
        expect(socket.closeCalled, false);
        daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'proxy.disconnect', 'params': <String, dynamic>{'id': id}}));
        await pumpEventQueue();
        expect(socket.closeCalled, true);

        // Sends disconnected event when socket.done completer finishes.
        socket.doneCompleter.complete();
        final DaemonMessage disconnectEvent = await broadcastOutput.firstWhere(
          (DaemonMessage message) => message.data['event'] != null && message.data['event'] == 'proxy.disconnected.$id',
        );
        expect(disconnectEvent.data, isNotNull);
      }, ioOverrides);
    });

    testUsingContext('proxy.connect connects to ipv6 if ipv4 failed', () async {
      final TestIOOverrides ioOverrides = TestIOOverrides();
      await io.IOOverrides.runWithIOOverrides(() async {
        final FakeSocket socket = FakeSocket();
        bool connectIpv4Called = false;
        int connectPort;
        ioOverrides.connectCallback = (dynamic host, int port) async {
          connectPort = port;
          if (host == io.InternetAddress.loopbackIPv4) {
            connectIpv4Called = true;
          } else if (host == io.InternetAddress.loopbackIPv6) {
            return socket;
          }
          throw const io.SocketException('fail');
        };

        daemon = Daemon(
          daemonConnection,
          notifyingLogger: notifyingLogger,
        );
        daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'proxy.connect', 'params': <String, dynamic>{'port': 123}}));

        final Stream<DaemonMessage> broadcastOutput = daemonStreams.outputs.stream.asBroadcastStream();
        final DaemonMessage firstResponse = await broadcastOutput.firstWhere(_notEvent);
        expect(firstResponse.data['id'], 0);
        expect(firstResponse.data['result'], isNotNull);
        expect(connectIpv4Called, true);
        expect(connectPort, 123);
      }, ioOverrides);
    });

    testUsingContext('proxy.connect fails if both ipv6 and ipv4 failed', () async {
      final TestIOOverrides ioOverrides = TestIOOverrides();
      await io.IOOverrides.runWithIOOverrides(() async {
        ioOverrides.connectCallback = (dynamic host, int port) => throw const io.SocketException('fail');

        daemon = Daemon(
          daemonConnection,
          notifyingLogger: notifyingLogger,
        );
        daemonStreams.inputs.add(DaemonMessage(<String, dynamic>{'id': 0, 'method': 'proxy.connect', 'params': <String, dynamic>{'port': 123}}));

        final Stream<DaemonMessage> broadcastOutput = daemonStreams.outputs.stream.asBroadcastStream();
        final DaemonMessage firstResponse = await broadcastOutput.firstWhere(_notEvent);
        expect(firstResponse.data['id'], 0);
        expect(firstResponse.data['result'], isNull);
        expect(firstResponse.data['error'], isNotNull);
      }, ioOverrides);
    });
  });

  group('notifyingLogger', () {
    BufferLogger bufferLogger;
    setUp(() {
      bufferLogger = BufferLogger.test();
    });

    tearDown(() {
      bufferLogger.clear();
    });

    testUsingContext('outputs trace messages in verbose mode', () async {
      final NotifyingLogger logger = NotifyingLogger(verbose: true, parent: bufferLogger);
      logger.printTrace('test');
      expect(bufferLogger.errorText, contains('test'));
    });

    testUsingContext('ignores trace messages in non-verbose mode', () async {
      final NotifyingLogger logger = NotifyingLogger(verbose: false, parent: bufferLogger);

      final Future<LogMessage> messageResult = logger.onMessage.first;
      logger.printTrace('test');
      logger.printStatus('hello');

      final LogMessage message = await messageResult;

      expect(message.level, 'status');
      expect(message.message, 'hello');
      expect(bufferLogger.errorText, isEmpty);
    });

    testUsingContext('buffers messages sent before a subscription', () async {
      final NotifyingLogger logger = NotifyingLogger(verbose: false, parent: bufferLogger);

      logger.printStatus('hello');

      final LogMessage message = await logger.onMessage.first;

      expect(message.level, 'status');
      expect(message.message, 'hello');
    });
  });

  group('daemon queue', () {
    DebounceOperationQueue<int, String> queue;
    const Duration debounceDuration = Duration(seconds: 1);

    setUp(() {
      queue = DebounceOperationQueue<int, String>();
    });

    testWithoutContext(
        'debounces/merges same operation type and returns same result',
        () async {
      await _runFakeAsync((FakeAsync time) async {
        final List<Future<int>> operations = <Future<int>>[
          queue.queueAndDebounce('OP1', debounceDuration, () async => 1),
          queue.queueAndDebounce('OP1', debounceDuration, () async => 2),
        ];

        time.elapse(debounceDuration * 5);
        final List<int> results = await Future.wait(operations);

        expect(results, orderedEquals(<int>[1, 1]));
      });
    });

    testWithoutContext('does not merge results outside of the debounce duration',
        () async {
      await _runFakeAsync((FakeAsync time) async {
        final List<Future<int>> operations = <Future<int>>[
          queue.queueAndDebounce('OP1', debounceDuration, () async => 1),
          Future<int>.delayed(debounceDuration * 2).then((_) =>
              queue.queueAndDebounce('OP1', debounceDuration, () async => 2)),
        ];

        time.elapse(debounceDuration * 5);
        final List<int> results = await Future.wait(operations);

        expect(results, orderedEquals(<int>[1, 2]));
      });
    });

    testWithoutContext('does not merge results of different operations',
        () async {
      await _runFakeAsync((FakeAsync time) async {
        final List<Future<int>> operations = <Future<int>>[
          queue.queueAndDebounce('OP1', debounceDuration, () async => 1),
          queue.queueAndDebounce('OP2', debounceDuration, () async => 2),
        ];

        time.elapse(debounceDuration * 5);
        final List<int> results = await Future.wait(operations);

        expect(results, orderedEquals(<int>[1, 2]));
      });
    });

    testWithoutContext('does not run any operations concurrently', () async {
      // Crete a function that's slow, but throws if another instance of the
      // function is running.
      bool isRunning = false;
      Future<int> f(int ret) async {
        if (isRunning) {
          throw Exception('Functions ran concurrently!');
        }
        isRunning = true;
        await Future<void>.delayed(debounceDuration * 2);
        isRunning = false;
        return ret;
      }

      await _runFakeAsync((FakeAsync time) async {
        final List<Future<int>> operations = <Future<int>>[
          queue.queueAndDebounce('OP1', debounceDuration, () => f(1)),
          queue.queueAndDebounce('OP2', debounceDuration, () => f(2)),
        ];

        time.elapse(debounceDuration * 5);
        final List<int> results = await Future.wait(operations);

        expect(results, orderedEquals(<int>[1, 2]));
      });
    });
  });
}

bool _notEvent(DaemonMessage message) => message.data['event'] == null;

bool _isConnectedEvent(DaemonMessage message) => message.data['event'] == 'daemon.connected';

class FakeFuchsiaWorkflow extends Fake implements FuchsiaWorkflow {
  FakeFuchsiaWorkflow({ this.canListDevices = true });

  @override
  final bool canListDevices;
}

class FakeAndroidWorkflow extends Fake implements AndroidWorkflow {
  FakeAndroidWorkflow({ this.canListDevices = true });

  @override
  final bool canListDevices;
}

class FakeIOSWorkflow extends Fake implements IOSWorkflow {
  FakeIOSWorkflow({ this.canListDevices = true });

  @override
  final bool canListDevices;
}

// 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 FakeAndroidDevice extends Fake implements AndroidDevice {
  @override
  final String id = 'device';

  @override
  final String name = 'device';

  @override
  Future<String> get emulatorId async => 'device';

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

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

  @override
  final Category category = Category.mobile;

  @override
  final PlatformType platformType = PlatformType.android;

  @override
  final bool ephemeral = false;

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

  @override
  bool get supportsHotReload => true;

  @override
  bool get supportsHotRestart => true;

  @override
  bool get supportsScreenshot => true;

  @override
  bool get supportsFastStart => true;

  @override
  bool get supportsFlutterExit => true;

  @override
  Future<bool> get supportsHardwareRendering async => true;

  @override
  bool get supportsStartPaused => true;

  BuildMode supportsRuntimeModeCalledBuildMode;
  @override
  Future<bool> supportsRuntimeMode(BuildMode buildMode) async {
    supportsRuntimeModeCalledBuildMode = buildMode;
    return true;
  }

  DeviceLogReader logReader;
  @override
  FutureOr<DeviceLogReader> getLogReader({
    covariant ApplicationPackage app,
    bool includePastLogs = false,
  }) => logReader;

  ApplicationPackage startAppPackage;
  LaunchResult launchResult;
  @override
  Future<LaunchResult> startApp(
    ApplicationPackage package, {
    String mainPath,
    String route,
    DebuggingOptions debuggingOptions,
    Map<String, Object> platformArgs = const <String, Object>{},
    bool prebuiltApplication = false,
    bool ipv6 = false,
    String userIdentifier,
  }) async {
    startAppPackage = package;
    return launchResult;
  }

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

class FakeDeviceLogReader implements DeviceLogReader {
  final StreamController<String> logLinesController = StreamController<String>();
  bool disposeCalled = false;

  @override
  int appPid;

  @override
  FlutterVmService connectedVMService;

  @override
  void dispose() {
    disposeCalled = true;
  }

  @override
  Stream<String> get logLines => logLinesController.stream;

  @override
  String get name => 'device';

}

class FakeDevtoolsLauncher extends Fake implements DevtoolsLauncher {
  FakeDevtoolsLauncher(this._serverAddress);

  final DevToolsServerAddress _serverAddress;

  @override
  Future<DevToolsServerAddress> serve() async => _serverAddress;

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

class FakeApplicationPackageFactory implements ApplicationPackageFactory {
  TargetPlatform platformRequested;
  File applicationBinaryRequested;
  ApplicationPackage applicationPackage;

  @override
  Future<ApplicationPackage> getPackageForPlatform(TargetPlatform platform, {BuildInfo buildInfo, File applicationBinary}) async {
    platformRequested = platform;
    applicationBinaryRequested = applicationBinary;
    return applicationPackage;
  }
}

class FakeApplicationPackage extends Fake implements ApplicationPackage {}

class TestIOOverrides extends io.IOOverrides {
  Future<io.Socket> Function(dynamic host, int port) connectCallback;

  @override
  Future<io.Socket> socketConnect(dynamic host, int port,
      {dynamic sourceAddress, int sourcePort = 0, Duration timeout}) {
    return connectCallback(host, port);
  }
}

class FakeSocket extends Fake implements io.Socket {
  bool closeCalled = false;
  final StreamController<Uint8List> controller = StreamController<Uint8List>();
  final List<List<int>> addedData = <List<int>>[];
  final Completer<bool> doneCompleter = Completer<bool>();

  @override
  StreamSubscription<Uint8List> listen(
    void Function(Uint8List event) onData, {
    Function onError,
    void Function() onDone,
    bool cancelOnError,
  }) {
    return controller.stream.listen(onData, onError: onError, onDone: onDone, cancelOnError: cancelOnError);
  }

  @override
  void add(List<int> data) {
    addedData.add(data);
  }

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

  @override
  Future<bool> get done => doneCompleter.future;

  @override
  void destroy() {}
}
