public async Task Should_set_exception_on_rpc_error_response()
        {
            var reqMsg = new Message(0x100500, 1, new TestRequest {TestId = 1});
            
            var rpcResult = new RpcResult
            {
                ReqMsgId = reqMsg.MsgId,
                Result = new RpcError {ErrorCode = 400, ErrorMessage = "BAD_REQUEST"}
            };
            var resMsg = new Message(0x200600, 2, rpcResult);

            var request = new Mock<IRequest>();
            request.SetupGet(r => r.Message).Returns(reqMsg);

            var requestsManager = new Mock<IRequestsManager>();
            requestsManager.Setup(manager => manager.Get(reqMsg.MsgId)).Returns(request.Object);

            var handler = new RpcResultHandler(requestsManager.Object);
            await handler.HandleAsync(resMsg);

            requestsManager.Verify(manager => manager.Get(It.IsAny<ulong>()), Times.Once);
            requestsManager.Verify(manager => manager.Get(reqMsg.MsgId), Times.Once);

            request.Verify(r => r.SetException(It.IsAny<Exception>()), Times.Once);
            request.Verify(
                r => r.SetException(It.Is<RpcErrorException>(exception => exception.Error == rpcResult.Result)),
                Times.Once);
        }
        public async Task Should_set_rpc_result_to_requst()
        {
            var reqMsg = new Message(0x100500, 1, new TestRequest {TestId = 1});
            
            var rpcResult = new RpcResult
            {
                ReqMsgId = reqMsg.MsgId,
                Result = new TestResponse {TestId = 1, TestText = "THIS IS RESPONSE!"}
            };
            var resMsg = new Message(0x200600, 2, rpcResult);

            var request = new Mock<IRequest>();
            request.SetupGet(r => r.Message).Returns(reqMsg);

            var requestsManager = new Mock<IRequestsManager>();
            requestsManager.Setup(manager => manager.Get(reqMsg.MsgId)).Returns(request.Object);

            var handler = new RpcResultHandler(requestsManager.Object);
            await handler.HandleAsync(resMsg);

            requestsManager.Verify(manager => manager.Get(It.IsAny<ulong>()), Times.Once);
            requestsManager.Verify(manager => manager.Get(reqMsg.MsgId), Times.Once);

            request.Verify(r => r.SetResponse(It.IsAny<object>()), Times.Once);
            request.Verify(r => r.SetResponse(rpcResult.Result), Times.Once);
        }
        public async Task Should_update_salt_and_resend_message_on_bad_server_salt_notification()
        {
            const ulong newSalt = 9;

            var reqMsg = new Message(0x100500, 1, new Object());
            var request = new Mock<IRequest>();
            request.SetupGet(r => r.Message).Returns(reqMsg);
            var resMsg = new Message(
                0x200600,
                2,
                new BadServerSalt {BadMsgId = reqMsg.MsgId, BadMsgSeqno = reqMsg.Seqno, ErrorCode = (uint) ErrorCode.IncorrectServerSalt, NewServerSalt = newSalt});

            var connection = new Mock<IMTProtoClientConnection>();
            var requestsManager = new Mock<IRequestsManager>();
            requestsManager.Setup(manager => manager.Get(reqMsg.MsgId)).Returns(request.Object);

            var handler = new BadMsgNotificationHandler(connection.Object, requestsManager.Object);
            await handler.HandleAsync(resMsg);

            connection.Verify(c => c.UpdateSalt(It.IsAny<ulong>()), Times.Once);
            connection.Verify(c => c.UpdateSalt(newSalt), Times.Once);

            requestsManager.Verify(manager => manager.Get(It.IsAny<ulong>()), Times.Once);
            requestsManager.Verify(manager => manager.Get(reqMsg.MsgId), Times.Once);

            request.Verify(r => r.SendAsync(), Times.Once);
        }
        public async Task Should_dispatch_messages()
        {
            var msg1 = new Message(1, 2, new TestResponse {TestId = 3, TestText = "TEXT 1"});
            var msg1Ex = new Message(3, 4, new TestResponseEx {TestId = 3, TestText = "TEXT 1", TestText2 = "TEXT 1 EX"});
            var msg2 = new Message(5, 6, new TestResponse2 {Name = "Mr.Resp", Address = "1 Object st.", City = "Class"});
            var msg3 = new Message(7, 8, 9);

            Expression<Func<IResponseHandler, Task>> handleAnyMsgExp = handler => handler.HandleAsync(It.IsAny<IMessage>());

            var handler1 = new Mock<IResponseHandler>();
            handler1.SetupGet(handler => handler.ResponseType).Returns(typeof (ITestResponse));

            var handler2 = new Mock<IResponseHandler>();
            handler2.SetupGet(handler => handler.ResponseType).Returns(typeof (ITestResponse2));

            var handlerF = new Mock<IResponseHandler>();
            handlerF.SetupGet(handler => handler.ResponseType).Returns(typeof (object));

            var dispatcher = new ResponseDispatcher();
            dispatcher.AddHandler(handler1.Object);
            dispatcher.AddHandler(handler2.Object);
            dispatcher.FallbackHandler = handlerF.Object;

            await dispatcher.DispatchAsync(msg1);

            handler1.Verify(handler => handler.HandleAsync(msg1));
            handler1.Verify(handleAnyMsgExp, Times.Once());
            handler2.Verify(handleAnyMsgExp, Times.Never());
            handlerF.Verify(handleAnyMsgExp, Times.Never());

            await dispatcher.DispatchAsync(msg1Ex);

            handler1.Verify(handler => handler.HandleAsync(msg1Ex));
            handler1.Verify(handleAnyMsgExp, Times.Exactly(2));
            handler2.Verify(handleAnyMsgExp, Times.Never());
            handlerF.Verify(handleAnyMsgExp, Times.Never());

            await dispatcher.DispatchAsync(msg2);

            handler2.Verify(handler => handler.HandleAsync(msg2));
            handler2.Verify(handleAnyMsgExp, Times.Once());
            handler1.Verify(handleAnyMsgExp, Times.Exactly(2));
            handlerF.Verify(handleAnyMsgExp, Times.Never());

            await dispatcher.DispatchAsync(msg3);

            handlerF.Verify(handler => handler.HandleAsync(msg3), "Fallback handler didn't handle a message.");
            handlerF.Verify(handleAnyMsgExp, Times.Once());
            handler1.Verify(handleAnyMsgExp, Times.Exactly(2));
            handler2.Verify(handleAnyMsgExp, Times.Once);
        }
        public async Task Should_handle_container_and_forward_internal_messages_to_dispatcher()
        {
            var messages = new List<Message> {new Message(1, 1, 1), new Message(2, 2, 2), new Message(3, 3, 3)};
            var containerMessage = new Message(4, 4, new MsgContainer {Messages = messages});
            List<Message> expectedMessages = messages.CloneTLObject();
            var receivedMessages = new List<IMessage>();

            var responseDispatcher = new Mock<IResponseDispatcher>();
            responseDispatcher.Setup(dispatcher => dispatcher.DispatchAsync(It.IsAny<IMessage>()))
                .Returns(TaskConstants.Completed)
                .Callback<IMessage>(receivedMessages.Add);

            var handler = new MessageContainerHandler(responseDispatcher.Object);
            await handler.HandleAsync(containerMessage);

            receivedMessages.Should().Equal(expectedMessages);
        }
        public async Task Should_set_response_to_request()
        {
            var request = new Mock<IRequest>();
            request.SetupGet(request1 => request1.Message).Returns(() => new Message(1, 1, new TestRequest {TestId = 1}));

            var response = new TestResponse {TestId = 1, TestText = "Simple test text."};
            var responseMessage = new Message(1, 1, response);

            var requestsManager = new Mock<IRequestsManager>();
            requestsManager.Setup(manager => manager.GetFirstOrDefault(response, It.IsAny<bool>())).Returns(request.Object).Verifiable();

            var handler = new FirstRequestResponseHandler(requestsManager.Object);
            await handler.HandleAsync(responseMessage);

            requestsManager.Verify();
            request.Verify(request1 => request1.SetResponse(response), Times.Once());
        }
        public async Task Should_send_plain_message_and_wait_for_response()
        {
            IServiceLocator serviceLocator = TestRig.CreateTestServiceLocator();

            var messageProcessor = serviceLocator.ResolveType<IMessageCodec>();

            var request = new TestRequest {TestId = 9};
            var expectedResponse = new TestResponse {TestId = 9, TestText = "Number 1"};
            var expectedResponseMessage = new Message(0x0102030405060708, 0, expectedResponse);
            byte[] expectedResponseMessageBytes = messageProcessor.EncodePlainMessage(expectedResponseMessage);

            SetupMockTransportWhichReturnsBytes(serviceLocator, expectedResponseMessageBytes);

            using (var connection = serviceLocator.ResolveType<IMTProtoClientConnection>())
            {
                await connection.Connect();

                // Testing sending a plain message.
                TestResponse response = await connection.RequestAsync<TestResponse>(request, MessageSendingFlags.None, TimeSpan.FromSeconds(5));
                response.Should().NotBeNull();
                response.Should().Be(expectedResponse);

                await connection.Disconnect();
            }
        }