blob: d2cdefb5ca1a50c47976836d10bca88e83d90fe1 [file] [log] [blame]
// Copyright (c) 2015, 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 = 2.9
// OtherResources=file_lock_script.dart
import 'dart:async';
import 'dart:io';
import "package:async_helper/async_helper.dart";
import "package:expect/expect.dart";
import "package:path/path.dart";
// Check whether the file is locked or not.
check(String path, int start, int end, FileLock mode, {bool locked}) {
// Client process returns either 'LOCK FAILED' or 'LOCK SUCCEEDED'.
var expected = locked ? 'LOCK FAILED' : 'LOCK SUCCEEDED';
var arguments = <String>[]
..addAll(Platform.executableArguments)
..add(Platform.script.resolve('file_lock_script.dart').toFilePath())
..add(path)
..add(mode == FileLock.exclusive ? 'EXCLUSIVE' : 'SHARED')
..add('$start')
..add('$end');
var stacktrace = StackTrace.current;
return Process
.run(Platform.executable, arguments)
.then((ProcessResult result) {
if (result.exitCode != 0 || !result.stdout.contains(expected)) {
print("Client failed, exit code ${result.exitCode}");
print(" stdout:");
print(result.stdout);
print(" stderr:");
print(result.stderr);
print(" arguments:");
print(arguments);
print(" call stack:");
print(stacktrace);
Expect.fail('Client subprocess exit code: ${result.exitCode}');
}
});
}
checkLocked(String path,
[int start = 0, int end = -1, FileLock mode = FileLock.exclusive]) =>
check(path, start, end, mode, locked: true);
checkNotLocked(String path,
[int start = 0, int end = -1, FileLock mode = FileLock.exclusive]) =>
check(path, start, end, mode, locked: false);
void testLockWholeFile() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf = file.openSync(mode: FileMode.write);
raf.lockSync();
asyncStart();
checkLocked(file.path).then((_) {
return checkLocked(file.path, 0, 2).then((_) {
raf.unlockSync();
return checkNotLocked(file.path).then((_) {});
});
}).whenComplete(() {
raf.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockWholeFileAsync() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf = file.openSync(mode: FileMode.write);
asyncStart();
Future.forEach([
() => raf.lock(),
() => checkLocked(file.path, 0, 2),
() => checkLocked(file.path),
() => raf.unlock(),
() => checkNotLocked(file.path),
], (f) => f()).whenComplete(() {
raf.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockRange() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf1 = file.openSync(mode: FileMode.write);
var raf2 = file.openSync(mode: FileMode.write);
asyncStart();
var tests = [
() => raf1.lockSync(FileLock.exclusive, 2, 3),
() => raf2.lockSync(FileLock.exclusive, 5, 7),
() => checkNotLocked(file.path, 0, 2),
() => checkLocked(file.path, 0, 3),
() => checkNotLocked(file.path, 4, 5),
() => checkLocked(file.path, 4, 6),
() => checkLocked(file.path, 6),
() => checkNotLocked(file.path, 7),
() => raf1.unlockSync(2, 3),
() => checkNotLocked(file.path, 0, 5),
() => checkLocked(file.path, 4, 6),
() => checkLocked(file.path, 6),
() => checkNotLocked(file.path, 7),
];
// On Windows regions unlocked must match regions locked.
if (!Platform.isWindows) {
tests.addAll([
() => raf1.unlockSync(5, 6),
() => checkNotLocked(file.path, 0, 6),
() => checkLocked(file.path, 6),
() => checkNotLocked(file.path, 7),
() => raf2.unlockSync(6, 7),
() => checkNotLocked(file.path)
]);
} else {
tests
.addAll([() => raf2.unlockSync(5, 7), () => checkNotLocked(file.path)]);
}
Future.forEach(tests, (f) => f()).whenComplete(() {
raf1.closeSync();
raf2.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockRangeAsync() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf1 = file.openSync(mode: FileMode.write);
var raf2 = file.openSync(mode: FileMode.write);
asyncStart();
var tests = [
() => raf1.lock(FileLock.exclusive, 2, 3),
() => raf2.lock(FileLock.exclusive, 5, 7),
() => checkNotLocked(file.path, 0, 2),
() => checkLocked(file.path, 0, 3),
() => checkNotLocked(file.path, 4, 5),
() => checkLocked(file.path, 4, 6),
() => checkLocked(file.path, 6),
() => checkNotLocked(file.path, 7),
() => raf1.unlock(2, 3),
() => checkNotLocked(file.path, 0, 5),
() => checkLocked(file.path, 4, 6),
() => checkLocked(file.path, 6),
() => checkNotLocked(file.path, 7),
];
// On Windows regions unlocked must match regions locked.
if (!Platform.isWindows) {
tests.addAll([
() => raf1.unlock(5, 6),
() => checkNotLocked(file.path, 0, 6),
() => checkLocked(file.path, 6),
() => checkNotLocked(file.path, 7),
() => raf2.unlock(6, 7),
() => checkNotLocked(file.path)
]);
} else {
tests.addAll([() => raf2.unlock(5, 7), () => checkNotLocked(file.path)]);
}
Future.forEach(tests, (f) => f()).whenComplete(() {
raf1.closeSync();
raf2.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockEnd() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf = file.openSync(mode: FileMode.append);
asyncStart();
Future.forEach([
() => raf.lockSync(FileLock.exclusive, 2),
() => checkNotLocked(file.path, 0, 2),
() => checkLocked(file.path, 0, 3),
() => checkLocked(file.path, 9),
() => raf.writeFromSync(new List.filled(10, 0)),
() => checkLocked(file.path, 10),
() => checkLocked(file.path, 19),
() => raf.unlockSync(2),
() => checkNotLocked(file.path)
], (f) => f()).whenComplete(() {
raf.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockEndAsync() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf = file.openSync(mode: FileMode.append);
asyncStart();
Future.forEach([
() => raf.lock(FileLock.exclusive, 2),
() => checkNotLocked(file.path, 0, 2),
() => checkLocked(file.path, 0, 3),
() => checkLocked(file.path, 9),
() => raf.writeFromSync(new List.filled(10, 0)),
() => checkLocked(file.path, 10),
() => checkLocked(file.path, 19),
() => raf.unlock(2),
() => checkNotLocked(file.path)
], (f) => f()).whenComplete(() {
raf.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockShared() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf = file.openSync();
asyncStart();
Future.forEach([
() => raf.lock(FileLock.shared),
() => checkLocked(file.path),
() => checkLocked(file.path, 0, 2),
() => checkNotLocked(file.path, 0, 2, FileLock.shared)
], (f) => f()).then((_) {
raf.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockSharedAsync() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf = file.openSync();
asyncStart();
Future.forEach([
() => raf.lock(FileLock.shared),
() => checkLocked(file.path),
() => checkLocked(file.path, 0, 2),
() => checkNotLocked(file.path, 0, 2, FileLock.shared)
], (f) => f()).whenComplete(() {
raf.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockAfterLength() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf = file.openSync(mode: FileMode.append);
asyncStart();
Future.forEach([
() => raf.lockSync(FileLock.exclusive, 2, 15),
() => checkNotLocked(file.path, 0, 2),
() => checkLocked(file.path, 0, 3),
() => checkLocked(file.path, 9),
() => checkLocked(file.path, 14),
() => raf.writeFromSync(new List.filled(10, 0)),
() => checkLocked(file.path, 10),
() => checkNotLocked(file.path, 15),
() => raf.unlockSync(2, 15),
() => checkNotLocked(file.path)
], (f) => f()).whenComplete(() {
raf.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void testLockAfterLengthAsync() {
Directory directory = Directory.systemTemp.createTempSync('dart_file_lock');
File file = new File(join(directory.path, "file"));
file.writeAsBytesSync(new List.filled(10, 0));
var raf = file.openSync(mode: FileMode.append);
asyncStart();
Future.forEach([
() => raf.lock(FileLock.exclusive, 2, 15),
() => checkNotLocked(file.path, 0, 2),
() => checkLocked(file.path, 0, 3),
() => checkLocked(file.path, 9),
() => checkLocked(file.path, 14),
() => raf.writeFromSync(new List.filled(10, 0)),
() => checkLocked(file.path, 10),
() => checkNotLocked(file.path, 15),
() => raf.unlock(2, 15),
() => checkNotLocked(file.path)
], (f) => f()).whenComplete(() {
raf.closeSync();
directory.deleteSync(recursive: true);
asyncEnd();
});
}
void main() {
testLockWholeFile();
testLockWholeFileAsync();
testLockRange();
testLockRangeAsync();
testLockEnd();
testLockEndAsync();
testLockShared();
testLockSharedAsync();
testLockAfterLength();
testLockAfterLengthAsync();
}