Beispiel #1
0
        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());
        }
Beispiel #2
0
        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."));
            }
        }
Beispiel #3
0
        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));
                }
            });
        }
Beispiel #5
0
        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);
        }
Beispiel #7
0
        /// <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);
        }
Beispiel #8
0
        /// <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);
            });
        }
Beispiel #10
0
        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);
            });
        }
Beispiel #13
0
        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);
            });
        }
Beispiel #15
0
        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();
                }
            });
        }