private static IIpcResult RPCSendCore(ConfiguredCommand conf, IClient rpc, bool isSync) { string operationPayload = ToPayload(conf); var operation = new IpcOperation(operationPayload, waitForServerAck: isSync); return(rpc.Send(operation).GetAwaiter().GetResult()); }
private async Task <Possible <T> > ExecuteCommand <T>(Command <T> command) { try { IIpcOperation ipcOperation = new IpcOperation(Command.Serialize(command), waitForServerAck: true); IIpcResult ipcResult = await m_client.Send(ipcOperation); if (!ipcResult.Succeeded) { return(new Failure <string>(ipcResult.ToString())); } T cmdResult; if (!command.TryParseResult(ipcResult.Payload, out cmdResult)) { return(new Failure <string>($"{ErrorCannotParseIpcResultMessage}: {ipcResult}")); } return(cmdResult); } catch (Exception ex) { return(new Failure <Exception>(ex).Annotate($"Executing {command.GetType().Name} command threw exception.")); } }
public void TestWithExecutionError(IIpcProvider provider) { var testName = nameof(TestWithExecutionError); WithIpcServer( provider, CrashingExecutor, ServerConfigWithLogger(testName), (moniker, server) => { using (var client = provider.GetClient(provider.RenderConnectionString(moniker), ClientConfigWithLogger(testName))) { var syncOp = new IpcOperation("sync", waitForServerAck: true); var asyncOp = new IpcOperation("async", waitForServerAck: false); var syncResult = SendWithTimeout(client, syncOp); var asyncResult = SendWithTimeout(client, asyncOp); Assert.True(asyncResult.Succeeded, "Asynchronous operation is expected to succeed if executor crashes"); Assert.False(syncResult.Succeeded, "Synchronous operation is expected to fail if executor crashes"); Assert.Equal(IpcResultStatus.ExecutionError, syncResult.ExitCode); Assert.True(syncResult.Payload.Contains("System.Exception")); // because CrashingExecutor throws System.Exception Assert.True(syncResult.Payload.Contains(syncOp.Payload)); // because CrashingExecutor throws System.Exception whose message is equal to syncOp.Payload client.RequestStop(); client.Completion.GetAwaiter().GetResult(); } }); }
public async Task TestConnectionLost() { await WithSetup( nameof(TestConnectionLost), async (client, serverSocket) => { using (client) { // issue an operation var op = new IpcOperation("hi", waitForServerAck: true); var sendTask = Task.Run(() => client.Send(op)); // close connection serverSocket.Disconnect(false); serverSocket.Close(); // the task should fail var result = await sendTask; XAssert.IsFalse(result.Succeeded); // assert client fails await Assert.ThrowsAsync <AggregateException>(() => WaitClientDone(client)); } }); }
public void TestConcurrentSynchronousOperations(IIpcProvider provider) { var testName = nameof(TestConcurrentSynchronousOperations); WithIpcServer( provider, EchoingExecutor, ServerConfigWithLogger(testName), (moniker, server) => { using (IClient client = provider.GetClient(provider.RenderConnectionString(moniker), ClientConfigWithLogger(testName))) { var threads = Enumerable .Range(1, 10) .Select(i => new Thread(() => { var message = "hi" + i; var op = new IpcOperation(message, waitForServerAck: true); var result = SendWithTimeout(client, op); Assert.True(result.Succeeded, "error: " + result.Payload); Assert.Equal(op.Payload, result.Payload); })) .ToArray(); Start(threads); Join(threads); client.RequestStop(); client.Completion.GetAwaiter().GetResult(); } }); }
private async Task <Request> SendPing(Stream stream) { var pingOp = new IpcOperation("Ping", waitForServerAck: true); var pingRequest = new Request(pingOp); await pingRequest.SerializeAsync(stream); return(pingRequest); }
/// <summary> /// Serializes this object to a stream writer. /// </summary> /// <remarks> /// Doesn't handle any exceptions. /// </remarks> public async Task SerializeAsync(Stream stream, CancellationToken token) { await Utils.WriteIntAsync(stream, Id, token); await IpcOperation.SerializeAsync(stream, Operation, token); await stream.FlushAsync(token); }
/// <summary> /// Deserializes on object of this type from a stream reader. /// </summary> /// <remarks> /// Doesn't handle any exceptions. /// </remarks> public static async Task <Request> DeserializeAsync(Stream reader, CancellationToken token) { var id = await Utils.ReadIntAsync(reader, token); var operation = await IpcOperation.DeserializeAsync(reader, token); var request = new Request(id, operation); return(request); }
public async Task TestIntertwinedTwoOperations() { await WithSetupAndTeardownAssertingClientCompleted( nameof(TestIntertwinedTwoOperations), async (client, serverStream) => { // create 2 operations var hiOp = new IpcOperation("hi", waitForServerAck: true); var helloOp = new IpcOperation("hello", waitForServerAck: true); // send both operations via the same client var hiTask = Task.Run(() => client.Send(hiOp)); var helloTask = Task.Run(() => client.Send(helloOp)); // receive 2 requests var req1 = await Request.DeserializeAsync(serverStream); var req2 = await Request.DeserializeAsync(serverStream); // aux functions var matchFn = new Func <IIpcOperation, Request>((op) => req1.Operation.Payload == op.Payload ? req1 : req2.Operation.Payload == op.Payload ? req2 : null); var respondFn = new Func <Request, Task>((req) => { var resp = new Response(req.Id, IpcResult.Success(req.Operation.Payload.ToUpperInvariant())); return(resp.SerializeAsync(serverStream)); }); var waitAndCheckResultFn = new Func <Task <IIpcResult>, IIpcOperation, Task>(async(task, operation) => { var result = await task; Assert.Equal(operation.Payload.ToUpperInvariant(), result.Payload); Assert.True(result.Succeeded); }); // match received requests to sent operations var hiReq = matchFn(hiOp); Assert.NotNull(hiReq); Assert.Equal(hiOp.Payload, hiReq.Operation.Payload); var helloReq = matchFn(helloOp); Assert.NotNull(helloReq); Assert.Equal(helloOp.Payload, helloReq.Operation.Payload); // respond to helloReq, assert helloTask completes await respondFn(helloReq); await waitAndCheckResultFn(helloTask, helloOp); // respond to hiReq, assert hiTask completes await respondFn(hiReq); await waitAndCheckResultFn(hiTask, hiOp); }); }
public async Task TestIpcOperationSerializeAsync(string payload, bool waitForAck) { var ipcOp = new IpcOperation(payload, waitForAck); // serialize using var stream = new MemoryStream(); await ipcOp.SerializeAsync(stream, CancellationToken.None); // reset stream position and deserialize stream.Position = 0; var ipcOpClone = await IpcOperation.DeserializeAsync(stream, CancellationToken.None); // compare var errMessage = $"Cloning failed:\n - original: {ipcOp}\n - clone: {ipcOpClone}"; XAssert.AreEqual(payload, ipcOpClone.Payload, errMessage); XAssert.AreEqual(waitForAck, ipcOpClone.ShouldWaitForServerAck, errMessage); }
public async Task TestSendResponseTwice() { await WithSetupAndTeardownAssertingClientFaultedWithIpcException( nameof(TestSendResponseTwice), IpcException.IpcExceptionKind.SpuriousResponse, async (client, serverStream) => { // issue two operations var hiOp = new IpcOperation("hi", waitForServerAck: true); var helloOp = new IpcOperation("hello", waitForServerAck: true); var hiTask = Task.Run(() => client.Send(hiOp)); var helloTask = Task.Run(() => client.Send(helloOp)); // receive 1 request sent by the client var req = await Request.DeserializeAsync(serverStream); // match it to corresponding task var match = req.Operation.Payload == hiOp.Payload ? Tuple.Create(hiTask, helloTask) : req.Operation.Payload == helloOp.Payload ? Tuple.Create(helloTask, hiTask) : null; Assert.NotNull(match); var matchedTask = match.Item1; var otherTask = match.Item2; // send a good response var resp = new Response(req.Id, IpcResult.Success("ok")); await resp.SerializeAsync(serverStream); // assert the matched task completed var result = await matchedTask; Assert.True(result.Succeeded); Assert.Equal("ok", result.Payload); // send the same response again causing the client to fail // with IpcException because the corresponding request has been completed. await resp.SerializeAsync(serverStream); // assert the other task failed var otherResult = await otherTask; Assert.False(otherResult.Succeeded); }); }
public async Task TestSendResponseNotMatchingRequestId() { await WithSetupAndTeardownAssertingClientFaultedWithIpcException( nameof(TestSendResponseNotMatchingRequestId), IpcException.IpcExceptionKind.SpuriousResponse, async (client, serverStream) => { var op = new IpcOperation("hi", waitForServerAck: true); var sendTask = Task.Run(() => client.Send(op)); var req = await Request.DeserializeAsync(serverStream); Assert.Equal(op.Payload, req.Operation.Payload); // send response whose RequestId doesn't match the Id of the request await new Response(req.Id + 100, IpcResult.Success("ok")).SerializeAsync(serverStream); // assert the task fails with a GenericError (and the client fails with IpcException) await AssertGenericErrorIpcResult(sendTask); }); }
private async Task <Possible <T> > ExecuteCommand <T>(Command <T> command) { IIpcOperation ipcOperation = new IpcOperation(Command.Serialize(command), waitForServerAck: true); IIpcResult ipcResult = await m_client.Send(ipcOperation); if (!ipcResult.Succeeded) { return(new Failure <string>(ipcResult.ToString())); } T cmdResult; if (!command.TryParseResult(ipcResult.Payload, out cmdResult)) { return(new Failure <string>("Cannot parse IPC result: " + ipcResult.ToString())); } return(cmdResult); }
public async Task TestSendIllFormattedResponse() { await WithSetupAndTeardownAssertingClientFaultedWithIpcException( nameof(TestSendIllFormattedResponse), IpcException.IpcExceptionKind.Serialization, async (client, serverStream) => { var op = new IpcOperation("hi", waitForServerAck: true); var sendTask = Task.Run(() => client.Send(op)); var req = await Request.DeserializeAsync(serverStream); Assert.Equal(op.Payload, req.Operation.Payload); // send ill-formatted response await Utils.WriteStringAsync(serverStream, "bogus response", CancellationToken.None); // integer is expected on the other end await serverStream.FlushAsync(); // assert the task fails with a GenericError (and the client fails with IpcException) await AssertGenericErrorIpcResult(sendTask); }); }
public void TestSimpleSyncOperation(IIpcProvider provider) { var testName = nameof(TestSimpleSyncOperation); WithIpcServer( provider, EchoingExecutor, ServerConfigWithLogger(testName), (moniker, server) => { using (var client = provider.GetClient(provider.RenderConnectionString(moniker), ClientConfigWithLogger(testName))) { var payload = "sync"; var syncOp = new IpcOperation(payload, waitForServerAck: true); var syncResult = SendWithTimeout(client, syncOp); Assert.True(syncResult.Succeeded, syncResult.Payload); Assert.Equal(syncResult.Payload, payload); client.RequestStop(); client.Completion.GetAwaiter().GetResult(); } }); }