// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. 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 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as p;
import 'package:test/test.dart';

import 'package:pub/src/exit_codes.dart' as exit_codes;
import 'package:pub/src/io.dart';

import 'descriptor.dart' as d;
import 'test_pub.dart';

void main() {
  setUp(() async {
    await servePackages((builder) {
      builder.serve('foo', '1.0.0');
      builder.serve('foo', '2.0.0');
    });

    await d.dir(appPath, [
      d.appPubspec(),
      d.dir('web', []),
      d.dir('bin', [d.file('script.dart', "main() => print('hello!');")])
    ]).create();

    await pubGet();
  });

  test(
      'does not require a pub get if a `flutter_gen` package is injected into package_config.json',
      () async {
    await d.dir('bar', [
      d.pubspec({'name': 'bar'})
    ]).create();
    await d.dir(appPath, [
      d.appPubspec({
        'bar': {'path': '../bar'}
      })
    ]).create();

    await pubGet();

    final packageConfig =
        p.join(d.sandbox, 'myapp', '.dart_tool', 'package_config.json');
    final contents = json.decode(readTextFile(packageConfig));
    contents['packages'].add({
      'name': 'flutter_gen',
      'rootUri': '.dart_tool/flutter_gen',
      'languageVersion': '2.8',
    });
    writeTextFile(packageConfig, json.encode(contents));

    await runPub(args: ['run', 'bin/script.dart'], output: 'hello!');
  });
  group('requires the user to run pub get first if', () {
    group("there's no lockfile", () {
      setUp(() {
        deleteEntry(p.join(d.sandbox, 'myapp/pubspec.lock'));
      });

      _requiresPubGet(
          'No pubspec.lock file found, please run "pub get" first.');
    });

    group("there's no package_config.json", () {
      setUp(() {
        deleteEntry(p.join(d.sandbox, 'myapp/.dart_tool/package_config.json'));
      });

      _requiresPubGet(
          'No .dart_tool/package_config.json file found, please run "pub get".');
    });

    group('the pubspec has a new dependency', () {
      setUp(() async {
        await d.dir('foo', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'foo': {'path': '../foo'}
          })
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');
      });

      _requiresPubGet('The pubspec.yaml file has changed since the '
          'pubspec.lock file was generated, please run "pub get" again.');
    });

    group('the lockfile has a dependency from the wrong source', () {
      setUp(() async {
        await d.dir(appPath, [
          d.appPubspec({'foo': '1.0.0'})
        ]).create();

        await pubGet();

        await createLockFile(appPath, sandbox: ['foo']);

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');
      });

      _requiresPubGet('The pubspec.yaml file has changed since the '
          'pubspec.lock file was generated, please run "pub get" again.');
    });

    group('the lockfile has a dependency from an unknown source', () {
      setUp(() async {
        await d.dir(appPath, [
          d.appPubspec({'foo': '1.0.0'})
        ]).create();

        await pubGet();

        await d.dir(appPath, [
          d.file(
              'pubspec.lock',
              yaml({
                'packages': {
                  'foo': {
                    'description': 'foo',
                    'version': '1.0.0',
                    'source': 'sdk'
                  }
                }
              }))
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');
      });

      _requiresPubGet('The pubspec.yaml file has changed since the '
          'pubspec.lock file was generated, please run "pub get" again.');
    });

    group('the lockfile has a dependency with the wrong description', () {
      setUp(() async {
        await d.dir('bar', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'foo': {'path': '../bar'}
          })
        ]).create();

        await pubGet();

        await createLockFile(appPath, sandbox: ['foo']);

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');
      });

      _requiresPubGet('The pubspec.yaml file has changed since the '
          'pubspec.lock file was generated, please run "pub get" again.');
    });

    group('the pubspec has an incompatible version of a dependency', () {
      setUp(() async {
        await d.dir(appPath, [
          d.appPubspec({'foo': '1.0.0'})
        ]).create();

        await pubGet();

        await d.dir(appPath, [
          d.appPubspec({'foo': '2.0.0'})
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');
      });

      _requiresPubGet('The pubspec.yaml file has changed since the '
          'pubspec.lock file was generated, please run "pub get" again.');
    });

    group(
        'the lockfile is pointing to an unavailable package with a newer '
        'pubspec', () {
      setUp(() async {
        await d.dir(appPath, [
          d.appPubspec({'foo': '1.0.0'})
        ]).create();

        await pubGet();

        deleteEntry(p.join(d.sandbox, cachePath));

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.yaml');
      });

      _requiresPubGet('The pubspec.yaml file has changed since the '
          'pubspec.lock file was generated, please run "pub get" again.');
    });

    group(
        'the lockfile is pointing to an unavailable package with an older '
        '.packages', () {
      setUp(() async {
        await d.dir(appPath, [
          d.appPubspec({'foo': '1.0.0'})
        ]).create();

        await pubGet();

        deleteEntry(p.join(d.sandbox, cachePath));

        // Ensure that the lockfile looks newer than the .packages file.
        await _touch('pubspec.lock');
      });

      _requiresPubGet('The pubspec.lock file has changed since the .packages '
          'file was generated, please run "pub get" again.');
    });

    group("the lockfile has a package that the .packages file doesn't", () {
      setUp(() async {
        await d.dir('foo', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'foo': {'path': '../foo'}
          })
        ]).create();

        await pubGet();

        await createPackagesFile(appPath);

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.lock');
      });

      _requiresPubGet('The pubspec.lock file has changed since the .packages '
          'file was generated, please run "pub get" again.');
    });

    group('the .packages file has a package with a non-file URI', () {
      setUp(() async {
        await d.dir('foo', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'foo': {'path': '../foo'}
          })
        ]).create();

        await pubGet();

        await d.dir(appPath, [
          d.file('.packages', '''
myapp:lib
foo:http://example.com/
''')
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.lock');
      });

      _requiresPubGet('The pubspec.lock file has changed since the .packages '
          'file was generated, please run "pub get" again.');
    });

    group('the .packages file points to the wrong place', () {
      setUp(() async {
        await d.dir('bar', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'foo': {'path': '../bar'}
          })
        ]).create();

        await pubGet();

        await createPackagesFile(appPath, sandbox: ['foo']);

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.lock');
      });

      _requiresPubGet('The pubspec.lock file has changed since the .packages '
          'file was generated, please run "pub get" again.');
    });

    group('the package_config.json file points to the wrong place', () {
      setUp(() async {
        await d.dir('bar', [d.libPubspec('foo', '1.0.0')]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'foo': {'path': '../bar'}
          })
        ]).create();

        await pubGet();

        await d.dir(appPath, [
          d.packageConfigFile([
            d.packageConfigEntry(
              name: 'foo',
              path: '../foo', // this is the wrong path
            ),
            d.packageConfigEntry(
              name: 'myapp',
              path: '.',
            ),
          ]),
        ]).create();

        // Ensure that the pubspec looks newer than the lockfile.
        await _touch('pubspec.lock');
      });

      _requiresPubGet('The pubspec.lock file has changed since the '
          '.dart_tool/package_config.json file was generated, '
          'please run "pub get" again.');
    });

    group("the lock file's SDK constraint doesn't match the current SDK", () {
      setUp(() async {
        // Avoid using a path dependency because it triggers the full validation
        // logic. We want to be sure SDK-validation works without that logic.
        globalPackageServer.add((builder) {
          builder.serve('foo', '3.0.0', pubspec: {
            'environment': {'sdk': '>=1.0.0 <2.0.0'}
          });
        });

        await d.dir(appPath, [
          d.pubspec({
            'name': 'myapp',
            'dependencies': {'foo': '3.0.0'},
            'environment': {
              'sdk': '>=1.0.0 <2.0.0',
            },
          }),
        ]).create();

        await pubGet(environment: {'_PUB_TEST_SDK_VERSION': '1.2.3+4'});
      });

      _requiresPubGet("Dart 0.1.2+3 is incompatible with your dependencies' "
          'SDK constraints. Please run \"pub get\" again.');
    });

    test(
        "the lock file's Flutter SDK constraint doesn't match the "
        'current Flutter SDK', () async {
      // Avoid using a path dependency because it triggers the full validation
      // logic. We want to be sure SDK-validation works without that logic.
      globalPackageServer.add((builder) {
        builder.serve('foo', '3.0.0', pubspec: {
          'environment': {'flutter': '>=1.0.0 <2.0.0'}
        });
      });

      await d.dir('flutter', [d.file('version', '1.2.3')]).create();

      await d.dir(appPath, [
        d.appPubspec({'foo': '3.0.0'})
      ]).create();

      await pubGet(environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')});

      await d.dir('flutter', [d.file('version', '0.9.0')]).create();

      // Run pub manually here because otherwise we don't have access to
      // d.sandbox.
      await runPub(
          args: ['run', 'script'],
          environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')},
          error: "Flutter 0.9.0 is incompatible with your dependencies' SDK "
              'constraints. Please run "pub get" again.',
          exitCode: exit_codes.DATA);
    });

    group("a path dependency's dependency doesn't match the lockfile", () {
      setUp(() async {
        await d.dir('bar', [
          d.libPubspec('bar', '1.0.0', deps: {'foo': '1.0.0'})
        ]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'bar': {'path': '../bar'}
          })
        ]).create();

        await pubGet();

        // Update bar's pubspec without touching the app's.
        await d.dir('bar', [
          d.libPubspec('bar', '1.0.0', deps: {'foo': '2.0.0'})
        ]).create();
      });

      _requiresPubGet('${p.join('..', 'bar', 'pubspec.yaml')} has changed '
          'since the pubspec.lock file was generated, please run "pub get" '
          'again.');
    });

    group(
        "a path dependency's language version doesn't match the package_config.json",
        () {
      setUp(() async {
        await d.dir('bar', [
          d.libPubspec(
            'bar',
            '1.0.0',
            deps: {'foo': '1.0.0'},
            // Creates language version requirement 0.0
            sdk: '>= 0.0.1 <=0.9.9', // tests runs with '0.1.2+3'
          ),
        ]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'bar': {'path': '../bar'}
          })
        ]).create();

        await pubGet();

        // Update bar's pubspec without touching the app's.
        await d.dir('bar', [
          d.libPubspec(
            'bar',
            '1.0.0',
            deps: {'foo': '1.0.0'},
            // Creates language version requirement 0.1
            sdk: '>= 0.1.0 <=0.9.9', // tests runs with '0.1.2+3'
          ),
        ]).create();
      });

      _requiresPubGet('${p.join('..', 'bar', 'pubspec.yaml')} has changed '
          'since the pubspec.lock file was generated, please run "pub get" '
          'again.');
    });
  });

  group("doesn't require the user to run pub get first if", () {
    group(
        'the pubspec is older than the lockfile which is older than the '
        'packages file, even if the contents are wrong', () {
      setUp(() async {
        await d.dir(appPath, [
          d.appPubspec({'foo': '1.0.0'})
        ]).create();
        // Ensure we get a new mtime (mtime is only reported with 1s precision)
        await _touch('pubspec.yaml');

        await _touch('pubspec.lock');
        await _touch('.packages');
        await _touch('.dart_tool/package_config.json');
      });

      _runsSuccessfully(runDeps: false);
    });

    group("the pubspec is newer than the lockfile, but they're up-to-date", () {
      setUp(() async {
        await d.dir(appPath, [
          d.appPubspec({'foo': '1.0.0'})
        ]).create();

        await pubGet();

        await _touch('pubspec.yaml');
      });

      _runsSuccessfully();
    });

    // Regression test for #1416
    group('a path dependency has a dependency on the root package', () {
      setUp(() async {
        await d.dir('foo', [
          d.libPubspec('foo', '1.0.0', deps: {'myapp': 'any'})
        ]).create();

        await d.dir(appPath, [
          d.appPubspec({
            'foo': {'path': '../foo'}
          })
        ]).create();

        await pubGet();

        await _touch('pubspec.lock');
      });

      _runsSuccessfully();
    });

    group("the lockfile is newer than package_config.json, but it's up-to-date",
        () {
      setUp(() async {
        await d.dir(appPath, [
          d.appPubspec({'foo': '1.0.0'})
        ]).create();

        await pubGet();

        await _touch('pubspec.lock');
      });

      _runsSuccessfully();
    });

    group("an overridden dependency's SDK constraint is unmatched", () {
      setUp(() async {
        globalPackageServer.add((builder) {
          builder.serve('bar', '1.0.0', pubspec: {
            'environment': {'sdk': '0.0.0-fake'}
          });
        });

        await d.dir(appPath, [
          d.pubspec({
            'name': 'myapp',
            'dependency_overrides': {'bar': '1.0.0'}
          })
        ]).create();

        await pubGet();

        await _touch('pubspec.lock');
      });

      _runsSuccessfully();
    });

    test('the lock file has a Flutter SDK but Flutter is unavailable',
        () async {
      // Avoid using a path dependency because it triggers the full validation
      // logic. We want to be sure SDK-validation works without that logic.
      globalPackageServer.add((builder) {
        builder.serve('foo', '3.0.0', pubspec: {
          'environment': {'flutter': '>=1.0.0 <2.0.0'}
        });
      });

      await d.dir('flutter', [d.file('version', '1.2.3')]).create();

      await d.dir(appPath, [
        d.appPubspec({'foo': '3.0.0'})
      ]).create();

      await pubGet(environment: {'FLUTTER_ROOT': p.join(d.sandbox, 'flutter')});

      await d.dir('flutter', [d.file('version', '2.4.6')]).create();

      // Run pub manually here because otherwise we don't have access to
      // d.sandbox.
      await runPub(args: ['run', 'bin/script.dart']);
    });
  });
}

/// Runs every command that care about the world being up-to-date, and asserts
/// that it prints [message] as part of its error.
void _requiresPubGet(String message) {
  for (var command in ['run', 'deps']) {
    test('for pub $command', () {
      var args = [command];
      if (command == 'run') args.add('script');

      return runPub(
          args: args, error: contains(message), exitCode: exit_codes.DATA);
    });
  }
}

/// Ensures that pub doesn't require "pub get" for the current package.
///
/// If [runDeps] is false, `pub deps` isn't included in the test. This is
/// sometimes not desirable, since it uses slightly stronger checks for pubspec
/// and lockfile consistency.
void _runsSuccessfully({bool runDeps = true}) {
  var commands = ['run'];
  if (runDeps) commands.add('deps');

  for (var command in commands) {
    test('for pub $command', () async {
      var args = [command];
      if (command == 'run') args.add('bin/script.dart');

      await runPub(args: args);

      // If pub determines that everything is up-to-date, it should set the
      // mtimes to indicate that.
      var pubspecModified =
          File(p.join(d.sandbox, 'myapp/pubspec.yaml')).lastModifiedSync();
      var lockFileModified =
          File(p.join(d.sandbox, 'myapp/pubspec.lock')).lastModifiedSync();
      var packagesModified =
          File(p.join(d.sandbox, 'myapp/.packages')).lastModifiedSync();
      var packageConfigModified =
          File(p.join(d.sandbox, 'myapp/.dart_tool/package_config.json'))
              .lastModifiedSync();

      expect(!pubspecModified.isAfter(lockFileModified), isTrue);
      expect(!lockFileModified.isAfter(packagesModified), isTrue);
      expect(!lockFileModified.isAfter(packageConfigModified), isTrue);
    });
  }
}

/// Schedules a non-semantic modification to [path].
Future _touch(String path) async {
  // Delay a bit to make sure the modification times are noticeably different.
  // 1s seems to be the finest granularity that dart:io reports.
  await Future.delayed(Duration(seconds: 1));

  path = p.join(d.sandbox, 'myapp', path);
  touch(path);
}
