// Copyright (c) 2013, 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.

// OtherResources=skipping_dart2js_compilations_helper.dart

/*
 * This test makes sure that the "skipping Dart2Js compilations if the output is
 * already up to date" feature does work as it should.
 * Therefore this test ensures that compilations are only skipped if the last
 * modified date of the output of a dart2js compilation is newer than
 *   - the dart application to compile (including it's dependencies)
 *   - the dart2js snapshot
 * Furthermore it ensures that a compilation is not skipped if any of the
 * necessary files could not be found (dart2js snapshots, previous dart2js
 * output (+deps file), dart application)
 */

import 'dart:async';
import 'dart:io';

import 'package:expect/expect.dart';

import 'package:test_runner/src/command.dart';
import 'package:test_runner/src/command_output.dart';
import 'package:test_runner/src/path.dart';
import 'package:test_runner/src/repository.dart';
import 'package:test_runner/src/test_case.dart';

/// This class is reponsible for setting up the files necessary for this test
/// as well as touching a file.
class FileUtils {
  Directory tempDir;
  File testJs;
  File testJsDeps;
  File testDart;
  File testSnapshot;

  FileUtils(
      {bool createJs,
      bool createJsDeps,
      bool createDart,
      bool createSnapshot}) {
    tempDir = Directory.systemTemp
        .createTempSync('dart_skipping_dart2js_compilations');
    if (createJs) {
      testJs = _createFile(testJsFilePath);
      _writeToFile(testJs, "test.js content");
    }
    if (createSnapshot) {
      testSnapshot = _createFile(testSnapshotFilePath);
      _writeToFile(testSnapshot, "dart2js snapshot");
    }
    if (createDart) {
      testDart = _createFile(testDartFilePath);
      _writeToFile(testDart, "dart code");
    }
    if (createJsDeps) {
      testJsDeps = _createFile(testJsDepsFilePath);
      var path = Path(tempDir.path).append("test.dart").absolute;
      _writeToFile(testJsDeps, "file://$path");
    }
  }

  void cleanup() {
    if (testJs != null) testJs.deleteSync();
    if (testJsDeps != null) testJsDeps.deleteSync();
    if (testDart != null) testDart.deleteSync();
    if (testSnapshot != null) testSnapshot.deleteSync();

    // if the script did run, it created this file, so we need to delete it
    File file = File(scriptOutputPath.toNativePath());
    if (file.existsSync()) {
      file.deleteSync();
    }

    tempDir.deleteSync();
  }

  Path get scriptOutputPath {
    return Path(tempDir.path).append('created_if_command_did_run.txt').absolute;
  }

  Path get testDartFilePath {
    return Path(tempDir.path).append('test.dart').absolute;
  }

  Path get testJsFilePath {
    return Path(tempDir.path).append('test.js').absolute;
  }

  Path get testJsDepsFilePath {
    return Path(tempDir.path).append('test.js.deps').absolute;
  }

  Path get testSnapshotFilePath {
    return Path(tempDir.path).append('test_dart2js.snapshot').absolute;
  }

  void touchFile(File file) {
    _writeToFile(file, _readFile(file));
  }

  void _writeToFile(File file, String content) {
    if (content != null) {
      var fd =
          File(file.resolveSymbolicLinksSync()).openSync(mode: FileMode.write);
      fd.writeStringSync(content);
      fd.closeSync();
    }
  }

  String _readFile(File file) {
    return file.readAsStringSync();
  }

  File _createFile(Path path) {
    var file = File(path.toNativePath());
    file.createSync();
    return file;
  }
}

class CommandCompletedHandler {
  FileUtils fileUtils;
  bool _shouldHaveRun;

  CommandCompletedHandler(FileUtils this.fileUtils, bool this._shouldHaveRun);

  void processCompletedTest(CommandOutput output) {
    Expect.equals(0, output.exitCode);
    Expect.equals(0, output.stderr.length);
    if (_shouldHaveRun) {
      Expect.equals(0, output.stdout.length);
      Expect.isTrue(
          File(fileUtils.scriptOutputPath.toNativePath()).existsSync());
    } else {
      Expect.isFalse(
          File(fileUtils.scriptOutputPath.toNativePath()).existsSync());
    }
  }
}

Command makeCompilationCommand(String testName, FileUtils fileUtils) {
  var createFileScript = Platform.script
      .resolve('skipping_dart2js_compilations_helper.dart')
      .toFilePath();
  var executable = Platform.executable;
  var arguments = <String>[]
    ..addAll(Platform.executableArguments)
    ..add(createFileScript)
    ..add(fileUtils.scriptOutputPath.toNativePath());
  var bootstrapDeps = [Uri.parse("file://${fileUtils.testSnapshotFilePath}")];
  return Command.compilation('dart2js', fileUtils.testJsFilePath.toNativePath(),
      bootstrapDeps, executable, arguments, {},
      alwaysCompile: false);
}

void main() {
  // This script is in [sdk]/pkg/test_runner/test.
  Repository.uri = Platform.script.resolve('../../..');

  var fs_noTestJs = FileUtils(
      createJs: false,
      createJsDeps: true,
      createDart: true,
      createSnapshot: true);
  var fs_noTestJsDeps = FileUtils(
      createJs: true,
      createJsDeps: false,
      createDart: true,
      createSnapshot: true);
  var fs_noTestDart = FileUtils(
      createJs: true,
      createJsDeps: true,
      createDart: false,
      createSnapshot: true);
  var fs_noTestSnapshot = FileUtils(
      createJs: true,
      createJsDeps: true,
      createDart: true,
      createSnapshot: false);
  var fs_notUpToDate_snapshot = FileUtils(
      createJs: true,
      createJsDeps: true,
      createDart: true,
      createSnapshot: true);
  var fs_notUpToDate_dart = FileUtils(
      createJs: true,
      createJsDeps: true,
      createDart: true,
      createSnapshot: true);
  var fs_upToDate = FileUtils(
      createJs: true,
      createJsDeps: true,
      createDart: true,
      createSnapshot: true);
  void cleanup() {
    fs_noTestJs.cleanup();
    fs_noTestJsDeps.cleanup();
    fs_noTestDart.cleanup();
    fs_noTestSnapshot.cleanup();
    fs_notUpToDate_snapshot.cleanup();
    fs_notUpToDate_dart.cleanup();
    fs_upToDate.cleanup();
  }

  void touchFilesAndRunTests() {
    fs_notUpToDate_snapshot.touchFile(fs_notUpToDate_snapshot.testSnapshot);
    fs_notUpToDate_dart.touchFile(fs_notUpToDate_dart.testDart);
    fs_upToDate.touchFile(fs_upToDate.testJs);

    Future runTest(String name, FileUtils fileUtils, bool shouldRun) {
      var completedHandler = CommandCompletedHandler(fileUtils, shouldRun);
      var command = makeCompilationCommand(name, fileUtils) as ProcessCommand;
      var process = RunningProcess(command, 60);
      return process.run().then((CommandOutput output) {
        completedHandler.processCompletedTest(output);
      });
    }

    // We run the tests in sequence, so that if one of them fails we clean up
    // everything and throw.
    runTest("fs_noTestJs", fs_noTestJs, true).then((_) {
      return runTest("fs_noTestJsDeps", fs_noTestJsDeps, true);
    }).then((_) {
      return runTest("fs_noTestDart", fs_noTestDart, true);
    }).then((_) {
      return runTest("fs_noTestSnapshot", fs_noTestSnapshot, true);
    }).then((_) {
      return runTest("fs_notUpToDate_snapshot", fs_notUpToDate_snapshot, true);
    }).then((_) {
      return runTest("fs_notUpToDate_dart", fs_notUpToDate_dart, true);
    }).then((_) {
      // This is the only test where all dependencies are present and the
      // test.js file is newer than all the others. So we pass 'false' for
      // shouldRun.
      return runTest("fs_upToDate", fs_upToDate, false);
    }).catchError((error) {
      cleanup();
      throw error;
    }).then((_) {
      cleanup();
    });
  }

  // We need to wait some time to make sure that the files we 'touch' get a
  // bigger timestamp than the old ones
  Timer(Duration(seconds: 1), touchFilesAndRunTests);
}
