Example #1
0
        public void Test_WorkflowReply()
        {
            // Ensures that we can serialize and deserialize workflow reply messages.

            WorkflowReply message;

            using (var stream = new MemoryStream())
            {
                // Empty message.

                message = new WorkflowReply();

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <WorkflowReply>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(0, message.RequestId);
                Assert.Null(message.Error);
                Assert.Equal(0, message.ContextId);
                Assert.Equal(InternalReplayStatus.Unspecified, message.ReplayStatus);

                // Round-trip

                message.ClientId     = 444;
                message.RequestId    = 555;
                message.Error        = new CadenceError("MyError");
                message.ContextId    = 666;
                message.ReplayStatus = InternalReplayStatus.Replaying;

                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal("MyError", message.Error.String);
                Assert.Equal(666, message.ContextId);
                Assert.Equal(InternalReplayStatus.Replaying, message.ReplayStatus);

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <WorkflowReply>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal("MyError", message.Error.String);
                Assert.Equal(666, message.ContextId);
                Assert.Equal(InternalReplayStatus.Replaying, message.ReplayStatus);

                // Clone()

                message = (WorkflowReply)message.Clone();
                Assert.NotNull(message);
                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal("MyError", message.Error.String);
                Assert.Equal(666, message.ContextId);
                Assert.Equal(InternalReplayStatus.Replaying, message.ReplayStatus);
            }
        }
Example #2
0
        /// <summary>
        /// Transmits a message to the local <b>cadence-client</b> web server and then
        /// verifies that the response matches.
        /// </summary>
        /// <typeparam name="TMessage">The message type.</typeparam>
        /// <param name="message">The message to be checked.</param>
        /// <returns>The received echo message.</returns>
        private TMessage EchoToClient <TMessage>(TMessage message)
            where TMessage : ProxyMessage, new()
        {
#if DEBUG
            var bytes   = message.SerializeAsBytes();
            var content = new ByteArrayContent(bytes);

            content.Headers.ContentType = new MediaTypeHeaderValue(ProxyMessage.ContentType);

            var request = new HttpRequestMessage(HttpMethod.Put, "/echo")
            {
                Content = content
            };

            var response = fixture.ConnectionClient.SendAsync(request).Result;

            response.EnsureSuccessStatusCode();

            bytes = response.Content.ReadAsByteArrayAsync().Result;

            return(ProxyMessage.Deserialize <TMessage>(response.Content.ReadAsStreamAsync().Result));
#else
            // The RELEASE client doesn't support the "/echo" endpoint so we'll
            // simply return the input message so the unit tests will pass.

            return(message);
#endif
        }
Example #3
0
        public void Test_ActivityReply()
        {
            // Ensures that we can serialize and deserialize activity reply messages.

            ActivityReply message;

            using (var stream = new MemoryStream())
            {
                // Empty message.

                message = new ActivityReply();

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ActivityReply>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(0, message.RequestId);
                Assert.Null(message.Error);
                Assert.Equal(0, message.ActivityContextId);

                // Round-trip

                message.ClientId          = 444;
                message.RequestId         = 555;
                message.Error             = new CadenceError("MyError");
                message.ActivityContextId = 666;

                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal("MyError", message.Error.String);
                Assert.Equal(666, message.ActivityContextId);

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ActivityReply>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal("MyError", message.Error.String);
                Assert.Equal(666, message.ActivityContextId);

                // Clone()

                message = (ActivityReply)message.Clone();
                Assert.NotNull(message);
                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal("MyError", message.Error.String);
                Assert.Equal(666, message.ActivityContextId);
            }
        }
Example #4
0
        public void Test_WorkflowRequest()
        {
            // Ensures that we can serialize and deserialize workflow request messages.

            WorkflowRequest message;

            using (var stream = new MemoryStream())
            {
                // Empty message.

                message = new WorkflowRequest();

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <WorkflowRequest>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(0, message.ClientId);
                Assert.Equal(0, message.RequestId);
                Assert.Equal(0, message.ContextId);

                // Round-trip

                message.ClientId  = 444;
                message.RequestId = 555;
                message.ContextId = 666;

                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal(666, message.ContextId);

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <WorkflowRequest>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal(666, message.ContextId);

                // Clone()

                message = (WorkflowRequest)message.Clone();
                Assert.NotNull(message);
                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.Equal(666, message.ContextId);
            }
        }
Example #5
0
        public void Test_ProxyRequest()
        {
            // Ensures that we can serialize and deserialize request messages.

            ProxyRequest message;

            using (var stream = new MemoryStream())
            {
                // Empty message.

                message = new ProxyRequest();

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ProxyRequest>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(0, message.ClientId);
                Assert.Equal(0, message.RequestId);
                Assert.False(message.IsCancellable);

                // Round-trip

                message.ClientId  = 444;
                message.RequestId = 555;
                Assert.Equal(555, message.RequestId);
                message.IsCancellable = true;

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ProxyRequest>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.True(message.IsCancellable);

                // Clone()

                message = (ProxyRequest)message.Clone();
                Assert.NotNull(message);
                Assert.Equal(444, message.ClientId);
                Assert.Equal(555, message.RequestId);
                Assert.True(message.IsCancellable);
            }
        }
Example #6
0
        /// <summary>
        /// Handles requests to the test <b>"/echo"</b> endpoint path.
        /// </summary>
        /// <param name="context">The request context.</param>
        /// <returns>The tracking <see cref="Task"/>.</returns>
        private async Task OnEchoRequestAsync(HttpContext context)
        {
            var request        = context.Request;
            var response       = context.Response;
            var requestMessage = ProxyMessage.Deserialize <ProxyMessage>(request.Body);
            var clonedMessage  = requestMessage.Clone();

            response.ContentType = ProxyMessage.ContentType;

            var stream = clonedMessage.SerializeAsStream();

            try
            {
                await stream.CopyToAsync(response.Body);
            }
            finally
            {
                MemoryStreamPool.Free(stream);
            }
        }
Example #7
0
        /// <summary>
        /// Transmits a message to the connection's associated <b>temporal-proxy</b>
        /// and then verifies that the response matches.
        /// </summary>
        /// <typeparam name="TMessage">The message type.</typeparam>
        /// <param name="message">The message to be checked.</param>
        /// <returns>The received echo message.</returns>
        private TMessage EchoToProxy <TMessage>(TMessage message)
            where TMessage : ProxyMessage, new()
        {
            var bytes   = message.SerializeAsBytes();
            var content = new ByteArrayContent(bytes);

            content.Headers.ContentType = new MediaTypeHeaderValue(ProxyMessage.ContentType);

            var request = new HttpRequestMessage(HttpMethod.Put, "/echo")
            {
                Content = content
            };

            var response = proxyClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;

            response.EnsureSuccessStatusCode();

            bytes = response.Content.ReadAsByteArrayAsync().Result;

            return(ProxyMessage.Deserialize <TMessage>(response.Content.ReadAsStreamAsync().Result));
        }
Example #8
0
        public void Test_ProxyReply()
        {
            // Ensures that we can serialize and deserialize reply messages.

            ProxyReply message;

            using (var stream = new MemoryStream())
            {
                // Empty message.

                message = new ProxyReply();

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ProxyReply>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(0, message.RequestId);
                Assert.Null(message.Error);

                // Round-trip

                message.RequestId = 555;
                message.Error     = new CadenceError("MyError");

                Assert.Equal(555, message.RequestId);
                Assert.Equal("MyError", message.Error.String);

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ProxyReply>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(555, message.RequestId);
                Assert.Equal("MyError", message.Error.String);
            }
        }
Example #9
0
        public void Test_ActivityRequest()
        {
            // Ensures that we can serialize and deserialize activity request messages.

            ActivityRequest message;

            using (var stream = new MemoryStream())
            {
                // Empty message.

                message = new ActivityRequest();

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ActivityRequest>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(0, message.RequestId);
                Assert.Equal(0, message.ContextId);

                // Round-trip

                message.RequestId = 555;
                Assert.Equal(555, message.RequestId);
                message.ContextId = 666;
                Assert.Equal(666, message.ContextId);

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ActivityRequest>(stream, ignoreTypeCode: true);
                Assert.NotNull(message);
                Assert.Equal(555, message.RequestId);
                Assert.Equal(666, message.ContextId);
            }
        }
Example #10
0
        public void Test_ProxyMessage()
        {
            // Ensures that we can serialize and deserialize base messages.

            ProxyMessage message;

            using (var stream = new MemoryStream())
            {
                // Empty message.

                message = new ProxyMessage();

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ProxyMessage>(stream, ignoreTypeCode: true);
                Assert.Equal(InternalMessageTypes.Unspecified, message.Type);
                Assert.Empty(message.Properties);
                Assert.Empty(message.Attachments);

                // Message with args and attachments.

                message = new ProxyMessage();

                message.Properties.Add(PropertyNames.TestOne, "1");
                message.Properties.Add(PropertyNames.TestTwo, "2");
                message.Properties.Add(PropertyNames.TestEmpty, string.Empty);
                message.Properties.Add(PropertyNames.TestNull, null);

                message.SetJsonProperty(PropertyNames.TestComplex, new ComplexType()
                {
                    Name = "foo", Value = "bar"
                });
                message.SetJsonProperty(PropertyNames.TestPerson, new Person()
                {
                    Name = "Jack", Age = 10
                });

                message.Attachments.Add(new byte[] { 0, 1, 2, 3, 4 });
                message.Attachments.Add(new byte[0]);
                message.Attachments.Add(null);

                stream.SetLength(0);
                stream.Write(message.SerializeAsBytes(ignoreTypeCode: true));
                stream.Seek(0, SeekOrigin.Begin);

                message = ProxyMessage.Deserialize <ProxyMessage>(stream, ignoreTypeCode: true);
                Assert.Equal(InternalMessageTypes.Unspecified, message.Type);
                Assert.Equal(6, message.Properties.Count);
                Assert.Equal("1", message.Properties[PropertyNames.TestOne]);
                Assert.Equal("2", message.Properties[PropertyNames.TestTwo]);
                Assert.Empty(message.Properties[PropertyNames.TestEmpty]);
                Assert.Null(message.Properties[PropertyNames.TestNull]);

                var complex = message.GetJsonProperty <ComplexType>(PropertyNames.TestComplex);
                Assert.Equal("foo", complex.Name);
                Assert.Equal("bar", complex.Value);

                var person = message.GetJsonProperty <Person>(PropertyNames.TestPerson);
                Assert.Equal("Jack", person.Name);
                Assert.Equal(10, person.Age);

                Assert.Equal(3, message.Attachments.Count);
                Assert.Equal(new byte[] { 0, 1, 2, 3, 4 }, message.Attachments[0]);
                Assert.Empty(message.Attachments[1]);
                Assert.Null(message.Attachments[2]);
            }
        }
Example #11
0
        /// <summary>
        /// Handles requests to the emulated <b>cadence-proxy</b> root <b>"/"</b> endpoint path.
        /// </summary>
        /// <param name="context">The request context.</param>
        /// <returns>The tracking <see cref="Task"/>.</returns>
        private async Task OnEmulatedRootRequestAsync(HttpContext context)
        {
            var request      = context.Request;
            var response     = context.Response;
            var proxyMessage = ProxyMessage.Deserialize <ProxyMessage>(request.Body);

            if (EmulatedLibraryClient == null && proxyMessage.Type != InternalMessageTypes.InitializeRequest)
            {
                response.StatusCode = StatusCodes.Status400BadRequest;
                await response.WriteAsync($"Unexpected Message: Waiting for an [{nameof(InitializeRequest)}] message to specify the [cadence-client] network endpoint.");

                return;
            }

            // Handle proxy reply messages by completing any pending [CallClientAsync()] operation.

            var reply = proxyMessage as ProxyReply;

            if (reply != null)
            {
                Operation operation;

                using (await emulationMutex.AcquireAsync())
                {
                    emulatedOperations.TryGetValue(reply.RequestId, out operation);
                }

                if (operation != null)
                {
                    if (reply.Type != operation.Request.ReplyType)
                    {
                        response.StatusCode = StatusCodes.Status400BadRequest;
                        await response.WriteAsync($"[cadence-emulation] has a request [type={operation.Request.Type}, requestId={operation.RequestId}] pending but reply [type={reply.Type}] is not valid and will be ignored.");
                    }
                    else
                    {
                        operation.SetReply(reply);
                        response.StatusCode = StatusCodes.Status200OK;
                    }
                }
                else
                {
                    log.LogWarn(() => $"[cadence-emulation] reply [type={reply.Type}, requestId={reply.RequestId}] does not map to a pending operation and will be ignored.");

                    response.StatusCode = StatusCodes.Status400BadRequest;
                    await response.WriteAsync($"[cadence-emulation] does not have a pending operation with [requestId={reply.RequestId}].");
                }

                return;
            }

            // Handle proxy request messages.

            switch (proxyMessage.Type)
            {
            //-------------------------------------------------------------
            // Client messages

            case InternalMessageTypes.CancelRequest:

                await OnEmulatedCancelRequestAsync((CancelRequest)proxyMessage);

                break;

            case InternalMessageTypes.DomainDescribeRequest:

                await OnEmulatedDomainDescribeRequestAsync((DomainDescribeRequest)proxyMessage);

                break;

            case InternalMessageTypes.DomainRegisterRequest:

                await OnEmulatedDomainRegisterRequestAsync((DomainRegisterRequest)proxyMessage);

                break;

            case InternalMessageTypes.DomainUpdateRequest:

                await OnEmulatedDomainUpdateRequestAsync((DomainUpdateRequest)proxyMessage);

                break;

            case InternalMessageTypes.HeartbeatRequest:

                await OnEmulatedHeartbeatRequestAsync((HeartbeatRequest)proxyMessage);

                break;

            case InternalMessageTypes.InitializeRequest:

                await OnEmulatedInitializeRequestAsync((InitializeRequest)proxyMessage);

                break;

            case InternalMessageTypes.ConnectRequest:

                await OnEmulatedConnectRequestAsync((ConnectRequest)proxyMessage);

                break;

            case InternalMessageTypes.TerminateRequest:

                await OnEmulatedTerminateRequestAsync((TerminateRequest)proxyMessage);

                break;

            case InternalMessageTypes.NewWorkerRequest:

                await OnEmulatedNewWorkerRequestAsync((NewWorkerRequest)proxyMessage);

                break;

            case InternalMessageTypes.StopWorkerRequest:

                await OnEmulatedStopWorkerRequestAsync((StopWorkerRequest)proxyMessage);

                break;

            case InternalMessageTypes.PingRequest:

                await OnEmulatedPingRequestAsync((PingRequest)proxyMessage);

                break;

            //-------------------------------------------------------------
            // Workflow messages

            case InternalMessageTypes.WorkflowExecuteRequest:

                await OnEmulatedWorkflowExecuteRequestAsync((WorkflowExecuteRequest)proxyMessage);

                break;

            case InternalMessageTypes.WorkflowRegisterRequest:

                await OnEmulatedWorkflowRegisterRequestAsync((WorkflowRegisterRequest)proxyMessage);

                break;

            case InternalMessageTypes.WorkflowSetCacheSizeRequest:

                await OnEmulatedWorkflowSetCacheSizeRequestAsync((WorkflowSetCacheSizeRequest)proxyMessage);

                break;

            case InternalMessageTypes.WorkflowGetResultRequest:

                await OnEmulatedWorkflowGetResultRequestAsync((WorkflowGetResultRequest)proxyMessage);

                break;

            //-------------------------------------------------------------

            default:

                response.StatusCode = StatusCodes.Status400BadRequest;
                await response.WriteAsync($"EMULATION: Message [{proxyMessage.Type}] is not supported.");

                break;
            }

            await Task.CompletedTask;
        }