// 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 --profile_vm=true
// VMOptions=--profiler --profile_vm=false
// 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();
  }
}
