// 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.
//
// Dart test program for testing error handling in directory I/O.

// @dart = 2.9

import "dart:async";
import "dart:io";

import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";

Directory tempDir() {
  return Directory.systemTemp.createTempSync('dart_directory_error');
}

bool checkCreateInNonExistentFileSystemException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  Expect.isTrue(e.toString().indexOf("Creation failed") != -1);
  if (Platform.operatingSystem == "linux") {
    Expect.equals(2, e.osError.errorCode);
  } else if (Platform.operatingSystem == "macos") {
    Expect.equals(2, e.osError.errorCode);
  } else if (Platform.operatingSystem == "windows") {
    Expect.equals(3, e.osError.errorCode);
  }

  return true;
}

void testCreateInNonExistent(Directory temp, Function done) {
  Directory inNonExistent = new Directory("${temp.path}/nonExistent/xxx");
  Expect.throws(() => inNonExistent.createSync(),
      (e) => checkCreateInNonExistentFileSystemException(e));

  inNonExistent.create().catchError((error) {
    checkCreateInNonExistentFileSystemException(error);
    done();
  });
}

bool checkCreateTempInNonExistentFileSystemException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  if (Platform.operatingSystem == "linux") {
    Expect.equals(2, e.osError.errorCode);
  } else if (Platform.operatingSystem == "macos") {
    Expect.equals(2, e.osError.errorCode);
  } else if (Platform.operatingSystem == "windows") {
    Expect.equals(3, e.osError.errorCode);
  }

  return true;
}

void testCreateTempInNonExistent(Directory temp, Function done) {
  Directory nonExistent = new Directory("${temp.path}/nonExistent/xxx");
  Expect.throws(() => nonExistent.createTempSync('tempdir'),
      (e) => checkCreateTempInNonExistentFileSystemException(e));

  nonExistent.createTemp('tempdir').catchError((error) {
    checkCreateTempInNonExistentFileSystemException(error);
    done();
  });
}

bool checkDeleteNonExistentFileSystemException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  // File not not found has error code 2 on all supported platforms.
  Expect.equals(2, e.osError.errorCode);

  return true;
}

void testDeleteNonExistent(Directory temp, Function done) {
  Directory nonExistent = new Directory("${temp.path}/nonExistent");
  Expect.throws(() => nonExistent.deleteSync(),
      (e) => checkDeleteNonExistentFileSystemException(e));

  nonExistent.delete().catchError((error) {
    checkDeleteNonExistentFileSystemException(error);
    done();
  });
}

bool checkDeleteRecursivelyNonExistentFileSystemException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  Expect.isTrue(e.toString().indexOf("Deletion failed") != -1);
  // File not not found has error code 2 on all supported platforms.
  Expect.equals(2, e.osError.errorCode);

  return true;
}

void testDeleteRecursivelyNonExistent(Directory temp, Function done) {
  Directory nonExistent = new Directory("${temp.path}/nonExistent");
  Expect.throws(() => nonExistent.deleteSync(recursive: true),
      (e) => checkDeleteRecursivelyNonExistentFileSystemException(e));

  nonExistent.delete(recursive: true).catchError((error) {
    checkDeleteRecursivelyNonExistentFileSystemException(error);
    done();
  });
}

bool checkListNonExistentFileSystemException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  Expect.isTrue(e.toString().indexOf("Directory listing failed") != -1);
  if (Platform.operatingSystem == "linux") {
    Expect.equals(2, e.osError.errorCode);
  } else if (Platform.operatingSystem == "macos") {
    Expect.equals(2, e.osError.errorCode);
  } else if (Platform.operatingSystem == "windows") {
    Expect.equals(3, e.osError.errorCode);
  }

  return true;
}

bool checkAsyncListNonExistentFileSystemException(error) {
  return checkListNonExistentFileSystemException(error);
}

void testListNonExistent(Directory temp, Function done) {
  Directory nonExistent = new Directory("${temp.path}/nonExistent");
  Expect.throws(() => nonExistent.listSync(), (e) => e is FileSystemException);
  nonExistent.list().listen((_) => Expect.fail("listing should not succeed"),
      onError: (e) {
    checkAsyncListNonExistentFileSystemException(e);
    done();
  });
}

void testRenameNonExistent(Directory temp, Function done) {
  Directory nonExistent = new Directory("${temp.path}/nonExistent");
  var newPath = "${temp.path}/nonExistent2";
  Expect.throws(
      () => nonExistent.renameSync(newPath), (e) => e is FileSystemException);
  var renameDone = nonExistent.rename(newPath);
  renameDone
      .then((ignore) => Expect.fail('rename non existent'))
      .catchError((error) {
    Expect.isTrue(error is FileSystemException);
    done();
  });
}

void testRenameFileAsDirectory(Directory temp, Function done) {
  File f = new File("${temp.path}/file");
  var newPath = "${temp.path}/file2";
  f.createSync();
  var d = new Directory(f.path);
  Expect.throws(() => d.renameSync(newPath), (e) => e is FileSystemException);
  var renameDone = d.rename(newPath);
  renameDone
      .then((ignore) => Expect.fail('rename file as directory'))
      .catchError((error) {
    Expect.isTrue(error is FileSystemException);
    done();
  });
}

testRenameOverwriteFile(Directory temp, Function done) {
  var temp1 = Directory.systemTemp.createTempSync('dart_directory_error');
  var fileName = '${temp.path}/x';
  new File(fileName).createSync();
  Expect.throws(
      () => temp1.renameSync(fileName), (e) => e is FileSystemException);
  var renameDone = temp1.rename(fileName);
  renameDone
      .then((ignore) => Expect.fail('rename dir overwrite file'))
      .catchError((error) {
    Expect.isTrue(error is FileSystemException);
    temp1.deleteSync(recursive: true);
    done();
  });
}

void runTest(Function test) {
  // Create a temporary directory for the test.
  var temp = Directory.systemTemp.createTempSync('dart_directory_error');

  // Wait for the test to finish and delete the temporary directory.
  asyncStart();

  // Run the test.
  test(temp, () {
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

main() {
  runTest(testCreateInNonExistent);
  runTest(testCreateTempInNonExistent);
  runTest(testDeleteNonExistent);
  runTest(testDeleteRecursivelyNonExistent);
  runTest(testListNonExistent);
  runTest(testRenameNonExistent);
  runTest(testRenameFileAsDirectory);
  runTest(testRenameOverwriteFile);
}
