blob: 68bebe8fc5775f948cfe43a5b079107a8b13dc2c [file] [log] [blame]
// 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);
}