// 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.
// Testing file input stream, VM-only, standalone test.
//
// OtherResources=readuntil_test.dat
// OtherResources=readline_test1.dat
// OtherResources=readline_test2.dat

// @dart = 2.9

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

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

String getFilename(String path) {
  return Platform.script.resolve(path).toFilePath();
}

void testStringLineSplitter() {
  String fileName = getFilename("readuntil_test.dat");
  // File contains "Hello Dart\nwassup!\n"
  File file = new File(fileName);
  int linesRead = 0;
  var lineStream = file
      .openRead()
      .cast<List<int>>()
      .transform(utf8.decoder)
      .transform(new LineSplitter());
  lineStream.listen((line) {
    linesRead++;
    if (linesRead == 1) {
      Expect.equals("Hello Dart", line);
    } else if (linesRead == 2) {
      Expect.equals("wassup!", line);
    } else {
      Expect.fail("More or less than 2 lines read ($linesRead lines read).");
    }
  });
}

void testOpenStreamAsync() {
  asyncStart();
  String fileName = getFilename("readuntil_test.dat");
  // File contains "Hello Dart\nwassup!\n"
  var expected = "Hello Dart\nwassup!\n".codeUnits;
  var byteCount = 0;
  (new File(fileName)).openRead().listen((d) => byteCount += d.length,
      onDone: () {
    Expect.equals(expected.length, byteCount);
    asyncEnd();
  });
}

// Create a file that is big enough that a file stream will
// read it in multiple chunks.
int writeLongFileSync(File file) {
  file.createSync();
  StringBuffer buffer = new StringBuffer();
  for (var i = 0; i < 50000; i++) {
    buffer.write("Hello, world");
  }
  file.writeAsStringSync(buffer.toString());
  var length = file.lengthSync();
  Expect.equals(buffer.length, length);
  return length;
}

void testInputStreamTruncate() {
  asyncStart();
  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
  var file = new File('${temp.path}/input_stream_truncate.txt');
  var originalLength = writeLongFileSync(file);
  // Start streaming the file. Pause after first chunk. Truncate
  // underlying file and check that the streaming stops with or
  // without getting all data.
  var streamedBytes = 0;
  var subscription;
  subscription = file.openRead().listen((d) {
    if (streamedBytes == 0) {
      subscription.pause();
      // Truncate the file by opening it for writing.
      file.open(mode: FileMode.write).then((opened) {
        opened.close().then((_) {
          Expect.equals(0, file.lengthSync());
          subscription.resume();
        });
      });
    }
    streamedBytes += d.length;
  }, onDone: () {
    Expect.isTrue(streamedBytes > 0 && streamedBytes <= originalLength);
    temp.delete(recursive: true).then((_) => asyncEnd());
  }, onError: (e) {
    Expect.fail("Unexpected error");
  });
}

void testInputStreamDelete() {
  asyncStart();
  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
  var file = new File('${temp.path}/input_stream_delete.txt');
  var originalLength = writeLongFileSync(file);
  // Start streaming the file. Pause after first chunk. Truncate
  // underlying file and check that the streaming stops with or
  // without getting all data.
  var streamedBytes = 0;
  var subscription;
  subscription = file.openRead().listen((d) {
    if (streamedBytes == 0) {
      subscription.pause();
      // Delete the underlying file by opening it for writing.
      file.delete().then((deleted) {
        Expect.isFalse(deleted.existsSync());
        subscription.resume();
      }).catchError((e) {
        // On Windows, you cannot delete a file that is open
        // somewhere else. The stream has this file open
        // and therefore we get an error on deletion on Windows.
        Expect.equals('windows', Platform.operatingSystem);
        subscription.resume();
      });
    }
    streamedBytes += d.length;
  }, onDone: () {
    Expect.equals(originalLength, streamedBytes);
    temp.delete(recursive: true).then((_) => asyncEnd());
  }, onError: (e) {
    Expect.fail("Unexpected error");
  });
}

void testInputStreamAppend() {
  asyncStart();
  var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
  var file = new File('${temp.path}/input_stream_append.txt');
  var originalLength = writeLongFileSync(file);
  // Start streaming the file. Pause after first chunk. Append to
  // underlying file and check that the stream gets all the data.
  var streamedBytes = 0;
  var subscription;
  subscription = file.openRead().listen((d) {
    if (streamedBytes == 0) {
      subscription.pause();
      // Double the length of the underlying file.
      file.readAsBytes().then((bytes) {
        file.writeAsBytes(bytes, mode: FileMode.append).then((_) {
          Expect.equals(2 * originalLength, file.lengthSync());
          subscription.resume();
        });
      });
    }
    streamedBytes += d.length;
  }, onDone: () {
    Expect.equals(2 * originalLength, streamedBytes);
    temp.delete(recursive: true).then((_) => asyncEnd());
  }, onError: (e) {
    Expect.fail("Unexpected error");
  });
}

void testInputStreamOffset() {
  void test(int start, int end, int expectedBytes) {
    asyncStart();
    var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
    var file = new File('${temp.path}/input_stream_offset.txt');
    var originalLength = writeLongFileSync(file);
    var streamedBytes = 0;
    if (expectedBytes < 0) expectedBytes = originalLength + expectedBytes;
    file.openRead(start, end).listen((d) {
      streamedBytes += d.length;
    }, onDone: () {
      Expect.equals(expectedBytes, streamedBytes);
      temp.delete(recursive: true).then((_) => asyncEnd());
    }, onError: (e) {
      Expect.fail("Unexpected error");
    });
  }

  test(10, 20, 10);
  test(10, 11, 1);
  test(10, 10, 0);
  test(100000000, null, 0);
  test(null, 0, 0);
  test(null, 1, 1);
  test(1, null, -1);
  test(20, null, -20);
}

void testInputStreamBadOffset() {
  void test(int start, int end) {
    asyncStart();
    var temp = Directory.systemTemp.createTempSync('file_input_stream_test');
    var file = new File('${temp.path}/input_stream_bad_offset.txt');
    var originalLength = writeLongFileSync(file);
    var streamedBytes = 0;
    bool error = false;
    file.openRead(start, end).listen((d) {
      streamedBytes += d.length;
    }, onDone: () {
      Expect.isTrue(error);
      temp.deleteSync(recursive: true);
      asyncEnd();
    }, onError: (e) {
      error = true;
    });
  }

  test(-1, null);
  test(100, 99);
  test(null, -1);
}

void testStringLineSplitterEnding(String name, int length) {
  String fileName = getFilename(name);
  // File contains 10 lines.
  File file = new File(fileName);
  Expect.equals(length, file.lengthSync());
  var lineStream = file
      .openRead()
      .cast<List<int>>()
      .transform(utf8.decoder)
      .transform(new LineSplitter());
  int lineCount = 0;
  lineStream.listen((line) {
    lineCount++;
    Expect.isTrue(lineCount <= 10);
    if (line[0] != "#") {
      Expect.equals("Line $lineCount", line);
    }
  }, onDone: () {
    Expect.equals(10, lineCount);
  });
}

main() {
  testStringLineSplitter();
  testOpenStreamAsync();
  testInputStreamTruncate();
  testInputStreamDelete();
  testInputStreamAppend();
  testInputStreamOffset();
  testInputStreamBadOffset();
  // Check the length of these files as both are text files where one
  // is without a terminating line separator which can easily be added
  // back if accidentally opened in a text editor.
  testStringLineSplitterEnding("readline_test1.dat", 111);
  testStringLineSplitterEnding("readline_test2.dat", 114);
}
