a323c55162
Change-Id: I4d492a63a41880ef8cd69321372a4853825b9efd Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/426321 Reviewed-by: Liam Appelbe <liama@google.com> Auto-Submit: Bob Nystrom <rnystrom@google.com> Commit-Queue: Liam Appelbe <liama@google.com>
282 lines
8.2 KiB
Dart
282 lines
8.2 KiB
Dart
// 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
|
|
|
|
import "dart:convert";
|
|
import "dart:io";
|
|
|
|
import "package:expect/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);
|
|
}
|