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

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

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

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

bool checkCreateInNonExistentFileSystemException(e) {
  Expect.isTrue(e is PathNotFoundException);
  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));

  Future<Directory?>.value(inNonExistent.create()).catchError((error) {
    checkCreateInNonExistentFileSystemException(error);
    done();
  });
}

bool checkCreateTempInNonExistentFileSystemException(e) {
  Expect.isTrue(e is PathNotFoundException);
  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));

  Future<Directory?>.value(nonExistent.createTemp('tempdir'))
      .catchError((error) {
    checkCreateTempInNonExistentFileSystemException(error);
    done();
  });
}

bool checkDeleteNonExistentFileSystemException(e) {
  Expect.isTrue(e is PathNotFoundException);
  Expect.isTrue(e.osError != null);
  // File 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));

  Future<FileSystemEntity?>.value(nonExistent.delete()).catchError((error) {
    checkDeleteNonExistentFileSystemException(error);
    done();
  });
}

bool checkDeleteRecursivelyNonExistentFileSystemException(e) {
  Expect.isTrue(e is PathNotFoundException);
  Expect.isTrue(e.osError != null);
  Expect.isTrue(e.toString().indexOf("Deletion failed") != -1);
  // File 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));

  Future<FileSystemEntity?>.value(nonExistent.delete(recursive: true))
      .catchError((error) {
    checkDeleteRecursivelyNonExistentFileSystemException(error);
    done();
  });
}

bool checkListNonExistentFileSystemException(e) {
  Expect.isTrue(e is PathNotFoundException);
  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 PathNotFoundException);
  var renameDone = nonExistent.rename(newPath);
  renameDone
      .then((ignore) => Expect.fail('rename non existent'))
      .catchError((error) {
    Expect.isTrue(error is PathNotFoundException);
    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);
}
