// Copyright 2013 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 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_plugin_tools/src/common/core.dart';
import 'package:flutter_plugin_tools/src/common/file_utils.dart';
import 'package:flutter_plugin_tools/src/format_command.dart';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';

import 'mocks.dart';
import 'util.dart';

void main() {
  late FileSystem fileSystem;
  late MockPlatform mockPlatform;
  late Directory packagesDir;
  late RecordingProcessRunner processRunner;
  late FormatCommand analyzeCommand;
  late CommandRunner<void> runner;
  late String javaFormatPath;
  late String kotlinFormatPath;

  setUp(() {
    fileSystem = MemoryFileSystem();
    mockPlatform = MockPlatform();
    packagesDir = createPackagesDirectory(fileSystem: fileSystem);
    processRunner = RecordingProcessRunner();
    analyzeCommand = FormatCommand(
      packagesDir,
      processRunner: processRunner,
      platform: mockPlatform,
    );

    // Create the Java and Kotlin formatter files that the command checks for,
    // to avoid a download.
    final p.Context path = analyzeCommand.path;
    javaFormatPath = path.join(path.dirname(path.fromUri(mockPlatform.script)),
        'google-java-format-1.3-all-deps.jar');
    fileSystem.file(javaFormatPath).createSync(recursive: true);
    kotlinFormatPath = path.join(
        path.dirname(path.fromUri(mockPlatform.script)),
        'ktfmt-0.46-jar-with-dependencies.jar');
    fileSystem.file(kotlinFormatPath).createSync(recursive: true);

    runner = CommandRunner<void>('format_command', 'Test for format_command');
    runner.addCommand(analyzeCommand);
  });

  /// Returns a modified version of a list of [relativePaths] that are relative
  /// to [package] to instead be relative to [packagesDir].
  List<String> getPackagesDirRelativePaths(
      RepositoryPackage package, List<String> relativePaths) {
    final p.Context path = analyzeCommand.path;
    final String relativeBase =
        path.relative(package.path, from: packagesDir.path);
    return relativePaths
        .map((String relativePath) => path.join(relativeBase, relativePath))
        .toList();
  }

  /// Returns a list of [count] relative paths to pass to [createFakePlugin]
  /// or [createFakePackage] with name [packageName] such that each path will
  /// be 99 characters long relative to [packagesDir].
  ///
  /// This is for each of testing batching, since it means each file will
  /// consume 100 characters of the batch length.
  List<String> get99CharacterPathExtraFiles(String packageName, int count) {
    final int padding = 99 -
        packageName.length -
        1 - // the path separator after the package name
        1 - // the path separator after the padding
        10; // the file name
    const int filenameBase = 10000;

    final p.Context path = analyzeCommand.path;
    return <String>[
      for (int i = filenameBase; i < filenameBase + count; ++i)
        path.join('a' * padding, '$i.dart'),
    ];
  }

  test('formats .dart files', () async {
    const List<String> files = <String>[
      'lib/a.dart',
      'lib/src/b.dart',
      'lib/src/c.dart',
    ];
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: files,
    );

    await runCapturingPrint(runner, <String>['format']);

    expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          ProcessCall(
              'dart',
              <String>['format', ...getPackagesDirRelativePaths(plugin, files)],
              packagesDir.path),
        ]));
  });

  test('does not format .dart files with pragma', () async {
    const List<String> formattedFiles = <String>[
      'lib/a.dart',
      'lib/src/b.dart',
      'lib/src/c.dart',
    ];
    const String unformattedFile = 'lib/src/d.dart';
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: <String>[
        ...formattedFiles,
        unformattedFile,
      ],
    );

    final p.Context posixContext = p.posix;
    childFileWithSubcomponents(
            plugin.directory, posixContext.split(unformattedFile))
        .writeAsStringSync(
            '// copyright bla bla\n// This file is hand-formatted.\ncode...');

    await runCapturingPrint(runner, <String>['format']);

    expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          ProcessCall(
              'dart',
              <String>[
                'format',
                ...getPackagesDirRelativePaths(plugin, formattedFiles)
              ],
              packagesDir.path),
        ]));
  });

  test('fails if dart format fails', () async {
    const List<String> files = <String>[
      'lib/a.dart',
      'lib/src/b.dart',
      'lib/src/c.dart',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    processRunner.mockProcessesForExecutable['dart'] = <FakeProcessInfo>[
      FakeProcessInfo(MockProcess(exitCode: 1), <String>['format'])
    ];
    Error? commandError;
    final List<String> output = await runCapturingPrint(
        runner, <String>['format'], errorHandler: (Error e) {
      commandError = e;
    });

    expect(commandError, isA<ToolExit>());
    expect(
        output,
        containsAllInOrder(<Matcher>[
          contains('Failed to format Dart files: exit code 1.'),
        ]));
  });

  test('skips dart if --no-dart flag is provided', () async {
    const List<String> files = <String>[
      'lib/a.dart',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    await runCapturingPrint(runner, <String>['format', '--no-dart']);
    expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
  });

  test('formats .java files', () async {
    const List<String> files = <String>[
      'android/src/main/java/io/flutter/plugins/a_plugin/a.java',
      'android/src/main/java/io/flutter/plugins/a_plugin/b.java',
    ];
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: files,
    );

    await runCapturingPrint(runner, <String>['format']);

    expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          const ProcessCall('java', <String>['-version'], null),
          ProcessCall(
              'java',
              <String>[
                '-jar',
                javaFormatPath,
                '--replace',
                ...getPackagesDirRelativePaths(plugin, files)
              ],
              packagesDir.path),
        ]));
  });

  test('fails with a clear message if Java is not in the path', () async {
    const List<String> files = <String>[
      'android/src/main/java/io/flutter/plugins/a_plugin/a.java',
      'android/src/main/java/io/flutter/plugins/a_plugin/b.java',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    processRunner.mockProcessesForExecutable['java'] = <FakeProcessInfo>[
      FakeProcessInfo(MockProcess(exitCode: 1), <String>['-version'])
    ];
    Error? commandError;
    final List<String> output = await runCapturingPrint(
        runner, <String>['format'], errorHandler: (Error e) {
      commandError = e;
    });

    expect(commandError, isA<ToolExit>());
    expect(
        output,
        containsAllInOrder(<Matcher>[
          contains(
              'Unable to run "java". Make sure that it is in your path, or '
              'provide a full path with --java-path.'),
        ]));
  });

  test('fails if Java formatter fails', () async {
    const List<String> files = <String>[
      'android/src/main/java/io/flutter/plugins/a_plugin/a.java',
      'android/src/main/java/io/flutter/plugins/a_plugin/b.java',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    processRunner.mockProcessesForExecutable['java'] = <FakeProcessInfo>[
      FakeProcessInfo(
          MockProcess(), <String>['-version']), // check for working java
      FakeProcessInfo(MockProcess(exitCode: 1), <String>['-jar']), // format
    ];
    Error? commandError;
    final List<String> output = await runCapturingPrint(
        runner, <String>['format'], errorHandler: (Error e) {
      commandError = e;
    });

    expect(commandError, isA<ToolExit>());
    expect(
        output,
        containsAllInOrder(<Matcher>[
          contains('Failed to format Java files: exit code 1.'),
        ]));
  });

  test('honors --java-path flag', () async {
    const List<String> files = <String>[
      'android/src/main/java/io/flutter/plugins/a_plugin/a.java',
      'android/src/main/java/io/flutter/plugins/a_plugin/b.java',
    ];
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: files,
    );

    await runCapturingPrint(
        runner, <String>['format', '--java-path=/path/to/java']);

    expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          const ProcessCall('/path/to/java', <String>['--version'], null),
          ProcessCall(
              '/path/to/java',
              <String>[
                '-jar',
                javaFormatPath,
                '--replace',
                ...getPackagesDirRelativePaths(plugin, files)
              ],
              packagesDir.path),
        ]));
  });

  test('skips Java if --no-java flag is provided', () async {
    const List<String> files = <String>[
      'android/src/main/java/io/flutter/plugins/a_plugin/a.java',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    await runCapturingPrint(runner, <String>['format', '--no-java']);
    expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
  });

  test('formats c-ish files', () async {
    const List<String> files = <String>[
      'ios/Classes/Foo.h',
      'ios/Classes/Foo.m',
      'linux/foo_plugin.cc',
      'macos/Classes/Foo.h',
      'macos/Classes/Foo.mm',
      'windows/foo_plugin.cpp',
    ];
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: files,
    );

    await runCapturingPrint(runner, <String>['format']);

    expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          const ProcessCall('clang-format', <String>['--version'], null),
          ProcessCall(
              'clang-format',
              <String>[
                '-i',
                '--style=file',
                ...getPackagesDirRelativePaths(plugin, files)
              ],
              packagesDir.path),
        ]));
  });

  test('fails with a clear message if clang-format is not in the path',
      () async {
    const List<String> files = <String>[
      'linux/foo_plugin.cc',
      'macos/Classes/Foo.h',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    processRunner.mockProcessesForExecutable['clang-format'] =
        <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
    Error? commandError;
    final List<String> output = await runCapturingPrint(
        runner, <String>['format'], errorHandler: (Error e) {
      commandError = e;
    });

    expect(commandError, isA<ToolExit>());
    expect(
        output,
        containsAllInOrder(<Matcher>[
          contains('Unable to run "clang-format". Make sure that it is in your '
              'path, or provide a full path with --clang-format-path.'),
        ]));
  });

  test('falls back to working clang-format in the path', () async {
    const List<String> files = <String>[
      'linux/foo_plugin.cc',
      'macos/Classes/Foo.h',
    ];
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: files,
    );

    processRunner.mockProcessesForExecutable['clang-format'] =
        <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
    processRunner.mockProcessesForExecutable['which'] = <FakeProcessInfo>[
      FakeProcessInfo(
          MockProcess(
              stdout:
                  '/usr/local/bin/clang-format\n/path/to/working-clang-format'),
          <String>['-a', 'clang-format'])
    ];
    processRunner.mockProcessesForExecutable['/usr/local/bin/clang-format'] =
        <FakeProcessInfo>[FakeProcessInfo(MockProcess(exitCode: 1))];
    await runCapturingPrint(runner, <String>['format']);

    expect(
        processRunner.recordedCalls,
        containsAll(<ProcessCall>[
          const ProcessCall(
              '/path/to/working-clang-format', <String>['--version'], null),
          ProcessCall(
              '/path/to/working-clang-format',
              <String>[
                '-i',
                '--style=file',
                ...getPackagesDirRelativePaths(plugin, files)
              ],
              packagesDir.path),
        ]));
  });

  test('honors --clang-format-path flag', () async {
    const List<String> files = <String>[
      'windows/foo_plugin.cpp',
    ];
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: files,
    );

    await runCapturingPrint(runner,
        <String>['format', '--clang-format-path=/path/to/clang-format']);

    expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          const ProcessCall(
              '/path/to/clang-format', <String>['--version'], null),
          ProcessCall(
              '/path/to/clang-format',
              <String>[
                '-i',
                '--style=file',
                ...getPackagesDirRelativePaths(plugin, files)
              ],
              packagesDir.path),
        ]));
  });

  test('fails if clang-format fails', () async {
    const List<String> files = <String>[
      'linux/foo_plugin.cc',
      'macos/Classes/Foo.h',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    processRunner.mockProcessesForExecutable['clang-format'] =
        <FakeProcessInfo>[
      FakeProcessInfo(MockProcess(),
          <String>['--version']), // check for working clang-format
      FakeProcessInfo(MockProcess(exitCode: 1), <String>['-i']), // format
    ];
    Error? commandError;
    final List<String> output = await runCapturingPrint(
        runner, <String>['format'], errorHandler: (Error e) {
      commandError = e;
    });

    expect(commandError, isA<ToolExit>());
    expect(
        output,
        containsAllInOrder(<Matcher>[
          contains(
              'Failed to format C, C++, and Objective-C files: exit code 1.'),
        ]));
  });

  test('skips clang-format if --no-clang-format flag is provided', () async {
    const List<String> files = <String>[
      'linux/foo_plugin.cc',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    await runCapturingPrint(runner, <String>['format', '--no-clang-format']);
    expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
  });

  group('kotlin-format', () {
    test('formats .kt files', () async {
      const List<String> files = <String>[
        'android/src/main/kotlin/io/flutter/plugins/a_plugin/a.kt',
        'android/src/main/kotlin/io/flutter/plugins/a_plugin/b.kt',
      ];
      final RepositoryPackage plugin = createFakePlugin(
        'a_plugin',
        packagesDir,
        extraFiles: files,
      );

      await runCapturingPrint(runner, <String>['format']);

      expect(
          processRunner.recordedCalls,
          orderedEquals(<ProcessCall>[
            const ProcessCall('java', <String>['-version'], null),
            ProcessCall(
                'java',
                <String>[
                  '-jar',
                  kotlinFormatPath,
                  ...getPackagesDirRelativePaths(plugin, files)
                ],
                packagesDir.path),
          ]));
    });

    test('fails if Kotlin formatter fails', () async {
      const List<String> files = <String>[
        'android/src/main/kotlin/io/flutter/plugins/a_plugin/a.kt',
        'android/src/main/kotlin/io/flutter/plugins/a_plugin/b.kt',
      ];
      createFakePlugin('a_plugin', packagesDir, extraFiles: files);

      processRunner.mockProcessesForExecutable['java'] = <FakeProcessInfo>[
        FakeProcessInfo(
            MockProcess(), <String>['-version']), // check for working java
        FakeProcessInfo(MockProcess(exitCode: 1), <String>['-jar']), // format
      ];
      Error? commandError;
      final List<String> output = await runCapturingPrint(
          runner, <String>['format'], errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Failed to format Kotlin files: exit code 1.'),
          ]));
    });

    test('skips Kotlin if --no-kotlin flag is provided', () async {
      const List<String> files = <String>[
        'android/src/main/kotlin/io/flutter/plugins/a_plugin/a.kt',
      ];
      createFakePlugin('a_plugin', packagesDir, extraFiles: files);

      await runCapturingPrint(runner, <String>['format', '--no-kotlin']);
      expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
    });
  });

  group('swift-format', () {
    test('formats Swift if --swift-format flag is provided', () async {
      const List<String> files = <String>[
        'macos/foo.swift',
      ];
      final RepositoryPackage plugin = createFakePlugin(
        'a_plugin',
        packagesDir,
        extraFiles: files,
      );

      await runCapturingPrint(runner, <String>[
        'format',
        '--swift',
        '--swift-format-path=/path/to/swift-format'
      ]);

      expect(
          processRunner.recordedCalls,
          orderedEquals(<ProcessCall>[
            const ProcessCall(
              '/path/to/swift-format',
              <String>['--version'],
              null,
            ),
            ProcessCall(
              '/path/to/swift-format',
              <String>['-i', ...getPackagesDirRelativePaths(plugin, files)],
              packagesDir.path,
            ),
            ProcessCall(
              '/path/to/swift-format',
              <String>[
                'lint',
                '--parallel',
                '--strict',
                ...getPackagesDirRelativePaths(plugin, files),
              ],
              packagesDir.path,
            ),
          ]));
    });

    test('skips Swift if --no-swift flag is provided', () async {
      const List<String> files = <String>[
        'macos/foo.swift',
      ];
      createFakePlugin(
        'a_plugin',
        packagesDir,
        extraFiles: files,
      );

      await runCapturingPrint(runner, <String>['format', '--no-swift']);

      expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
    });

    test('fails with a clear message if swift-format is not in the path',
        () async {
      const List<String> files = <String>[
        'macos/foo.swift',
      ];
      createFakePlugin('a_plugin', packagesDir, extraFiles: files);

      processRunner.mockProcessesForExecutable['swift-format'] =
          <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(exitCode: 1), <String>['--version']),
      ];
      Error? commandError;
      final List<String> output = await runCapturingPrint(
          runner, <String>['format', '--swift'], errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'Unable to run "swift-format". Make sure that it is in your path, or '
                'provide a full path with --swift-format-path.'),
          ]));
    });

    test('fails if swift-format lint fails', () async {
      const List<String> files = <String>[
        'macos/foo.swift',
      ];
      createFakePlugin('a_plugin', packagesDir, extraFiles: files);

      processRunner.mockProcessesForExecutable['swift-format'] =
          <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(),
            <String>['--version']), // check for working swift-format
        FakeProcessInfo(MockProcess(), <String>['-i']),
        FakeProcessInfo(MockProcess(exitCode: 1), <String>[
          'lint',
          '--parallel',
          '--strict',
        ]),
      ];
      Error? commandError;
      final List<String> output = await runCapturingPrint(runner, <String>[
        'format',
        '--swift',
        '--swift-format-path=swift-format'
      ], errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Failed to lint Swift files: exit code 1.'),
          ]));
    });

    test('fails if swift-format fails', () async {
      const List<String> files = <String>[
        'macos/foo.swift',
      ];
      createFakePlugin('a_plugin', packagesDir, extraFiles: files);

      processRunner.mockProcessesForExecutable['swift-format'] =
          <FakeProcessInfo>[
        FakeProcessInfo(MockProcess(),
            <String>['--version']), // check for working swift-format
        FakeProcessInfo(MockProcess(exitCode: 1), <String>['-i']),
      ];
      Error? commandError;
      final List<String> output = await runCapturingPrint(runner, <String>[
        'format',
        '--swift',
        '--swift-format-path=swift-format'
      ], errorHandler: (Error e) {
        commandError = e;
      });

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Failed to format Swift files: exit code 1.'),
          ]));
    });
  });

  test('skips known non-repo files', () async {
    const List<String> skipFiles = <String>[
      '/example/build/SomeFramework.framework/Headers/SomeFramework.h',
      '/example/Pods/APod.framework/Headers/APod.h',
      '.dart_tool/internals/foo.cc',
      '.dart_tool/internals/Bar.java',
      '.dart_tool/internals/baz.dart',
    ];
    const List<String> clangFiles = <String>['ios/Classes/Foo.h'];
    const List<String> dartFiles = <String>['lib/a.dart'];
    const List<String> javaFiles = <String>[
      'android/src/main/java/io/flutter/plugins/a_plugin/a.java'
    ];
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: <String>[
        ...skipFiles,
        // Include some files that should be formatted to validate that it's
        // correctly filtering even when running the commands.
        ...clangFiles,
        ...dartFiles,
        ...javaFiles,
      ],
    );

    await runCapturingPrint(runner, <String>['format']);

    expect(
        processRunner.recordedCalls,
        containsAll(<ProcessCall>[
          ProcessCall(
              'clang-format',
              <String>[
                '-i',
                '--style=file',
                ...getPackagesDirRelativePaths(plugin, clangFiles)
              ],
              packagesDir.path),
          ProcessCall(
              'dart',
              <String>[
                'format',
                ...getPackagesDirRelativePaths(plugin, dartFiles)
              ],
              packagesDir.path),
          ProcessCall(
              'java',
              <String>[
                '-jar',
                javaFormatPath,
                '--replace',
                ...getPackagesDirRelativePaths(plugin, javaFiles)
              ],
              packagesDir.path),
        ]));
  });

  test('skips GeneratedPluginRegistrant.swift', () async {
    const String sourceFile = 'macos/Classes/Foo.swift';
    final RepositoryPackage plugin = createFakePlugin(
      'a_plugin',
      packagesDir,
      extraFiles: <String>[
        sourceFile,
        'example/macos/Flutter/GeneratedPluginRegistrant.swift',
      ],
    );

    await runCapturingPrint(runner, <String>[
      'format',
      '--swift',
      '--swift-format-path=/path/to/swift-format'
    ]);

    expect(
        processRunner.recordedCalls,
        orderedEquals(<ProcessCall>[
          const ProcessCall(
            '/path/to/swift-format',
            <String>['--version'],
            null,
          ),
          ProcessCall(
            '/path/to/swift-format',
            <String>[
              '-i',
              ...getPackagesDirRelativePaths(plugin, <String>[sourceFile])
            ],
            packagesDir.path,
          ),
          ProcessCall(
            '/path/to/swift-format',
            <String>[
              'lint',
              '--parallel',
              '--strict',
              ...getPackagesDirRelativePaths(plugin, <String>[sourceFile]),
            ],
            packagesDir.path,
          ),
        ]));
  });

  test('fails if files are changed with --fail-on-change', () async {
    const List<String> files = <String>[
      'linux/foo_plugin.cc',
      'macos/Classes/Foo.h',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    const String changedFilePath = 'packages/a_plugin/linux/foo_plugin.cc';
    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
      FakeProcessInfo(
          MockProcess(stdout: changedFilePath), <String>['ls-files']),
    ];

    Error? commandError;
    final List<String> output =
        await runCapturingPrint(runner, <String>['format', '--fail-on-change'],
            errorHandler: (Error e) {
      commandError = e;
    });

    expect(commandError, isA<ToolExit>());
    expect(
        output,
        containsAllInOrder(<Matcher>[
          contains('These files are not formatted correctly'),
          contains(changedFilePath),
          // Ensure the error message links to instructions.
          contains(
              'https://github.com/flutter/packages/blob/main/script/tool/README.md#format-code'),
          contains('patch -p1 <<DONE'),
        ]));
  });

  test('fails if git ls-files fails', () async {
    const List<String> files = <String>[
      'linux/foo_plugin.cc',
      'macos/Classes/Foo.h',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
      FakeProcessInfo(MockProcess(exitCode: 1), <String>['ls-files'])
    ];
    Error? commandError;
    final List<String> output =
        await runCapturingPrint(runner, <String>['format', '--fail-on-change'],
            errorHandler: (Error e) {
      commandError = e;
    });

    expect(commandError, isA<ToolExit>());
    expect(
        output,
        containsAllInOrder(<Matcher>[
          contains('Unable to determine changed files.'),
        ]));
  });

  test('reports git diff failures', () async {
    const List<String> files = <String>[
      'linux/foo_plugin.cc',
      'macos/Classes/Foo.h',
    ];
    createFakePlugin('a_plugin', packagesDir, extraFiles: files);

    const String changedFilePath = 'packages/a_plugin/linux/foo_plugin.cc';
    processRunner.mockProcessesForExecutable['git'] = <FakeProcessInfo>[
      FakeProcessInfo(
          MockProcess(stdout: changedFilePath), <String>['ls-files']),
      FakeProcessInfo(MockProcess(exitCode: 1), <String>['diff']),
    ];

    Error? commandError;
    final List<String> output =
        await runCapturingPrint(runner, <String>['format', '--fail-on-change'],
            errorHandler: (Error e) {
      commandError = e;
    });

    expect(commandError, isA<ToolExit>());
    expect(
        output,
        containsAllInOrder(<Matcher>[
          contains('These files are not formatted correctly'),
          contains(changedFilePath),
          contains('Unable to determine diff.'),
        ]));
  });

  test('Batches moderately long file lists on Windows', () async {
    mockPlatform.isWindows = true;

    const String pluginName = 'a_plugin';
    // -1 since the command itself takes some length.
    const int batchSize = (windowsCommandLineMax ~/ 100) - 1;

    // Make the file list one file longer than would fit in the batch.
    final List<String> batch1 =
        get99CharacterPathExtraFiles(pluginName, batchSize + 1);
    final String extraFile = batch1.removeLast();

    createFakePlugin(
      pluginName,
      packagesDir,
      extraFiles: <String>[...batch1, extraFile],
    );

    await runCapturingPrint(runner, <String>['format']);

    // Ensure that it was batched...
    expect(processRunner.recordedCalls.length, 2);
    // ... and that the spillover into the second batch was only one file.
    expect(
        processRunner.recordedCalls,
        contains(
          ProcessCall(
              'dart',
              <String>[
                'format',
                '$pluginName\\$extraFile',
              ],
              packagesDir.path),
        ));
  });

  // Validates that the Windows limit--which is much lower than the limit on
  // other platforms--isn't being used on all platforms, as that would make
  // formatting slower on Linux and macOS.
  test('Does not batch moderately long file lists on non-Windows', () async {
    const String pluginName = 'a_plugin';
    // -1 since the command itself takes some length.
    const int batchSize = (windowsCommandLineMax ~/ 100) - 1;

    // Make the file list one file longer than would fit in a Windows batch.
    final List<String> batch =
        get99CharacterPathExtraFiles(pluginName, batchSize + 1);

    createFakePlugin(
      pluginName,
      packagesDir,
      extraFiles: batch,
    );

    await runCapturingPrint(runner, <String>['format']);

    expect(processRunner.recordedCalls.length, 1);
  });

  test('Batches extremely long file lists on non-Windows', () async {
    const String pluginName = 'a_plugin';
    // -1 since the command itself takes some length.
    const int batchSize = (nonWindowsCommandLineMax ~/ 100) - 1;

    // Make the file list one file longer than would fit in the batch.
    final List<String> batch1 =
        get99CharacterPathExtraFiles(pluginName, batchSize + 1);
    final String extraFile = batch1.removeLast();

    createFakePlugin(
      pluginName,
      packagesDir,
      extraFiles: <String>[...batch1, extraFile],
    );

    await runCapturingPrint(runner, <String>['format']);

    // Ensure that it was batched...
    expect(processRunner.recordedCalls.length, 2);
    // ... and that the spillover into the second batch was only one file.
    expect(
        processRunner.recordedCalls,
        contains(
          ProcessCall(
              'dart',
              <String>[
                'format',
                '$pluginName/$extraFile',
              ],
              packagesDir.path),
        ));
  });
}
