// 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 error handling in file I/O.

import "dart:convert";
import "dart:io";

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

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

bool checkCannotOpenFileException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  Expect.isTrue(e.toString().indexOf("Cannot open file") != -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 checkNonExistentFileSystemException(e, str) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  Expect.isTrue(e.toString().indexOf(str) != -1);
  // File not not found has error code 2 on all supported platforms.
  Expect.equals(2, e.osError.errorCode);
  return true;
}

bool checkOpenNonExistentFileSystemException(e) {
  return checkNonExistentFileSystemException(e, "Cannot open file");
}

bool checkDeleteNonExistentFileSystemException(e) {
  return checkNonExistentFileSystemException(e, "Cannot delete file");
}

bool checkLengthNonExistentFileSystemException(e) {
  return checkNonExistentFileSystemException(
      e, "Cannot retrieve length of file");
}

void testOpenBlankFilename() {
  asyncStart();
  var file = new File("");

  // Non-existing file should throw exception.
  Expect.throws(() => file.openSync(), (e) => checkCannotOpenFileException(e));

  var openFuture = file.open(mode: FileMode.read);
  openFuture.then((raf) => Expect.fail("Unreachable code")).catchError((error) {
    checkCannotOpenFileException(error);
    asyncEnd();
  });
}

void testOpenNonExistent() {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/nonExistentFile");

  // Non-existing file should throw exception.
  Expect.throws(
      () => file.openSync(), (e) => checkOpenNonExistentFileSystemException(e));

  var openFuture = file.open(mode: FileMode.read);
  openFuture.then((raf) => Expect.fail("Unreachable code")).catchError((error) {
    checkOpenNonExistentFileSystemException(error);
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

void testDeleteNonExistent() {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/nonExistentFile");

  // Non-existing file should throw exception.
  Expect.throws(() => file.deleteSync(),
      (e) => checkDeleteNonExistentFileSystemException(e));

  var delete = file.delete();
  delete.then((ignore) => Expect.fail("Unreachable code")).catchError((error) {
    checkDeleteNonExistentFileSystemException(error);
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

void testLengthNonExistent() {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/nonExistentFile");

  // Non-existing file should throw exception.
  Expect.throws(() => file.lengthSync(),
      (e) => checkLengthNonExistentFileSystemException(e));

  var lenFuture = file.length();
  lenFuture.then((len) => Expect.fail("Unreachable code")).catchError((error) {
    checkLengthNonExistentFileSystemException(error);
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

bool checkCreateInNonExistentFileSystemException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  Expect.isTrue(e.toString().indexOf("Cannot create file") != -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 testCreateInNonExistentDirectory() {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/nonExistentDirectory/newFile");

  // Create in non-existent directory should throw exception.
  Expect.throws(() => file.createSync(),
      (e) => checkCreateInNonExistentFileSystemException(e));

  var create = file.create();
  create.then((ignore) => Expect.fail("Unreachable code")).catchError((error) {
    checkCreateInNonExistentFileSystemException(error);
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

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

  return true;
}

void testResolveSymbolicLinksOnNonExistentDirectory() {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/nonExistentDirectory");

  // Full path non-existent directory should throw exception.
  Expect.throws(() => file.resolveSymbolicLinksSync(),
      (e) => checkResolveSymbolicLinksOnNonExistentFileSystemException(e));

  var resolvedFuture = file.resolveSymbolicLinks();
  resolvedFuture
      .then((path) => Expect.fail("Unreachable code $path"))
      .catchError((error) {
    checkResolveSymbolicLinksOnNonExistentFileSystemException(error);
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

void testReadAsBytesNonExistent() {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/nonExistentFile3");

  // Non-existing file should throw exception.
  Expect.throws(() => file.readAsBytesSync(),
      (e) => checkOpenNonExistentFileSystemException(e));

  var readAsBytesFuture = file.readAsBytes();
  readAsBytesFuture
      .then((data) => Expect.fail("Unreachable code"))
      .catchError((error) {
    checkOpenNonExistentFileSystemException(error);
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

void testReadAsTextNonExistent() {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/nonExistentFile4");

  // Non-existing file should throw exception.
  Expect.throws(() => file.readAsStringSync(),
      (e) => checkOpenNonExistentFileSystemException(e));

  var readAsStringFuture = file.readAsString(encoding: ascii);
  readAsStringFuture
      .then((data) => Expect.fail("Unreachable code"))
      .catchError((error) {
    checkOpenNonExistentFileSystemException(error);
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

testReadAsLinesNonExistent() {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/nonExistentFile5");

  // Non-existing file should throw exception.
  Expect.throws(() => file.readAsLinesSync(),
      (e) => checkOpenNonExistentFileSystemException(e));

  var readAsLinesFuture = file.readAsLines(encoding: ascii);
  readAsLinesFuture
      .then((data) => Expect.fail("Unreachable code"))
      .catchError((error) {
    checkOpenNonExistentFileSystemException(error);
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

bool checkWriteReadOnlyFileSystemException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.osError != null);
  Expect.isTrue(e.osError.errorCode != OSError.noErrorCode);
  return true;
}

// Create a test file in a temporary directory. Setup a port to signal
// when the temporary directory should be deleted. Pass the file and
// the port to the callback argument.
createTestFile(callback) {
  asyncStart();
  Directory temp = tempDir();
  var file = new File("${temp.path}/test_file");
  file.createSync();
  callback(file, () {
    temp.deleteSync(recursive: true);
    asyncEnd();
  });
}

testWriteByteToReadOnlyFile() {
  createTestFile((file, done) {
    var openedFile = file.openSync(mode: FileMode.read);

    // Writing to read only file should throw an exception.
    Expect.throws(() => openedFile.writeByteSync(0),
        (e) => checkWriteReadOnlyFileSystemException(e));

    var writeByteFuture = openedFile.writeByte(0);
    writeByteFuture.catchError((error) {
      checkWriteReadOnlyFileSystemException(error);
      openedFile.close().then((_) => done());
    });
  });
}

testWriteFromToReadOnlyFile() {
  createTestFile((file, done) {
    var openedFile = file.openSync(mode: FileMode.read);

    List<int> data = [0, 1, 2, 3];
    // Writing to read only file should throw an exception.
    Expect.throws(() => openedFile.writeFromSync(data, 0, data.length),
        (e) => checkWriteReadOnlyFileSystemException(e));

    var writeFromFuture = openedFile.writeFrom(data, 0, data.length);
    writeFromFuture.catchError((error) {
      checkWriteReadOnlyFileSystemException(error);
      openedFile.close().then((_) => done());
    });
  });
}

testTruncateReadOnlyFile() {
  createTestFile((file, done) {
    var openedFile = file.openSync(mode: FileMode.write);
    openedFile.writeByteSync(0);
    openedFile.closeSync();
    openedFile = file.openSync(mode: FileMode.read);

    // Truncating read only file should throw an exception.
    Expect.throws(() => openedFile.truncateSync(0),
        (e) => checkWriteReadOnlyFileSystemException(e));

    var truncateFuture = openedFile.truncate(0);
    truncateFuture
        .then((ignore) => Expect.fail("Unreachable code"))
        .catchError((error) {
      checkWriteReadOnlyFileSystemException(error);
      openedFile.close().then((_) => done());
    });
  });
}

bool checkFileClosedException(e) {
  Expect.isTrue(e is FileSystemException);
  Expect.isTrue(e.toString().indexOf("File closed") != -1);
  Expect.isTrue(e.osError == null);
  return true;
}

testOperateOnClosedFile() {
  createTestFile((file, done) {
    var openedFile = file.openSync(mode: FileMode.read);
    openedFile.closeSync();

    List<int> data = [0, 1, 2, 3];
    Expect.throws(
        () => openedFile.readByteSync(), (e) => checkFileClosedException(e));
    Expect.throws(
        () => openedFile.writeByteSync(0), (e) => checkFileClosedException(e));
    Expect.throws(() => openedFile.writeFromSync(data, 0, data.length),
        (e) => checkFileClosedException(e));
    Expect.throws(() => openedFile.readIntoSync(data, 0, data.length),
        (e) => checkFileClosedException(e));
    Expect.throws(() => openedFile.writeStringSync("Hello"),
        (e) => checkFileClosedException(e));
    Expect.throws(
        () => openedFile.positionSync(), (e) => checkFileClosedException(e));
    Expect.throws(() => openedFile.setPositionSync(0),
        (e) => checkFileClosedException(e));
    Expect.throws(
        () => openedFile.truncateSync(0), (e) => checkFileClosedException(e));
    Expect.throws(
        () => openedFile.lengthSync(), (e) => checkFileClosedException(e));
    Expect.throws(
        () => openedFile.flushSync(), (e) => checkFileClosedException(e));

    var errorCount = 0;

    _errorHandler(error) {
      checkFileClosedException(error);
      if (--errorCount == 0) {
        done();
      }
    }

    var readByteFuture = openedFile.readByte();
    readByteFuture
        .then((byte) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var writeByteFuture = openedFile.writeByte(0);
    writeByteFuture
        .then((ignore) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var readIntoFuture = openedFile.readInto(data, 0, data.length);
    readIntoFuture
        .then((bytesRead) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var writeFromFuture = openedFile.writeFrom(data, 0, data.length);
    writeFromFuture
        .then((ignore) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var writeStringFuture = openedFile.writeString("Hello");
    writeStringFuture
        .then((ignore) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var positionFuture = openedFile.position();
    positionFuture
        .then((position) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var setPositionFuture = openedFile.setPosition(0);
    setPositionFuture
        .then((ignore) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var truncateFuture = openedFile.truncate(0);
    truncateFuture
        .then((ignore) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var lenFuture = openedFile.length();
    lenFuture
        .then((length) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
    var flushFuture = openedFile.flush();
    flushFuture
        .then((ignore) => Expect.fail("Unreachable code"))
        .catchError(_errorHandler);
    errorCount++;
  });
}

testRepeatedlyCloseFile() {
  createTestFile((file, done) {
    var openedFile = file.openSync();
    openedFile.close().then((ignore) {
      var closeFuture = openedFile.close();
      closeFuture.then((ignore) => null).catchError((error) {
        Expect.isTrue(error is FileSystemException);
        done();
      });
    });
  });
}

testRepeatedlyCloseFileSync() {
  createTestFile((file, done) {
    var openedFile = file.openSync();
    openedFile.closeSync();
    Expect.throws(openedFile.closeSync, (e) => e is FileSystemException);
    done();
  });
}

testReadSyncClosedFile() {
  createTestFile((file, done) {
    var openedFile = file.openSync();
    openedFile.closeSync();
    Expect.throws(
        () => openedFile.readSync(1), (e) => e is FileSystemException);
    done();
  });
}

main() {
  testOpenBlankFilename();
  testOpenNonExistent();
  testDeleteNonExistent();
  testLengthNonExistent();
  testCreateInNonExistentDirectory();
  testResolveSymbolicLinksOnNonExistentDirectory();
  testReadAsBytesNonExistent();
  testReadAsTextNonExistent();
  testReadAsLinesNonExistent();
  testWriteByteToReadOnlyFile();
  testWriteFromToReadOnlyFile();
  testTruncateReadOnlyFile();
  testOperateOnClosedFile();
  testRepeatedlyCloseFile();
  testRepeatedlyCloseFileSync();
  testReadSyncClosedFile();
}
