// Copyright (c) 2012, 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.
//
// Process test program to test process communication.

// @dart = 2.9

library PlatformExecutableTest;

import "dart:io";

const _SCRIPT_KEY = '_test_script';

void expectEquals(a, b) {
  if (a != b) {
    throw 'Expected: $a\n'
        '  Actual: $b';
  }
}

void verify(String exePath, {String altPath}) {
  var env = {_SCRIPT_KEY: 'yes'};
  if (altPath != null) {
    env['PATH'] = altPath;
  }

  List<String> execArgs =
      ([]..addAll(Platform.executableArguments)
         ..add('--verbosity=warning'));
  var processResult = Process.runSync(
      exePath, [...execArgs, scriptPath],
      includeParentEnvironment: false, runInShell: true, environment: env);

  if (processResult.exitCode != 0) {
    throw 'Error with process\n'
        '$scriptPath'
        'Exit code: ${processResult.exitCode}\n'
        '   STDOUT: ${processResult.stdout}\n'
        '   STDERR: ${processResult.stderr}\n';
  }

  var result = processResult.stdout.trim();
  expectEquals(Platform.resolvedExecutable, result);
}

void testDartExecShouldNotBeInCurrentDir() {
  var type = FileSystemEntity.typeSync(platformExeName);
  expectEquals(FileSystemEntityType.notFound, type);
}

void testShouldFailOutsidePath() {
  var threw = false;
  try {
    Process.runSync(([platformExeName]..add('--verbosity=warning')).join(' '),
        ['--version'],
        includeParentEnvironment: false,
        environment: {_SCRIPT_KEY: 'yes', 'PATH': ''});
  } catch (_) {
    threw = true;
  }

  if (!threw) {
    throw 'Expected running the dart executable – "$platformExeName" without'
        ' the parent environment or path to fail.';
  }
}

void testShouldSucceedWithSourcePlatformExecutable() {
  verify(Platform.resolvedExecutable);
}

void testExeSymLinked(Directory dir) {
  var dirUri = new Uri.directory(dir.path);
  var link = new Link.fromUri(dirUri.resolve('dart_exe_link'));
  link.createSync(Platform.resolvedExecutable);
  verify(link.path);
}

void testPathToDirWithExeSymLinked(Directory dir) {
  var dirUri = new Uri.directory(dir.path);
  var link = new Link.fromUri(dirUri.resolve('dart_exe_link'));
  link.createSync(Platform.resolvedExecutable);
  verify('dart_exe_link', altPath: dir.path);
}

/// Create a sym-link to the SDK directory and run 'dart' from that path
void testExeDirSymLinked(Directory dir) {
  var dirUri = new Uri.directory(dir.path);

  var linkDirUri = dirUri.resolve('dart_bin_dir_link');
  var link = new Link.fromUri(linkDirUri);

  var exeFile = new File(Platform.resolvedExecutable);

  link.createSync(exeFile.parent.path);

  var linkedBin =
      new Uri.directory(linkDirUri.toFilePath()).resolve(platformExeName);

  verify(linkedBin.toFilePath());
}

void testPathPointsToSymLinkedSDKPath(Directory dir) {
  var dirUri = new Uri.directory(dir.path);

  var linkDirUri = dirUri.resolve('dart_bin_dir_link');
  var link = new Link.fromUri(linkDirUri);

  var exeFile = new File(Platform.resolvedExecutable);

  link.createSync(exeFile.parent.path);

  verify(platformExeName, altPath: link.path);
}

void testPathToSDKDir() {
  var exeFile = new File(Platform.resolvedExecutable);
  var binDirPath = exeFile.parent.path;

  verify(platformExeName, altPath: binDirPath);
}

void withTempDir(void test(Directory dir)) {
  var tempDir = Directory.systemTemp.createTempSync('dart.sdk.test.');
  try {
    test(tempDir);
  } finally {
    tempDir.deleteSync(recursive: true);
  }
}

String get platformExeName {
  var raw = new Uri.file(Platform.resolvedExecutable);
  return raw.pathSegments.last;
}

String get scriptPath => Platform.script.toFilePath();

void main() {
  // The same script is used for both running the tests and as for starting
  // child verifying the value of Platform.resolvedExecutable. If the
  // environment variable _SCRIPT_KEY is set this is a child process which
  // should print the value of Platform.resolvedExecutable.
  if (Platform.environment.containsKey(_SCRIPT_KEY)) {
    print(Platform.resolvedExecutable);
    return;
  }

  testDartExecShouldNotBeInCurrentDir();
  testShouldSucceedWithSourcePlatformExecutable(); //# 00: ok
  // dart:io does not support linking to files in Windows.
  if (!Platform.isWindows) {
    withTempDir(testExeSymLinked); //# 01: ok
  }
  withTempDir(testExeDirSymLinked); //# 02: ok
  testPathToSDKDir(); //# 03: ok
  withTempDir(testPathPointsToSymLinkedSDKPath); //# 04: ok
  // dart:io does not support linking to files in Windows.
  if (!Platform.isWindows) {
    withTempDir(testPathToDirWithExeSymLinked); //# 05: ok
  }
  testShouldFailOutsidePath(); //# 06: ok
}
