// Copyright (c) 2016, 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. // OtherResources=file_blocking_lock_script.dart // This test works by spawning a new process running // file_blocking_lock_script.dart, trading the file lock back and forth, // writing bytes 1 ... 25 in order to the file. There are checks to ensure // that the bytes are written in order, that one process doesn't write all the // bytes and that a non-blocking lock fails such that a blocking lock must // be taken, which succeeds. import 'dart:async'; import 'dart:convert'; 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. runPeer(String path, int len, FileLock mode) { var script = Platform.script.resolve('file_blocking_lock_script.dart').toFilePath(); var arguments = [] ..addAll(Platform.executableArguments) ..add(script) ..add(path) ..add(len.toString()); return Process.start(Platform.executable, arguments).then((process) { process.stdout.transform(utf8.decoder).listen((data) { print(data); }); process.stderr.transform(utf8.decoder).listen((data) { print(data); }); return process; }); } const int peerTimeoutMilliseconds = 30000; Future waitForPeer(RandomAccessFile raf, int length) async { Stopwatch s = new Stopwatch(); s.start(); while (true) { await raf.unlock(0, length); if (s.elapsedMilliseconds > peerTimeoutMilliseconds) { s.stop(); return false; } try { await raf.lock(FileLock.exclusive, 0, length); } catch (_) { await raf.lock(FileLock.blockingExclusive, 0, length); break; } } s.stop(); return true; } testLockWholeFile() async { const int length = 25; Directory directory = await Directory.systemTemp.createTemp('dart_file_lock'); File file = new File(join(directory.path, "file")); await file.writeAsBytes(new List.filled(length, 0)); var raf = await file.open(mode: FileMode.append); await raf.lock(FileLock.blockingExclusive, 0, length); Process peer = await runPeer(file.path, length, FileLock.blockingExclusive); // If the peer doesn't come up within the timeout, then give up on the test // to avoid the test being flaky. if (!await waitForPeer(raf, length)) { await raf.close(); await directory.delete(recursive: true); return; } // Check that the peer wrote to the file. int p = 0; await raf.setPosition(0); while (p < length) { int at = await raf.readByte(); Expect.equals(1, at); p++; } await raf.unlock(0, length); // Check that the peer exited successfully. int v = await peer.exitCode; Expect.equals(0, v); await raf.close(); await directory.delete(recursive: true); } main() async { asyncStart(); await testLockWholeFile(); asyncEnd(); }