// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:fake_async/fake_async.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/convert.dart' show utf8;

import '../src/common.dart';
import '../src/fake_process_manager.dart';

void main() {
  group(FakeProcess, () {
    testWithoutContext('exits with specified exit code', () async {
      final FakeProcess process = FakeProcess(exitCode: 42);
      expect(await process.exitCode, 42);
    });

    testWithoutContext('exits with specified stderr, stdout', () async {
      final FakeProcess process = FakeProcess(
        stderr: 'stderr\u{FFFD}'.codeUnits,
        stdout: 'stdout\u{FFFD}'.codeUnits,
      );
      await process.exitCode;

      // Verify that no encoding changes have been applied to output.
      //
      // In the past, we had hardcoded UTF-8 encoding for these streams in
      // FakeProcess. When a specific encoding is desired, it can be specified
      // on FakeCommand or in the encoding parameter of FakeProcessManager.run
      // or FakeProcessManager.runAsync.
      expect((await process.stderr.toList()).expand((List<int> x) => x), 'stderr\u{FFFD}'.codeUnits);
      expect((await process.stdout.toList()).expand((List<int> x) => x), 'stdout\u{FFFD}'.codeUnits);
    });

    testWithoutContext('exits after specified delay (if no completer specified)', () {
      final bool done = FakeAsync().run<bool>((FakeAsync time) {
        final FakeProcess process = FakeProcess(
          duration: const Duration(seconds: 30),
        );

        bool hasExited = false;
        unawaited(process.exitCode.then((int _) { hasExited = true; }));

        // Verify process hasn't exited before specified delay.
        time.elapse(const Duration(seconds: 15));
        expect(hasExited, isFalse);

        // Verify process has exited after specified delay.
        time.elapse(const Duration(seconds: 20));
        expect(hasExited, isTrue);

        return true;
      });
      expect(done, isTrue);
    });

    testWithoutContext('exits when completer completes (if no duration specified)', () {
      final bool done = FakeAsync().run<bool>((FakeAsync time) {
        final Completer<void> completer = Completer<void>();
        final FakeProcess process = FakeProcess(
          completer: completer,
        );

        bool hasExited = false;
        unawaited(process.exitCode.then((int _) { hasExited = true; }));

        // Verify process hasn't exited when all async tasks flushed.
        time.elapse(Duration.zero);
        expect(hasExited, isFalse);

        // Verify process has exited after completer completes.
        completer.complete();
        time.flushMicrotasks();
        expect(hasExited, isTrue);

        return true;
      });
      expect(done, isTrue);
    });

    testWithoutContext('when completer and duration are specified, does not exit until completer is completed', () {
      final bool done = FakeAsync().run<bool>((FakeAsync time) {
        final Completer<void> completer = Completer<void>();
        final FakeProcess process = FakeProcess(
          duration: const Duration(seconds: 30),
          completer: completer,
        );

        bool hasExited = false;
        unawaited(process.exitCode.then((int _) { hasExited = true; }));

        // Verify process hasn't exited before specified delay.
        time.elapse(const Duration(seconds: 15));
        expect(hasExited, isFalse);

        // Verify process hasn't exited until the completer completes.
        time.elapse(const Duration(seconds: 20));
        expect(hasExited, isFalse);

        // Verify process exits after the completer completes.
        completer.complete();
        time.flushMicrotasks();
        expect(hasExited, isTrue);

        return true;
      });
      expect(done, isTrue);
    });

    testWithoutContext('when completer and duration are specified, does not exit until duration has elapsed', () {
      final bool done = FakeAsync().run<bool>((FakeAsync time) {
        final Completer<void> completer = Completer<void>();
        final FakeProcess process = FakeProcess(
          duration: const Duration(seconds: 30),
          completer: completer,
        );

        bool hasExited = false;
        unawaited(process.exitCode.then((int _) { hasExited = true; }));

        // Verify process hasn't exited before specified delay.
        time.elapse(const Duration(seconds: 15));
        expect(hasExited, isFalse);

        // Verify process does not exit until duration has elapsed.
        completer.complete();
        expect(hasExited, isFalse);

        // Verify process exits after the duration elapses.
        time.elapse(const Duration(seconds: 20));
        expect(hasExited, isTrue);

        return true;
      });
      expect(done, isTrue);
    });

    testWithoutContext('process exit is asynchronous', () async {
      final FakeProcess process = FakeProcess();

      bool hasExited = false;
      unawaited(process.exitCode.then((int _) { hasExited = true; }));

      // Verify process hasn't completed.
      expect(hasExited, isFalse);

      // Flush async tasks. Verify process completes.
      await Future<void>.delayed(Duration.zero);
      expect(hasExited, isTrue);
    });

    testWithoutContext('stderr, stdout stream data after exit when outputFollowsExit is true', () async {
      final FakeProcess process = FakeProcess(
        stderr: 'stderr'.codeUnits,
        stdout: 'stdout'.codeUnits,
        outputFollowsExit: true,
      );

      final List<int> stderr = <int>[];
      final List<int> stdout = <int>[];
      process.stderr.listen(stderr.addAll);
      process.stdout.listen(stdout.addAll);

      // Ensure that no bytes have been received at process exit.
      await process.exitCode;
      expect(stderr, isEmpty);
      expect(stdout, isEmpty);

      // Flush all remaining async work. Ensure stderr, stdout is received.
      await Future<void>.delayed(Duration.zero);
      expect(stderr, 'stderr'.codeUnits);
      expect(stdout, 'stdout'.codeUnits);
    });
  });

  group(FakeProcessManager, () {
    late FakeProcessManager manager;

    setUp(() {
      manager = FakeProcessManager.empty();
    });

    group('start', () {
      testWithoutContext('can run a fake command', () async {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final Process process = await manager.start(<String>['faketool']);
        expect(await process.exitCode, 0);
        expect(await utf8.decodeStream(process.stdout), isEmpty);
        expect(await utf8.decodeStream(process.stderr), isEmpty);
      });

      testWithoutContext('outputFollowsExit delays stderr, stdout until after process exit', () async {
        manager.addCommand(const FakeCommand(
          command: <String>['faketool'],
          stderr: 'hello',
          stdout: 'world',
          outputFollowsExit: true,
        ));

        final List<int> stderrBytes = <int>[];
        final List<int> stdoutBytes = <int>[];

        // Start the process.
        final Process process = await manager.start(<String>['faketool']);
        final StreamSubscription<List<int>> stderrSubscription = process.stderr.listen((List<int> chunk) { stderrBytes.addAll(chunk); });
        final StreamSubscription<List<int>> stdoutSubscription = process.stdout.listen((List<int> chunk) { stdoutBytes.addAll(chunk); });

        // Immediately after exit, no output is emitted.
        await process.exitCode;
        expect(utf8.decode(stderrBytes), isEmpty);
        expect(utf8.decode(stdoutBytes), isEmpty);

        // Output is emitted asynchronously after process exit.
        await Future.wait(<Future<void>>[
          stderrSubscription.asFuture(),
          stdoutSubscription.asFuture(),
        ]);
        expect(utf8.decode(stderrBytes), 'hello');
        expect(utf8.decode(stdoutBytes), 'world');

        // Clean up stream subscriptions.
        await stderrSubscription.cancel();
        await stdoutSubscription.cancel();
      });
    });

    group('run', () {
      testWithoutContext('can run a fake command', () async {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final ProcessResult result = await manager.run(<String>['faketool']);
        expect(result.exitCode, 0);
        expect(result.stdout, isEmpty);
        expect(result.stderr, isEmpty);
      });

      testWithoutContext('stderr, stdout are String if encoding is unspecified', () async {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final ProcessResult result = await manager.run(<String>['faketool']);
        expect(result.exitCode, 0);
        expect(result.stdout, isA<String>());
        expect(result.stderr, isA<String>());
      });

      testWithoutContext('stderr, stdout are List<int> if encoding is null', () async {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final ProcessResult result = await manager.run(
          <String>['faketool'],
          stderrEncoding: null,
          stdoutEncoding: null,
        );
        expect(result.exitCode, 0);
        expect(result.stdout, isA<List<int>>());
        expect(result.stderr, isA<List<int>>());
      });

      testWithoutContext('stderr, stdout are String if encoding is specified', () async {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final ProcessResult result = await manager.run(
          <String>['faketool'],
          stderrEncoding: utf8,
          stdoutEncoding: utf8,
        );
        expect(result.exitCode, 0);
        expect(result.stdout, isA<String>());
        expect(result.stderr, isA<String>());
      });
    });

    group('runSync', () {
      testWithoutContext('can run a fake command', () {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final ProcessResult result = manager.runSync(<String>['faketool']);
        expect(result.exitCode, 0);
        expect(result.stdout, isEmpty);
        expect(result.stderr, isEmpty);
      });

      testWithoutContext('stderr, stdout are String if encoding is unspecified', () {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final ProcessResult result = manager.runSync(<String>['faketool']);
        expect(result.exitCode, 0);
        expect(result.stdout, isA<String>());
        expect(result.stderr, isA<String>());
      });

      testWithoutContext('stderr, stdout are List<int> if encoding is null', () {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final ProcessResult result = manager.runSync(
          <String>['faketool'],
          stderrEncoding: null,
          stdoutEncoding: null,
        );
        expect(result.exitCode, 0);
        expect(result.stdout, isA<List<int>>());
        expect(result.stderr, isA<List<int>>());
      });

      testWithoutContext('stderr, stdout are String if encoding is specified', () {
        manager.addCommand(const FakeCommand(command: <String>['faketool']));

        final ProcessResult result = manager.runSync(
          <String>['faketool'],
          stderrEncoding: utf8,
          stdoutEncoding: utf8,
        );
        expect(result.exitCode, 0);
        expect(result.stdout, isA<String>());
        expect(result.stderr, isA<String>());
      });
    });
  });
}
