// 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/license_check_command.dart';
import 'package:mockito/mockito.dart';
import 'package:platform/platform.dart';
import 'package:test/test.dart';

import 'common/package_command_test.mocks.dart';
import 'mocks.dart';
import 'util.dart';

void main() {
  group('LicenseCheckCommand', () {
    late CommandRunner<void> runner;
    late FileSystem fileSystem;
    late Platform platform;
    late Directory root;

    setUp(() {
      fileSystem = MemoryFileSystem();
      platform = MockPlatformWithSeparator();
      final Directory packagesDir =
          fileSystem.currentDirectory.childDirectory('packages');
      root = packagesDir.parent;

      final MockGitDir gitDir = MockGitDir();
      when(gitDir.path).thenReturn(packagesDir.parent.path);

      final LicenseCheckCommand command = LicenseCheckCommand(
        packagesDir,
        platform: platform,
        gitDir: gitDir,
      );
      runner =
          CommandRunner<void>('license_test', 'Test for $LicenseCheckCommand');
      runner.addCommand(command);
    });

    /// Writes a copyright+license block to [file], defaulting to a standard
    /// block for this repository.
    ///
    /// [commentString] is added to the start of each line.
    /// [prefix] is added to the start of the entire block.
    /// [suffix] is added to the end of the entire block.
    void writeLicense(
      File file, {
      String comment = '// ',
      String prefix = '',
      String suffix = '',
      String copyright =
          'Copyright 2013 The Flutter Authors. All rights reserved.',
      List<String> license = const <String>[
        'Use of this source code is governed by a BSD-style license that can be',
        'found in the LICENSE file.',
      ],
      bool useCrlf = false,
    }) {
      final List<String> lines = <String>['$prefix$comment$copyright'];
      for (final String line in license) {
        lines.add('$comment$line');
      }
      final String newline = useCrlf ? '\r\n' : '\n';
      file.writeAsStringSync(lines.join(newline) + suffix + newline);
    }

    test('looks at only expected extensions', () async {
      final Map<String, bool> extensions = <String, bool>{
        'c': true,
        'cc': true,
        'cpp': true,
        'dart': true,
        'h': true,
        'html': true,
        'java': true,
        'json': false,
        'kt': true,
        'm': true,
        'md': false,
        'mm': true,
        'png': false,
        'swift': true,
        'sh': true,
        'yaml': false,
      };

      const String filenameBase = 'a_file';
      for (final String fileExtension in extensions.keys) {
        root.childFile('$filenameBase.$fileExtension').createSync();
      }

      final List<String> output = await runCapturingPrint(
          runner, <String>['license-check'], errorHandler: (Error e) {
        // Ignore failure; the files are empty so the check is expected to fail,
        // but this test isn't for that behavior.
      });

      extensions.forEach((String fileExtension, bool shouldCheck) {
        final Matcher logLineMatcher =
            contains('Checking $filenameBase.$fileExtension');
        expect(output, shouldCheck ? logLineMatcher : isNot(logLineMatcher));
      });
    });

    test('ignore list overrides extension matches', () async {
      final List<String> ignoredFiles = <String>[
        // Ignored base names.
        'flutter_export_environment.sh',
        'GeneratedPluginRegistrant.java',
        'GeneratedPluginRegistrant.m',
        'generated_plugin_registrant.cc',
        'generated_plugin_registrant.cpp',
        // Ignored path suffixes.
        'foo.g.dart',
        'foo.mocks.dart',
        // Ignored files.
        'resource.h',
      ];

      for (final String name in ignoredFiles) {
        root.childFile(name).createSync();
      }

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      for (final String name in ignoredFiles) {
        expect(output, isNot(contains('Checking $name')));
      }
    });

    test('ignores submodules', () async {
      const String submoduleName = 'a_submodule';

      final File submoduleSpec = root.childFile('.gitmodules');
      submoduleSpec.writeAsStringSync('''
[submodule "$submoduleName"]
  path = $submoduleName
  url = https://github.com/foo/$submoduleName
''');

      const List<String> submoduleFiles = <String>[
        '$submoduleName/foo.dart',
        '$submoduleName/a/b/bar.dart',
        '$submoduleName/LICENSE',
      ];
      for (final String filePath in submoduleFiles) {
        root.childFile(filePath).createSync(recursive: true);
      }

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      for (final String filePath in submoduleFiles) {
        expect(output, isNot(contains('Checking $filePath')));
      }
    });

    test('passes if all checked files have license blocks', () async {
      final File checked = root.childFile('checked.cc');
      checked.createSync();
      writeLicense(checked);
      final File notChecked = root.childFile('not_checked.md');
      notChecked.createSync();

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      // Sanity check that the test did actually check a file.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Checking checked.cc'),
            contains('All files passed validation!'),
          ]));
    });

    test('passes correct license blocks on Windows', () async {
      final File checked = root.childFile('checked.cc');
      checked.createSync();
      writeLicense(checked, useCrlf: true);

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      // Sanity check that the test did actually check a file.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Checking checked.cc'),
            contains('All files passed validation!'),
          ]));
    });

    test('handles the comment styles for all supported languages', () async {
      final File fileA = root.childFile('file_a.cc');
      fileA.createSync();
      writeLicense(fileA);
      final File fileB = root.childFile('file_b.sh');
      fileB.createSync();
      writeLicense(fileB, comment: '# ');
      final File fileC = root.childFile('file_c.html');
      fileC.createSync();
      writeLicense(fileC, comment: '', prefix: '<!-- ', suffix: ' -->');

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      // Sanity check that the test did actually check the files.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Checking file_a.cc'),
            contains('Checking file_b.sh'),
            contains('Checking file_c.html'),
            contains('All files passed validation!'),
          ]));
    });

    test('fails if any checked files are missing license blocks', () async {
      final File goodA = root.childFile('good.cc');
      goodA.createSync();
      writeLicense(goodA);
      final File goodB = root.childFile('good.h');
      goodB.createSync();
      writeLicense(goodB);
      root.childFile('bad.cc').createSync();
      root.childFile('bad.h').createSync();

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

      expect(commandError, isA<ToolExit>());
      // Failure should give information about the problematic files.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'The license block for these files is missing or incorrect:'),
            contains('  bad.cc'),
            contains('  bad.h'),
          ]));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains(contains('All files passed validation!'))));
    });

    test('fails if any checked files are missing just the copyright', () async {
      final File good = root.childFile('good.cc');
      good.createSync();
      writeLicense(good);
      final File bad = root.childFile('bad.cc');
      bad.createSync();
      writeLicense(bad, copyright: '');

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

      expect(commandError, isA<ToolExit>());
      // Failure should give information about the problematic files.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'The license block for these files is missing or incorrect:'),
            contains('  bad.cc'),
          ]));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains(contains('All files passed validation!'))));
    });

    test('fails if any checked files are missing just the license', () async {
      final File good = root.childFile('good.cc');
      good.createSync();
      writeLicense(good);
      final File bad = root.childFile('bad.cc');
      bad.createSync();
      writeLicense(bad, license: <String>[]);

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

      expect(commandError, isA<ToolExit>());
      // Failure should give information about the problematic files.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'The license block for these files is missing or incorrect:'),
            contains('  bad.cc'),
          ]));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains(contains('All files passed validation!'))));
    });

    test('fails if any third-party code is not in a third_party directory',
        () async {
      final File thirdPartyFile = root.childFile('third_party.cc');
      thirdPartyFile.createSync();
      writeLicense(thirdPartyFile, copyright: 'Copyright 2017 Someone Else');

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

      expect(commandError, isA<ToolExit>());
      // Failure should give information about the problematic files.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'The license block for these files is missing or incorrect:'),
            contains('  third_party.cc'),
          ]));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains(contains('All files passed validation!'))));
    });

    test('succeeds for third-party code in a third_party directory', () async {
      final File thirdPartyFile = root
          .childDirectory('a_plugin')
          .childDirectory('lib')
          .childDirectory('src')
          .childDirectory('third_party')
          .childFile('file.cc');
      thirdPartyFile.createSync(recursive: true);
      writeLicense(thirdPartyFile,
          copyright: 'Copyright 2017 Workiva Inc.',
          license: <String>[
            'Licensed under the Apache License, Version 2.0 (the "License");',
            'you may not use this file except in compliance with the License.'
          ]);

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      // Sanity check that the test did actually check the file.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Checking a_plugin/lib/src/third_party/file.cc'),
            contains('All files passed validation!'),
          ]));
    });

    test('allows first-party code in a third_party directory', () async {
      final File firstPartyFileInThirdParty = root
          .childDirectory('a_plugin')
          .childDirectory('lib')
          .childDirectory('src')
          .childDirectory('third_party')
          .childFile('first_party.cc');
      firstPartyFileInThirdParty.createSync(recursive: true);
      writeLicense(firstPartyFileInThirdParty);

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      // Sanity check that the test did actually check the file.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Checking a_plugin/lib/src/third_party/first_party.cc'),
            contains('All files passed validation!'),
          ]));
    });

    test('fails for licenses that the tool does not expect', () async {
      final File good = root.childFile('good.cc');
      good.createSync();
      writeLicense(good);
      final File bad = root.childDirectory('third_party').childFile('bad.cc');
      bad.createSync(recursive: true);
      writeLicense(bad, license: <String>[
        'This program is free software: you can redistribute it and/or modify',
        'it under the terms of the GNU General Public License',
      ]);

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

      expect(commandError, isA<ToolExit>());
      // Failure should give information about the problematic files.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'No recognized license was found for the following third-party files:'),
            contains('  third_party/bad.cc'),
          ]));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains(contains('All files passed validation!'))));
    });

    test('Apache is not recognized for new authors without validation changes',
        () async {
      final File good = root.childFile('good.cc');
      good.createSync();
      writeLicense(good);
      final File bad = root.childDirectory('third_party').childFile('bad.cc');
      bad.createSync(recursive: true);
      writeLicense(
        bad,
        copyright: 'Copyright 2017 Some New Authors.',
        license: <String>[
          'Licensed under the Apache License, Version 2.0 (the "License");',
          'you may not use this file except in compliance with the License.'
        ],
      );

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

      expect(commandError, isA<ToolExit>());
      // Failure should give information about the problematic files.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains(
                'No recognized license was found for the following third-party files:'),
            contains('  third_party/bad.cc'),
          ]));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains(contains('All files passed validation!'))));
    });

    test('passes if all first-party LICENSE files are correctly formatted',
        () async {
      final File license = root.childFile('LICENSE');
      license.createSync();
      license.writeAsStringSync(_correctLicenseFileText);

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      // Sanity check that the test did actually check the file.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Checking LICENSE'),
            contains('All files passed validation!'),
          ]));
    });

    test('passes correct LICENSE files on Windows', () async {
      final File license = root.childFile('LICENSE');
      license.createSync();
      license
          .writeAsStringSync(_correctLicenseFileText.replaceAll('\n', '\r\n'));

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      // Sanity check that the test did actually check the file.
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Checking LICENSE'),
            contains('All files passed validation!'),
          ]));
    });

    test('fails if any first-party LICENSE files are incorrectly formatted',
        () async {
      final File license = root.childFile('LICENSE');
      license.createSync();
      license.writeAsStringSync(_incorrectLicenseFileText);

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

      expect(commandError, isA<ToolExit>());
      expect(output, isNot(contains(contains('All files passed validation!'))));
    });

    test('ignores third-party LICENSE format', () async {
      final File license =
          root.childDirectory('third_party').childFile('LICENSE');
      license.createSync(recursive: true);
      license.writeAsStringSync(_incorrectLicenseFileText);

      final List<String> output =
          await runCapturingPrint(runner, <String>['license-check']);

      // The file shouldn't be checked.
      expect(output, isNot(contains(contains('Checking third_party/LICENSE'))));
    });

    test('outputs all errors at the end', () async {
      root.childFile('bad.cc').createSync();
      root
          .childDirectory('third_party')
          .childFile('bad.cc')
          .createSync(recursive: true);
      final File license = root.childFile('LICENSE');
      license.createSync();
      license.writeAsStringSync(_incorrectLicenseFileText);

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

      expect(commandError, isA<ToolExit>());
      expect(
          output,
          containsAllInOrder(<Matcher>[
            contains('Checking LICENSE'),
            contains('Checking bad.cc'),
            contains('Checking third_party/bad.cc'),
            contains(
                'The following LICENSE files do not follow the expected format:'),
            contains('  LICENSE'),
            contains(
                'The license block for these files is missing or incorrect:'),
            contains('  bad.cc'),
            contains(
                'No recognized license was found for the following third-party files:'),
            contains('  third_party/bad.cc'),
          ]));
    });
  });
}

class MockPlatformWithSeparator extends MockPlatform {
  @override
  String get pathSeparator => isWindows ? r'\' : '/';
}

const String _correctLicenseFileText = '''
Copyright 2013 The Flutter Authors. All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.
    * Neither the name of Google Inc. nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
''';

// A common incorrect version created by copying text intended for a code file,
// with comment markers.
const String _incorrectLicenseFileText = '''
// Copyright 2013 The Flutter Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//    * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
''';
