// 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.

import 'dart:io';

import 'package:bazel_worker/bazel_worker.dart';
import 'package:bazel_worker/testing.dart';
import 'package:test/test.dart';

void main() {
  group('AsyncMessageGrouper', () {
    runTests(TestStdinAsync.new, AsyncMessageGrouper.new);
  });

  group('SyncMessageGrouper', () {
    runTests(TestStdinSync.new, SyncMessageGrouper.new);
  });
}

void runTests(TestStdin Function() stdinFactory,
    MessageGrouper Function(Stdin) messageGrouperFactory) {
  late MessageGrouper messageGrouper;

  late TestStdin stdinStream;

  setUp(() {
    stdinStream = stdinFactory();
    messageGrouper = messageGrouperFactory(stdinStream);
  });

  /// Check that if the message grouper produces the [expectedOutput] in
  /// response to the corresponding [input].
  Future check(List<int> input, List<List<int>> expectedOutput) async {
    stdinStream.addInputBytes(input);
    for (var chunk in expectedOutput) {
      expect(await messageGrouper.next, equals(chunk));
    }
  }

  /// Make a simple message having the given [length]
  List<int> makeMessage(int length) {
    var result = <int>[];
    for (var i = 0; i < length; i++) {
      result.add(i & 0xff);
    }
    return result;
  }

  test('Empty message', () async {
    await check([0], [[]]);
  });

  test('Short message', () async {
    await check([
      5,
      10,
      20,
      30,
      40,
      50
    ], [
      [10, 20, 30, 40, 50]
    ]);
  });

  test('Message with 2-byte length', () async {
    var len = 0x155;
    var msg = makeMessage(len);
    var encodedLen = [0xd5, 0x02];
    await check([...encodedLen, ...msg], [msg]);
  });

  test('Message with 3-byte length', () async {
    var len = 0x4103;
    var msg = makeMessage(len);
    var encodedLen = [0x83, 0x82, 0x01];
    await check([...encodedLen, ...msg], [msg]);
  });

  test('Multiple messages', () async {
    await check([
      2,
      10,
      20,
      2,
      30,
      40
    ], [
      [10, 20],
      [30, 40]
    ]);
  });

  test('Empty message at start', () async {
    await check([
      0,
      2,
      10,
      20
    ], [
      [],
      [10, 20]
    ]);
  });

  test('Empty message at end', () async {
    await check([
      2,
      10,
      20,
      0
    ], [
      [10, 20],
      []
    ]);
  });

  test('Empty message in the middle', () async {
    await check([
      2,
      10,
      20,
      0,
      2,
      30,
      40
    ], [
      [10, 20],
      [],
      [30, 40]
    ]);
  });

  test('Handles the case when stdin gives an error instead of EOF', () async {
    if (stdinStream is TestStdinSync) {
      // Reading will now cause an error as pendingBytes is empty.
      (stdinStream as TestStdinSync).pendingBytes.clear();
      expect(messageGrouper.next, isNull);
    } else if (stdinStream is TestStdinAsync) {
      (stdinStream as TestStdinAsync).controller.addError('Error!');
      expect(await messageGrouper.next, isNull);
    }
  });
}
