// 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.
//
// Dart test program for testing FileSystemEntity.resolveSymbolicLinks

import "package:expect/expect.dart";
import "package:path/path.dart";
import "package:async_helper/async_helper.dart";
import 'dart:async';
import 'dart:io';

main() {
  String testsDir = Platform.script.resolve('../..').toFilePath();
  // All of these tests test that resolveSymbolicLinks gives a path
  // that points to the same place as the original, and that it removes
  // all links, .., and . segments, and that it produces an absolute path.
  asyncTest(() => testFile(join(
      testsDir, 'standalone', 'io', 'resolve_symbolic_links_test.dart')));
  asyncTest(() => testFile(join(testsDir, 'standalone', 'io', '..', 'io',
                                'resolve_symbolic_links_test.dart')));

  asyncTest(() => testDir(join(testsDir, 'standalone', 'io')));
  asyncTest(() => testDir(join(testsDir, 'lib', '..', 'standalone', 'io')));
  // Test a relative path.
  asyncTest(() => testDir('.'));
  if (Platform.isWindows) {
    asyncTest(() =>testFile(join('\\\\?\\$testsDir', 'standalone', 'io',
                                 'resolve_symbolic_links_test.dart')));
    asyncTest(() => testDir('\\\\?\\$testsDir'));
  }
  asyncTest(() => Directory.systemTemp.createTemp('dart_resolve_symbolic_links')
      .then((tempDir) {
    String temp = tempDir.path;
    return makeEntities(temp).then((_) => Future.wait(
        [testFile(join(temp, 'dir1', 'file1')),
         testFile(join(temp, 'link1', 'file2')),
         testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
         testDir(join(temp, 'dir1', 'dir2', '..', '.', '..', 'dir1')),
         testLink(join(temp, 'link1'))]))
    .then((_) {
      if (Platform.isWindows) {
        // Windows applies '..' to a link without resolving the link first.
        return Future.wait([
            testFile(join(
                temp, 'dir1', '..', 'link1', '..', 'dir1', 'dir2', 'file2')),
            testDir(join(temp, 'dir1', '..', 'link1', '..', 'dir1')),
            testLink(join(temp, 'link1', '..', 'link1'))]);
      } else {
       // Non-Windows platforms resolve the link before adding the '..'.
        return Future.wait([
            testFile(join(
                temp, 'dir1', '..', 'link1', '..', 'dir2', 'file2')),
            testDir(join(temp, 'dir1', '..', 'link1', '..', 'dir2')),
            testLink(join(temp, 'link1', '..', '..', 'link1'))]);
      }
    })
    .then((_) {
      Directory.current = temp;
      return Future.wait([
          testFile('dir1/dir2/file2'),  // Test forward slashes on Windows too.
          testFile('link1/file2'),
          testFile(join('dir1', '..', 'dir1', '.', 'file1')),
          testDir('.'),
          testLink('link1')]);
    })
    .then((_) {
      Directory.current = 'link1';
      if (Platform.isWindows) {
        return Future.wait([
          testFile('file2'),
          // Windows applies '..' to a link without resolving the link first.
          testFile('..\\dir1\\file1'),
          testLink('.'),
          testDir('..'),
          testLink('..\\link1')]);
      } else {
        return Future.wait([
          testFile('file2'),
          // On non-Windows the link is changed to dir1/dir2 before .. happens.
          testFile('../dir2/file2'),
          testDir('.'),
          testDir('..'),
          testLink('../../link1')]);
      }
    })
    .whenComplete(() {
      Directory.current = testsDir;
      tempDir.delete(recursive: true);
    });
  }));
}

Future makeEntities(String temp) {
  return new Directory(join(temp, 'dir1', 'dir2')).create(recursive: true)
      .then((_) => new File(join(temp, 'dir1', 'dir2', 'file2')).create())
      .then((_) => new File(join(temp, 'dir1', 'file1')).create())
      .then((_) => new Link(join(temp, 'link1'))
            .create(join(temp, 'dir1', 'dir2')));
}

Future testFile(String name) {
  // We test that f.resolveSymbolicLinks points to the same place
  // as f, because the actual resolved path is not easily predictable.
  // The location of the temp directory varies from system to system,
  // and its path includes symbolic links on some systems.
  //Expect.isTrue(FileSystemEntity.identicalSync(name,
  //   new File(name).resolveSymbolicLinksSync()));
  return new File(name).resolveSymbolicLinks().then((String resolved) {
  //Expect.isTrue(FileSystemEntity.identicalSync(name, resolved));
    Expect.isTrue(isAbsolute(resolved));
    // Test that resolveSymbolicLinks removes all links, .., and . segments.
    Expect.isFalse(resolved.contains('..'));
    Expect.isFalse(resolved.contains('./'));
    Expect.isFalse(resolved.contains('link1'));
  });
}

Future testDir(String name) {
  Expect.isTrue(FileSystemEntity.identicalSync(name,
      new Directory(name).resolveSymbolicLinksSync()));
  return new Directory(name).resolveSymbolicLinks().then((String resolved) {
    Expect.isTrue(FileSystemEntity.identicalSync(name, resolved));
    Expect.isTrue(isAbsolute(resolved));
    // Test that resolveSymbolicLinks removes all links, .., and . segments.
    Expect.isFalse(resolved.contains('..'));
    Expect.isFalse(resolved.contains('./'));
    Expect.isFalse(resolved.contains('link1'));
  });
}

Future testLink(String name) {
  Expect.isFalse(FileSystemEntity.identicalSync(name,
      new Link(name).resolveSymbolicLinksSync()));
  Expect.isTrue(FileSystemEntity.identicalSync(new Link(name).targetSync(),
      new Link(name).resolveSymbolicLinksSync()));
  return new Link(name).resolveSymbolicLinks().then((String resolved) {
    Expect.isFalse(FileSystemEntity.identicalSync(name, resolved));
    Expect.isTrue(isAbsolute(resolved));
    // Test that resolveSymbolicLinks removes all links, .., and . segments.
    Expect.isFalse(resolved.contains('..'));
    Expect.isFalse(resolved.contains('./'));
    Expect.isFalse(resolved.contains('link1'));
    return new Link(name).target()
        .then((targetName) => FileSystemEntity.identical(targetName, resolved))
        .then((identical) => Expect.isTrue(identical));
  });
}
