// Copyright (c) 2023, 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 test program for testing dart:ffi async callbacks.
//
// VMOptions=
// VMOptions=--use-slow-path
// VMOptions=--use-slow-path --stacktrace-every=100
// VMOptions=--dwarf_stack_traces --no-retain_function_objects --no-retain_code_objects
// VMOptions=--test_il_serialization
// VMOptions=--profiler
// SharedObjects=ffi_test_functions

import 'dart:async';
import 'dart:ffi';
import 'dart:isolate';

import 'dart:io';

import "package:expect/expect.dart";

import 'dylib_utils.dart';

main(args, message) async {
  if (message != null) {
    // We've been spawned by Isolate.spawnUri. Run IsolateB.
    await IsolateB.entryPoint(message);
    return;
  }

  // Simple tests.
  await testNativeCallableHelloWorld();
  testNativeCallableDoubleCloseError();
  await testNativeCallableUseAfterFree();
  await testNativeCallableNestedCloseCall();
  await testNativeCallableThrowInsideCallback();
  await testNativeCallableDontKeepAlive();
  testNativeCallableKeepAliveGetter();
  await testNativeCallableClosure();

  // Message passing tests.
  globalVar = 1000;
  for (final sameGroup in [true, false]) {
    final isolateA = IsolateA(sameGroup);
    await isolateA.messageLoop();
    isolateA.close();
  }
  print("All tests completed :)");
}

final List<TestCase> messagePassingTestCases = [
  SanityCheck(),
  CallFromIsoAToIsoB(),
  CallFromIsoBToIsoA(),
  CallFromIsoAToIsoBViaNewThreadBlocking(),
  CallFromIsoBToIsoAViaNewThreadBlocking(),
  CallFromIsoAToIsoBViaNewThreadNonBlocking(),
  CallFromIsoBToIsoAViaNewThreadNonBlocking(),
  CallFromIsoAToBToA(),
  CallFromIsoBToAToB(),
  ManyCallsBetweenIsolates(),
  ManyCallsBetweenIsolatesViaNewThreadBlocking(),
  ManyCallsBetweenIsolatesViaNewThreadNonBlocking(),
];

var simpleFunctionResult = Completer<int>();
void simpleFunction(int a, int b) {
  simpleFunctionResult.complete(a + b);
}

Future<void> testNativeCallableHelloWorld() async {
  final lib = NativeLibrary();
  final callback = NativeCallable<CallbackNativeType>.listener(simpleFunction);

  simpleFunctionResult = Completer<int>();
  lib.callFunctionOnSameThread(1000, callback.nativeFunction);

  Expect.equals(1123, await simpleFunctionResult.future);
  callback.close();
}

testNativeCallableDoubleCloseError() {
  final callback = NativeCallable<CallbackNativeType>.listener(simpleFunction);
  Expect.notEquals(nullptr, callback.nativeFunction);
  callback.close();

  Expect.throwsStateError(() {
    final _ = callback.nativeFunction;
  });

  // Expect that these do not throw.
  callback.close();
  callback.keepIsolateAlive = true;
  Expect.isFalse(callback.keepIsolateAlive);
}

Future<void> testNativeCallableUseAfterFree() async {
  final lib = NativeLibrary();

  final callback = NativeCallable<CallbackNativeType>.listener(simpleFunction);
  final nativeFunction = callback.nativeFunction;
  callback.close();

  simpleFunctionResult = Completer<int>();
  lib.callFunctionOnSameThread(123, nativeFunction);

  await Future.delayed(Duration(milliseconds: 100));

  // The callback wasn't invoked, but we didn't crash either.
  Expect.equals(false, simpleFunctionResult.isCompleted);
}

NativeCallable? simpleFunctionAndCloseSelf_callable;
void simpleFunctionAndCloseSelf(int a, int b) {
  simpleFunctionAndCloseSelf_callable!.close();
  simpleFunctionResult.complete(a + b);
}

Future<void> testNativeCallableNestedCloseCall() async {
  final lib = NativeLibrary();
  simpleFunctionAndCloseSelf_callable =
      NativeCallable<CallbackNativeType>.listener(simpleFunctionAndCloseSelf);

  simpleFunctionResult = Completer<int>();
  lib.callFunctionOnSameThread(
      1000, simpleFunctionAndCloseSelf_callable!.nativeFunction);

  Expect.equals(1123, await simpleFunctionResult.future);

  // The callback is already closed.
  Expect.throwsStateError(() {
    final _ = simpleFunctionAndCloseSelf_callable!.nativeFunction;
  });
}

void simpleFunctionThrows(int a, int b) {
  throw a + b;
}

Future<void> testNativeCallableThrowInsideCallback() async {
  final lib = NativeLibrary();
  var caughtError;
  late final callback;

  runZonedGuarded(() {
    callback =
        NativeCallable<CallbackNativeType>.listener(simpleFunctionThrows);
  }, (Object error, StackTrace stack) {
    caughtError = error;
  });

  lib.callFunctionOnSameThread(1000, callback.nativeFunction);
  await Future.delayed(Duration(milliseconds: 100));

  Expect.equals(1123, caughtError);

  callback.close();
}

Future<void> testNativeCallableDontKeepAlive() async {
  final exitPort = ReceivePort();
  await Isolate.spawn((_) async {
    final lib = NativeLibrary();
    final callback =
        NativeCallable<CallbackNativeType>.listener(simpleFunction);

    simpleFunctionResult = Completer<int>();
    lib.callFunctionOnSameThread(1000, callback.nativeFunction);

    Expect.equals(1123, await simpleFunctionResult.future);
    callback.keepIsolateAlive = false;
  }, null, onExit: exitPort.sendPort);
  await exitPort.first;
  exitPort.close();
}

testNativeCallableKeepAliveGetter() {
  final callback = NativeCallable<CallbackNativeType>.listener(simpleFunction);
  Expect.isTrue(callback.keepIsolateAlive);
  callback.keepIsolateAlive = false;
  Expect.isFalse(callback.keepIsolateAlive);
  callback.keepIsolateAlive = true;
  Expect.isTrue(callback.keepIsolateAlive);
  callback.close();
}

Future<void> testNativeCallableClosure() async {
  final lib = NativeLibrary();
  int c = 70000;

  final callback = NativeCallable<CallbackNativeType>.listener((int a, int b) {
    simpleFunctionResult.complete(a + b + c);
  });

  simpleFunctionResult = Completer<int>();
  lib.callFunctionOnSameThread(1000, callback.nativeFunction);
  Expect.equals(71123, await simpleFunctionResult.future);

  c = 80000;
  simpleFunctionResult = Completer<int>();
  lib.callFunctionOnSameThread(4000, callback.nativeFunction);
  Expect.equals(84123, await simpleFunctionResult.future);

  callback.close();
}

final ffiTestFunctions = dlopenPlatformSpecific("ffi_test_functions");

// Global variable that is 1000 on isolate A, and 2000 on isolate B.
late final int globalVar;

class SanityCheck extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  Future<void> runOnIsoA(IsolateA iso) async {
    Expect.equals(1000, globalVar);
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnSameThread(
            responseId, Pointer.fromAddress(iso.fnPtrsA.addGlobalVarPtr)));
    print("SanityCheck.runOnIsoA message sent. Awaiting result...");
    Expect.equals(1123, await result);
  }

  @override
  Future<void> runOnIsoB(IsolateB iso) async {
    Expect.equals(2000, globalVar);
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnSameThread(
            responseId, Pointer.fromAddress(iso.fnPtrsB.addGlobalVarPtr)));
    print("SanityCheck.runOnIsoB message sent. Awaiting result...");
    Expect.equals(2123, await result);
  }
}

class CallFromIsoAToIsoB extends TestCase {
  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  Future<void> runOnIsoA(IsolateA iso) async {
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnSameThread(
            responseId, Pointer.fromAddress(iso.fnPtrsB.addGlobalVarPtr)));
    print("CallFromIsoAToIsoB.runOnIsoA message sent. Awaiting result...");
    Expect.equals(2123, await result);
  }
}

class CallFromIsoBToIsoA extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  Future<void> runOnIsoB(IsolateB iso) async {
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnSameThread(
            responseId, Pointer.fromAddress(iso.fnPtrsA.addGlobalVarPtr)));
    print("CallFromIsoBToIsoA.runOnIsoB message sent. Awaiting result...");
    Expect.equals(1123, await result);
  }
}

class CallFromIsoAToIsoBViaNewThreadBlocking extends TestCase {
  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  Future<void> runOnIsoA(IsolateA iso) async {
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnNewThreadBlocking(
            responseId, Pointer.fromAddress(iso.fnPtrsB.addGlobalVarPtr)));
    print(
        "CallFromIsoAToIsoBViaNewThreadBlocking.runOnIsoA message sent. Awaiting result...");
    Expect.equals(2123, await result);
  }
}

class CallFromIsoBToIsoAViaNewThreadBlocking extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  Future<void> runOnIsoB(IsolateB iso) async {
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnNewThreadBlocking(
            responseId, Pointer.fromAddress(iso.fnPtrsA.addGlobalVarPtr)));
    print(
        "CallFromIsoBToIsoAViaNewThreadBlocking.runOnIsoB message sent. Awaiting result...");
    Expect.equals(1123, await result);
  }
}

class CallFromIsoAToIsoBViaNewThreadNonBlocking extends TestCase {
  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  Future<void> runOnIsoA(IsolateA iso) async {
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnNewThreadNonBlocking(
            responseId, Pointer.fromAddress(iso.fnPtrsB.addGlobalVarPtr)));
    print(
        "CallFromIsoAToIsoBViaNewThreadNonBlocking.runOnIsoA message sent. Awaiting result...");
    Expect.equals(2123, await result);
  }
}

class CallFromIsoBToIsoAViaNewThreadNonBlocking extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  Future<void> runOnIsoB(IsolateB iso) async {
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnNewThreadNonBlocking(
            responseId, Pointer.fromAddress(iso.fnPtrsA.addGlobalVarPtr)));
    print(
        "CallFromIsoBToIsoAViaNewThreadNonBlocking.runOnIsoB message sent. Awaiting result...");
    Expect.equals(1123, await result);
  }
}

class CallFromIsoAToBToA extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  Future<void> runOnIsoA(IsolateA iso) async {
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnSameThread(
            responseId,
            Pointer.fromAddress(
                iso.fnPtrsB.callFromIsoBToAAndMultByGlobalVarPtr)));
    print("CallFromIsoAToBToA.runOnIsoA message sent. Awaiting result...");
    Expect.equals(2000 * 1123, await result);
  }
}

class CallFromIsoBToAToB extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  Future<void> runOnIsoB(IsolateB iso) async {
    final result = iso.atm.call((responseId) => iso.natLib
        .callFunctionOnSameThread(
            responseId,
            Pointer.fromAddress(
                iso.fnPtrsA.callFromIsoAToBAndMultByGlobalVarPtr)));
    print("CallFromIsoBToAToB.runOnIsoB message sent. Awaiting result...");
    Expect.equals(1000 * 2123, await result);
  }
}

class ManyCallsBetweenIsolates extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  Future<void> runOnIsoA(IsolateA iso) async {
    print("ManyCallsBetweenIsolates.runOnIsoA sending messages.");
    await Future.wait(List.filled(100, null).map((_) async {
      final result = iso.atm.call((responseId) => iso.natLib
          .callFunctionOnSameThread(
              responseId, Pointer.fromAddress(iso.fnPtrsB.addGlobalVarPtr)));
      Expect.equals(2123, await result);
    }));
  }

  @override
  Future<void> runOnIsoB(IsolateB iso) async {
    print("ManyCallsBetweenIsolates.runOnIsoB sending messages.");
    await Future.wait(List.filled(100, null).map((_) async {
      final result = iso.atm.call((responseId) => iso.natLib
          .callFunctionOnSameThread(
              responseId, Pointer.fromAddress(iso.fnPtrsA.addGlobalVarPtr)));
      Expect.equals(1123, await result);
    }));
  }
}

class ManyCallsBetweenIsolatesViaNewThreadBlocking extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  Future<void> runOnIsoA(IsolateA iso) async {
    print(
        "ManyCallsBetweenIsolatesViaNewThreadBlocking.runOnIsoA sending messages.");
    await Future.wait(List.filled(100, null).map((_) async {
      final result = iso.atm.call((responseId) => iso.natLib
          .callFunctionOnNewThreadBlocking(
              responseId, Pointer.fromAddress(iso.fnPtrsB.addGlobalVarPtr)));
      Expect.equals(2123, await result);
    }));
  }

  @override
  Future<void> runOnIsoB(IsolateB iso) async {
    print(
        "ManyCallsBetweenIsolatesViaNewThreadBlocking.runOnIsoB sending messages.");
    await Future.wait(List.filled(100, null).map((_) async {
      final result = iso.atm.call((responseId) => iso.natLib
          .callFunctionOnNewThreadBlocking(
              responseId, Pointer.fromAddress(iso.fnPtrsA.addGlobalVarPtr)));
      Expect.equals(1123, await result);
    }));
  }
}

class ManyCallsBetweenIsolatesViaNewThreadNonBlocking extends TestCase {
  @override
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => atm.toIsoB;

  @override
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => atm.toIsoA;

  @override
  Future<void> runOnIsoA(IsolateA iso) async {
    print(
        "ManyCallsBetweenIsolatesViaNewThreadNonBlocking.runOnIsoA sending messages.");
    await Future.wait(List.filled(100, null).map((_) async {
      final result = iso.atm.call((responseId) => iso.natLib
          .callFunctionOnNewThreadNonBlocking(
              responseId, Pointer.fromAddress(iso.fnPtrsB.addGlobalVarPtr)));
      Expect.equals(2123, await result);
    }));
  }

  @override
  Future<void> runOnIsoB(IsolateB iso) async {
    print(
        "ManyCallsBetweenIsolatesViaNewThreadNonBlocking.runOnIsoB sending messages.");
    await Future.wait(List.filled(100, null).map((_) async {
      final result = iso.atm.call((responseId) => iso.natLib
          .callFunctionOnNewThreadNonBlocking(
              responseId, Pointer.fromAddress(iso.fnPtrsA.addGlobalVarPtr)));
      Expect.equals(1123, await result);
    }));
  }
}

class AsyncTestManager {
  int _lastResponseId = 0;
  final _pending = <int, Completer<Object>>{};
  final _recvPort = ReceivePort("AsyncTestManager");

  late final SendPort toIsoA;
  late final SendPort toIsoB;
  SendPort get toThis => _recvPort.sendPort;

  AsyncTestManager(this._lastResponseId) {
    _recvPort.listen((msg) {
      final response = msg as List;
      final id = response[0];
      final value = response[1];
      _pending[id]!.complete(value);
      _pending.remove(id);
    });
  }

  Future<Object> call(void Function(int) asyncFunc) {
    final responseId = ++_lastResponseId;
    final completer = Completer<Object>();
    _pending[responseId] = completer;
    asyncFunc(responseId);
    return completer.future;
  }

  void close() {
    _recvPort.close();
  }
}

SendPort? _callbackResultPort;

void addGlobalVar(int responseId, int x) {
  final result = x + globalVar;
  _callbackResultPort!.send([responseId, result]);
}

void callFromIsoBToAAndMultByGlobalVar(int responseIdToA, int x) {
  final iso = IsolateB.instance!;
  iso.atm
      .call((responseIdToB) => iso.natLib.callFunctionOnSameThread(
          responseIdToB, Pointer.fromAddress(iso.fnPtrsA.addGlobalVarPtr)))
      .then((response) {
    final result = (response as int) * globalVar;
    _callbackResultPort!.send([responseIdToA, result]);
  });
  print("callFromIsoBToAAndMultByGlobalVar message sent. Awaiting result...");
}

void callFromIsoAToBAndMultByGlobalVar(int responseIdToB, int x) {
  final iso = IsolateA.instance!;
  iso.atm
      .call((responseIdToA) => iso.natLib.callFunctionOnSameThread(
          responseIdToA, Pointer.fromAddress(iso.fnPtrsB.addGlobalVarPtr)))
      .then((response) {
    final result = (response as int) * globalVar;
    _callbackResultPort!.send([responseIdToB, result]);
  });
  print("callFromIsoAToBAndMultByGlobalVar message sent. Awaiting result...");
}

typedef CallbackNativeType = Void Function(Int64, Int32);

class Callbacks {
  final NativeCallable addGlobalVarFn;
  final NativeCallable callFromIsoBToAAndMultByGlobalVarFn;
  final NativeCallable callFromIsoAToBAndMultByGlobalVarFn;

  Callbacks()
      : addGlobalVarFn =
            NativeCallable<CallbackNativeType>.listener(addGlobalVar),
        callFromIsoBToAAndMultByGlobalVarFn =
            NativeCallable<CallbackNativeType>.listener(
                callFromIsoBToAAndMultByGlobalVar),
        callFromIsoAToBAndMultByGlobalVarFn =
            NativeCallable<CallbackNativeType>.listener(
                callFromIsoAToBAndMultByGlobalVar);

  void close() {
    addGlobalVarFn.close();
    callFromIsoBToAAndMultByGlobalVarFn.close();
    callFromIsoAToBAndMultByGlobalVarFn.close();
  }
}

class FnPtrs {
  // Storing function pointers as ints so they can be sent to other isolates.
  final int addGlobalVarPtr;
  final int callFromIsoBToAAndMultByGlobalVarPtr;
  final int callFromIsoAToBAndMultByGlobalVarPtr;

  FnPtrs._(this.addGlobalVarPtr, this.callFromIsoBToAAndMultByGlobalVarPtr,
      this.callFromIsoAToBAndMultByGlobalVarPtr);

  static FnPtrs fromCallbacks(Callbacks callbacks) => FnPtrs._(
        callbacks.addGlobalVarFn.nativeFunction.address,
        callbacks.callFromIsoBToAAndMultByGlobalVarFn.nativeFunction.address,
        callbacks.callFromIsoAToBAndMultByGlobalVarFn.nativeFunction.address,
      );

  static FnPtrs fromList(List<int> ptrs) => FnPtrs._(ptrs[0], ptrs[1], ptrs[2]);
  List<int> toList() => [
        addGlobalVarPtr,
        callFromIsoBToAAndMultByGlobalVarPtr,
        callFromIsoAToBAndMultByGlobalVarPtr,
      ];
}

typedef FnRunnerNativeType = Void Function(Int64, Pointer);
typedef FnRunnerType = void Function(int, Pointer);

class NativeLibrary {
  late final FnRunnerType callFunctionOnSameThread;
  late final FnRunnerType callFunctionOnNewThreadBlocking;
  late final FnRunnerType callFunctionOnNewThreadNonBlocking;

  NativeLibrary() {
    callFunctionOnSameThread =
        ffiTestFunctions.lookupFunction<FnRunnerNativeType, FnRunnerType>(
            "CallFunctionOnSameThread");
    callFunctionOnNewThreadBlocking =
        ffiTestFunctions.lookupFunction<FnRunnerNativeType, FnRunnerType>(
            "CallFunctionOnNewThreadBlocking");
    callFunctionOnNewThreadNonBlocking =
        ffiTestFunctions.lookupFunction<FnRunnerNativeType, FnRunnerType>(
            "CallFunctionOnNewThreadNonBlocking");
  }
}

class TestCase {
  SendPort? sendIsoAResultsTo(AsyncTestManager atm) => null;
  SendPort? sendIsoBResultsTo(AsyncTestManager atm) => null;
  Future<void> runOnIsoA(IsolateA isoA) async {}
  Future<void> runOnIsoB(IsolateB isoB) async {}
}

class TestCaseSendPort {
  final SendPort sendPort;
  TestCaseSendPort(this.sendPort);
}

// IsolateA is the main isolate of the test. It spawns IsolateB.
class IsolateA {
  static IsolateA? instance;
  late final SendPort sendPort;
  final recvPort = ReceivePort("Isolate A ReceivePort");
  final atm = AsyncTestManager(1000000);
  final natLib = NativeLibrary();
  final callbacksA = Callbacks();
  late final FnPtrs fnPtrsA;
  late final FnPtrs fnPtrsB;
  final bool sameGroup;

  IsolateA(this.sameGroup) {
    instance = this;
    fnPtrsA = FnPtrs.fromCallbacks(callbacksA);
    atm.toIsoA = atm.toThis;
  }

  Future<void> messageLoop() async {
    if (sameGroup) {
      await Isolate.spawn(IsolateB.entryPoint, recvPort.sendPort);
    } else {
      await Isolate.spawnUri(Platform.script, [], recvPort.sendPort);
    }
    int testIndex = 0;
    await for (final List msg in recvPort) {
      final cmd = msg[0] as String;
      final arg = msg[1];
      if (cmd == 'sendPort') {
        sendPort = arg;
        sendPort.send(['testPort', atm.toThis]);
        sendPort.send(['fnPtrs', fnPtrsA.toList()]);
      } else if (cmd == 'fnPtrs') {
        fnPtrsB = FnPtrs.fromList(arg);
      } else if (cmd == 'testPort') {
        atm.toIsoB = arg;
      } else if (cmd == 'next') {
        if (testIndex >= messagePassingTestCases.length) {
          sendPort.send(['exit', null]);
        } else {
          _callbackResultPort = null;
          sendPort.send(['testCase', testIndex]);
          final testCase = messagePassingTestCases[testIndex];
          print('\nRunning $testCase on IsoA');
          _callbackResultPort = testCase.sendIsoAResultsTo(atm);
        }
      } else if (cmd == 'run') {
        final testCase = messagePassingTestCases[testIndex];
        await testCase.runOnIsoA(this);
        print('Running $testCase on IsoA DONE\n');
        testIndex += 1;
        sendPort.send(['next', null]);
      } else if (cmd == 'exit') {
        break;
      } else {
        Expect.fail('Unknown message: $msg');
        break;
      }
    }
  }

  void close() {
    print("Closing Isolate A");
    recvPort.close();
    atm.close();
    callbacksA.close();
  }
}

// IsolateB is the secondary isolate of the test. It's spawned by IsolateA.
class IsolateB {
  static IsolateB? instance;
  final SendPort sendPort;
  final recvPort = ReceivePort("Isolate B ReceivePort");
  final atm = AsyncTestManager(2000000);
  final natLib = NativeLibrary();
  final callbacksB = Callbacks();
  late final FnPtrs fnPtrsA;
  late final FnPtrs fnPtrsB;

  IsolateB(this.sendPort) {
    instance = this;
    fnPtrsB = FnPtrs.fromCallbacks(callbacksB);
    atm.toIsoB = atm.toThis;
    sendPort.send(['sendPort', recvPort.sendPort]);
    sendPort.send(['testPort', atm.toThis]);
    sendPort.send(['fnPtrs', fnPtrsB.toList()]);
    sendPort.send(['next', null]);
  }

  Future<void> messageLoop() async {
    await for (final List msg in recvPort) {
      final cmd = msg[0] as String;
      final arg = msg[1];
      if (cmd == 'fnPtrs') {
        fnPtrsA = FnPtrs.fromList(arg);
      } else if (cmd == 'testPort') {
        atm.toIsoA = arg;
      } else if (cmd == 'testCase') {
        final testCase = messagePassingTestCases[arg];
        _callbackResultPort = testCase.sendIsoBResultsTo(atm);
        sendPort.send(['run', null]);
        print('\nRunning $testCase on IsoB');
        await testCase.runOnIsoB(this);
        print('Running $testCase on IsoB DONE\n');
      } else if (cmd == 'next') {
        _callbackResultPort = null;
        sendPort.send(['next', null]);
      } else if (cmd == 'exit') {
        sendPort.send(['exit', null]);
        break;
      } else {
        Expect.fail('Unknown message: $msg');
        break;
      }
    }
  }

  void close() {
    print("Closing Isolate B");
    recvPort.close();
    atm.close();
    callbacksB.close();
  }

  static Future<void> entryPoint(SendPort sendPort) async {
    globalVar = 2000;
    final isolateB = IsolateB(sendPort);
    await isolateB.messageLoop();
    isolateB.close();
  }
}
