Cysharp/RuntimeUnitTestToolkit

Finally is not being called

Rurouni opened this issue · 0 comments

I have run into interesting bug when noticed that finally is not being called.
I have an coroutine based test that uses grpc with magic onion bits and essentially it boils down to:

var joinPromise = firstClientChat.JoinRoom(new JoinChatRoom() {RoomName = "room", UserName = user1})
                    .ToYieldInstruction(throwOnError: true);
yield return joinPromise;
Result result = joinPromise.Result;
  • when throwOnError: true - finally is not being called
  • when throwOnError: false - finally is being called despite same error is being thrown just one line below

I have a hunch that is something to do with how UnitTestRunner is handling chained coroutines.
To get more context inside firstClientChat.JoinRoom there is call into SendRequestAsync that calls into grpc stream

public IObservable<Message> SendRequestAsync(Message request)
{
   //non relevant code
    var replyReceivedFuture = new AsyncSubject<Message>();

    var pendingOperation = new PendingOperation(requestId, replyReceivedFuture, request);
    PendingOperationsByRequestId.Add(requestId, pendingOperation);

    return Send(request).ContinueWith(u =>
    {
        return replyReceivedFuture
            .Timeout(_sendTimeout)
            .ObserveOnMainThread()
            .Do(m => PendingOperationsByRequestId.Remove(requestId),
                m => PendingOperationsByRequestId.Remove(requestId));
    });
}

public IObservable<Unit> Send(byte[] data)
{
    return _asyncDuplexStreamingCall.RequestStream.WriteAsync(data)
        .DoOnError(e =>
        {
            Log.Warning(e, "{channel}: Send failed with error:{error}", this, e.Message);
        });
}

what happens Is that the error is propagated from _asyncDuplexStreamingCall.RequestStream.WriteAsync(data) then it's being intercepted in UnitTestRunner.UnwrapEnumerator and that stops iterating all enumerators in that recursive call but because it doesn't dispose enumerator that means finally section doesn't have a chance to be called...