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

library test.source.caching_pub_package_map_provider;

import 'dart:convert';
import 'dart:core' hide Resource;
import 'dart:io' as io;

import 'package:analysis_server/src/source/caching_pub_package_map_provider.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/source/package_map_provider.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/sdk_io.dart';
import 'package:unittest/unittest.dart';

import '../utils.dart';

main() {
  initializeTestEnvironment();

  group('CachingPubPackageMapProvider', () {
    MemoryResourceProvider resProvider;
    _MockPubListRunner mockRunner;
    bool writeFileException;

    Map result1 = {
      'packages': {'foo': '/tmp/proj1/packages/foo'},
      'input_files': ['/tmp/proj1/pubspec.yaml']
    };

    Map result1error = {
      'input_files': ['/tmp/proj1/pubspec.lock']
    };

    Map result2 = {
      'packages': {'bar': '/tmp/proj2/packages/bar'},
      'input_files': ['/tmp/proj2/pubspec.yaml']
    };

    Folder newProj(Map result) {
      Map packages = result['packages'];
      packages.forEach((String name, String path) {
        resProvider.newFolder(path);
      });
      List<String> inputFiles = result['input_files'];
      for (String path in inputFiles) {
        resProvider.newFile(path, '');
      }
      return resProvider.getResource(inputFiles[0]).parent;
    }

    int mockWriteFile(File cacheFile, String content) {
      if (writeFileException) {
        throw 'simulated write failure: $cacheFile';
      }
      if (!cacheFile.exists) {
        resProvider.newFolder(cacheFile.parent.path);
        resProvider.newFile(cacheFile.path, content);
      } else {
        resProvider.modifyFile(cacheFile.path, content);
      }
      Resource res = resProvider.getResource(cacheFile.path);
      if (res is File) {
        return res.createSource().modificationStamp;
      }
      throw 'expected file, but found $res';
    }

    CachingPubPackageMapProvider newPkgProvider() {
      return new CachingPubPackageMapProvider(
          resProvider,
          DirectoryBasedDartSdk.defaultSdk,
          mockRunner.runPubList,
          mockWriteFile);
    }

    setUp(() {
      resProvider = new MemoryResourceProvider();
      resProvider.newFolder('/tmp/proj/packages/foo');
      mockRunner = new _MockPubListRunner();
      writeFileException = false;
    });

    group('computePackageMap', () {
      // Assert pub list called once and results are cached in memory
      test('cache memory', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);
      });

      // Assert pub list called once and results are cached on disk
      test('cache disk', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider1 = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider1.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        CachingPubPackageMapProvider pkgProvider2 = newPkgProvider();
        info = pkgProvider2.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);
      });

      // Assert pub list called even if cache file is corrupted
      test('corrupt cache file', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider1 = newPkgProvider();
        resProvider.newFile(pkgProvider1.cacheFile.path, 'corrupt content');
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider1.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        CachingPubPackageMapProvider pkgProvider2 = newPkgProvider();
        info = pkgProvider2.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);
      });

      // Assert gracefully continue even if write to file fails
      test('failed write to cache file', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result1);
        writeFileException = true;
        PackageMapInfo info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);
      });

      // Assert modification in one shows up in the other
      test('shared disk cache', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider1 = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider1.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        Folder folder2 = newProj(result2);
        CachingPubPackageMapProvider pkgProvider2 = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result2);
        info = pkgProvider2.computePackageMap(folder2);
        expect(mockRunner.runCount, 2);
        _assertInfo(info, result2);

        info = pkgProvider1.computePackageMap(folder2);
        expect(mockRunner.runCount, 2);
        _assertInfo(info, result2);
      });

      // Assert pub list called again if input file modified
      test('input file changed', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        resProvider.modifyFile(info.dependencies.first, 'new content');
        mockRunner.nextResult = JSON.encode(result1);
        info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 2);
        _assertInfo(info, result1);
      });

      // Assert pub list called again if input file modified
      // after reloading package provider cache from disk
      test('input file changed 2', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider1 = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider1.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        resProvider.modifyFile(info.dependencies.first, 'new content');
        mockRunner.nextResult = JSON.encode(result1);
        CachingPubPackageMapProvider pkgProvider2 = newPkgProvider();
        info = pkgProvider2.computePackageMap(folder1);
        expect(mockRunner.runCount, 2);
        _assertInfo(info, result1);
      });

      // Assert pub list called again if input file deleted
      test('input file deleted', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        resProvider.deleteFile(info.dependencies.first);
        mockRunner.nextResult = JSON.encode(result1);
        info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 2);
        _assertInfo(info, result1);
      });

      // Assert pub list not called if folder does not exist
      // and returns same cached result if folder restored as before
      test('project removed then restored', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        CachingPubPackageMapProvider pkgProvider = newPkgProvider();
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);

        _RestorePoint restorePoint = new _RestorePoint(resProvider, folder1);
        resProvider.deleteFolder(folder1.path);
        info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertError(info, result1error);

        restorePoint.restore();
        info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 1);
        _assertInfo(info, result1);
      });

      // Assert pub list *is* run again
      // if dependency has changed during execution
      test('dependency changed during execution', () {
        expect(mockRunner.runCount, 0);

        Folder folder1 = newProj(result1);
        Resource pubspecFile = folder1.getChild('pubspec.yaml');
        expect(pubspecFile.exists, isTrue);
        CachingPubPackageMapProvider pkgProvider = newPkgProvider();
        mockRunner.nextResultFunction = () {
          resProvider.modifyFile(pubspecFile.path, 'new content');
          return JSON.encode(result1);
        };
        mockRunner.nextResult = JSON.encode(result1);
        PackageMapInfo info = pkgProvider.computePackageMap(folder1);
        expect(mockRunner.runCount, 2);
        _assertInfo(info, result1);
      });
    });
  });
}

_assertError(PackageMapInfo info, Map expected) {
  expect(info.packageMap, isNull);
  List<String> expectedFiles = expected['input_files'];
  expect(info.dependencies, hasLength(expectedFiles.length));
  for (String path in expectedFiles) {
    expect(info.dependencies, contains(path));
  }
}

_assertInfo(PackageMapInfo info, Map expected) {
  Map<String, String> expectedPackages = expected['packages'];
  expect(info.packageMap, hasLength(expectedPackages.length));
  for (String key in expectedPackages.keys) {
    List<Folder> packageList = info.packageMap[key];
    expect(packageList, hasLength(1));
    expect(packageList[0].path, expectedPackages[key]);
  }
  List<String> expectedFiles = expected['input_files'];
  expect(info.dependencies, hasLength(expectedFiles.length));
  for (String path in expectedFiles) {
    expect(info.dependencies, contains(path));
  }
}

typedef String MockResultFunction();

/**
 * Mock for simulating and tracking execution of pub list
 */
class _MockPubListRunner {
  int runCount = 0;
  List nextResults = [];

  void set nextResult(String result) {
    nextResults.add(result);
  }

  void set nextResultFunction(MockResultFunction resultFunction) {
    nextResults.add(resultFunction);
  }

  io.ProcessResult runPubList(Folder folder) {
    if (nextResults.isEmpty) {
      throw 'missing nextResult';
    }
    var result = nextResults.removeAt(0);
    if (result is MockResultFunction) {
      result = result();
    }
    ++runCount;
    return new _MockResult(result);
  }
}

class _MockResult implements io.ProcessResult {
  String result;

  _MockResult(this.result);

  @override
  int get exitCode => 0;

  // TODO: implement stdout
  @override
  get stdout => result;

  noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}

/**
 * An object containing information to restore the state of a deleted
 * folder and its content.
 */
class _RestorePoint {
  final MemoryResourceProvider provider;
  final List<String> _folderPaths = <String>[];
  final List<String> _filePaths = <String>[];
  final List<TimestampedData> _fileContents = <TimestampedData>[];

  /**
   * Construct a new instance that captures the current state of the folder
   * and all of its contained files and folders.
   */
  _RestorePoint(this.provider, Folder folder) {
    record(folder);
  }

  /**
   * Capture the current state of the folder
   * and all of its contained files and folders.
   */
  void record(Folder folder) {
    _folderPaths.add(folder.path);
    for (Resource child in folder.getChildren()) {
      if (child is Folder) {
        record(child);
      } else if (child is File) {
        _filePaths.add(child.path);
        _fileContents.add(child.createSource().contents);
      } else {
        throw 'unknown resource: $child';
      }
    }
  }

  /**
   * Restore the original files and folders.
   */
  void restore() {
    for (String path in _folderPaths) {
      provider.newFolder(path);
    }
    int fileCount = _filePaths.length;
    for (int fileIndex = 0; fileIndex < fileCount; ++fileIndex) {
      String path = _filePaths[fileIndex];
      TimestampedData content = _fileContents[fileIndex];
      provider.newFile(path, content.data, content.modificationTime);
    }
  }
}
