// 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 = <String>[]
    ..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<bool> 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();
}
