// 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.

// @dart = 2.8

import 'dart:io' as io show ProcessSignal;

import 'package:file/file.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/os.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:process/process.dart';
import 'package:test/fake.dart';

import '../src/common.dart';
import '../src/context.dart';
import '../src/fakes.dart';
import 'test_utils.dart';

final String dart = fileSystem.path
    .join(getFlutterRoot(), 'bin', platform.isWindows ? 'dart.bat' : 'dart');

void main() {
  group('Cache.lock', () {
    // Windows locking is too flaky for this to work reliably.
    if (platform.isWindows) {
      return;
    }
    testWithoutContext(
        'should log a message to stderr when lock is not acquired', () async {
      final String oldRoot = Cache.flutterRoot;
      final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('cache_test.');
      final BufferLogger logger = BufferLogger(
        terminal: Terminal.test(supportsColor: false, supportsEmoji: false),
        outputPreferences: OutputPreferences(),
      );
      logger.fatalWarnings = true;
      Process process;
      try {
        Cache.flutterRoot = tempDir.absolute.path;
        final Cache cache = Cache.test(
          fileSystem: fileSystem,
          processManager: FakeProcessManager.any(),
          logger: logger,
        );
        final File cacheFile = fileSystem.file(fileSystem.path
            .join(Cache.flutterRoot, 'bin', 'cache', 'lockfile'))
          ..createSync(recursive: true);
        final File script = fileSystem.file(fileSystem.path
            .join(Cache.flutterRoot, 'bin', 'cache', 'test_lock.dart'));
        script.writeAsStringSync(r'''
import 'dart:async';
import 'dart:io';

Future<void> main(List<String> args) async {
  File file = File(args[0]);
  final RandomAccessFile lock = file.openSync(mode: FileMode.write);
  while (true) {
    try {
      lock.lockSync();
      break;
    } on FileSystemException {}
  }
  await Future<void>.delayed(const Duration(seconds: 1));
  exit(0);
}
''');
        // Locks are per-process, so we have to launch a separate process to
        // test out cache locking.
        process = await const LocalProcessManager().start(
          <String>[dart, script.absolute.path, cacheFile.absolute.path],
        );
        // Wait for the script to lock the test cache file before checking to
        // see that the cache is unable to.
        bool locked = false;
        while (!locked) {
          // Give the script a chance to try for the lock much more often.
          await Future<void>.delayed(const Duration(milliseconds: 100));
          final RandomAccessFile lock = cacheFile.openSync(mode: FileMode.write);
          try {
            // If we can lock it, unlock immediately to give the script a
            // chance.
            lock.lockSync();
            lock.unlockSync();
          } on FileSystemException {
            // If we can't lock it, then the child script succeeded in locking
            // it, and we can now test.
            locked = true;
            break;
          }
        }
        // Finally, test that the cache cannot lock a locked file. This should
        // print a message if it can't lock the file.
        await cache.lock();
      } finally {
        // Just to keep from leaving the process hanging around.
        process?.kill(io.ProcessSignal.sighup);
        tryToDelete(tempDir);
        Cache.flutterRoot = oldRoot;
      }
      expect(logger.statusText, isEmpty);
      expect(logger.errorText, isEmpty);
      expect(logger.warningText,
          equals('Waiting for another flutter command to release the startup lock...\n'));
      expect(logger.hadErrorOutput, isFalse);
      // Should still be false, since the particular "Waiting..." message above
      // aims to avoid triggering failure as a fatal warning.
      expect(logger.hadWarningOutput, isFalse);
    });
    testWithoutContext(
        'should log a warning message for unknown version ', () async {
      final String oldRoot = Cache.flutterRoot;
      final Directory tempDir = fileSystem.systemTempDirectory.createTempSync('cache_test.');
      final BufferLogger logger = BufferLogger(
        terminal: Terminal.test(supportsColor: false, supportsEmoji: false),
        outputPreferences: OutputPreferences(),
      );
      logger.fatalWarnings = true;
      try {
        Cache.flutterRoot = tempDir.absolute.path;
        final Cache cache = Cache.test(
          fileSystem: fileSystem,
          processManager: FakeProcessManager.any(),
          logger: logger,
        );
        final FakeVersionlessArtifact artifact = FakeVersionlessArtifact(cache);
        cache.registerArtifact(artifact);
        await artifact.update(FakeArtifactUpdater(), logger, fileSystem, FakeOperatingSystemUtils());
      } finally {
        tryToDelete(tempDir);
        Cache.flutterRoot = oldRoot;
      }
      expect(logger.statusText, isEmpty);
      expect(logger.warningText, equals('No known version for the artifact name "fake". '
        'Flutter can continue, but the artifact may be re-downloaded on '
        'subsequent invocations until the problem is resolved.\n'));
      expect(logger.hadErrorOutput, isFalse);
      expect(logger.hadWarningOutput, isTrue);
    });
  });

  testWithoutContext('Dart SDK target arch matches host arch', () async {
    if (platform.isWindows) {
      return;
    }
    final ProcessResult dartResult = await const LocalProcessManager().run(
      <String>[dart, '--version'],
    );
    // Parse 'arch' out of a string like '... "os_arch"\n'.
    final String dartTargetArch = (dartResult.stdout as String)
      .trim().split(' ').last.replaceAll('"', '').split('_')[1];
    final ProcessResult unameResult = await const LocalProcessManager().run(
      <String>['uname', '-m'],
    );
    final String unameArch = (unameResult.stdout as String)
      .trim().replaceAll('aarch64', 'arm64')
             .replaceAll('x86_64', 'x64');
    expect(dartTargetArch, equals(unameArch));
  });
}

class FakeArtifactUpdater extends Fake implements ArtifactUpdater {
  void Function(String, Uri, Directory) onDownloadZipArchive;
  void Function(String, Uri, Directory) onDownloadZipTarball;

  @override
  Future<void> downloadZippedTarball(String message, Uri url, Directory location) async {
    onDownloadZipTarball?.call(message, url, location);
  }

  @override
  Future<void> downloadZipArchive(String message, Uri url, Directory location) async {
    onDownloadZipArchive?.call(message, url, location);
  }

  @override
  void removeDownloadedFiles() { }
}

class FakeVersionlessArtifact extends CachedArtifact {
  FakeVersionlessArtifact(Cache cache) : super(
    'fake',
    cache,
    DevelopmentArtifact.universal,
  );

  @override
  String get version => null;

  @override
  Future<void> updateInner(ArtifactUpdater artifactUpdater, FileSystem fileSystem, OperatingSystemUtils operatingSystemUtils) async { }
}
