// 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:test/test.dart';

import 'util.dart';

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

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

      final LicenseCheckCommand command = LicenseCheckCommand(
        packagesDir,
      );
      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.',
      ],
    }) {
      final List<String> lines = <String>['$prefix$comment$copyright'];
      for (final String line in license) {
        lines.add('$comment$line');
      }
      file.writeAsStringSync(lines.join('\n') + suffix + '\n');
    }

    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,
        '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('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, contains('Checking checked.cc'));
      expect(output, contains('All source 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, comment: '// ');
      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, contains('Checking file_a.cc'));
      expect(output, contains('Checking file_b.sh'));
      expect(output, contains('Checking file_c.html'));
      expect(output, contains('All source 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,
          contains(
              'The license block for these files is missing or incorrect:'));
      expect(output, contains('  bad.cc'));
      expect(output, contains('  bad.h'));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains('All source 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,
          contains(
              'The license block for these files is missing or incorrect:'));
      expect(output, contains('  bad.cc'));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains('All source 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,
          contains(
              'The license block for these files is missing or incorrect:'));
      expect(output, contains('  bad.cc'));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains('All source 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,
          contains(
              'The license block for these files is missing or incorrect:'));
      expect(output, contains('  third_party.cc'));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains('All source 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, contains('Checking a_plugin/lib/src/third_party/file.cc'));
      expect(output, contains('All source 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,
          contains('Checking a_plugin/lib/src/third_party/first_party.cc'));
      expect(output, contains('All source 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,
          contains(
              'No recognized license was found for the following third-party files:'));
      expect(output, contains('  third_party/bad.cc'));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains('All source 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,
          contains(
              'No recognized license was found for the following third-party files:'));
      expect(output, contains('  third_party/bad.cc'));
      // Failure shouldn't print the success message.
      expect(output, isNot(contains('All source 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, contains('Checking LICENSE'));
      expect(output, contains('All LICENSE 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('All LICENSE 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('Checking third_party/LICENSE')));
      expect(output, contains('All LICENSE files passed validation!'));
    });
  });
}

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.
''';
