public IOwned <RpcObjectRef <TService> > PublishInstance <TService>(IOwned <TService> serviceInstance)
            where TService : class
        {
            if (serviceInstance is null)
            {
                throw new ArgumentNullException(nameof(serviceInstance));
            }
            var allServices = RpcBuilderUtil.GetAllServices(serviceInstance.Value.GetType(), true);

            this.TryRegisterServiceDefinitions(allServices, null);

            var connectionInfo = this.RetrieveConnectionInfo();

            lock (this.syncRoot)
            {
                var serviceInstanceId = RpcObjectId.NewId();

                var publishedServices = this.PublishInstanceCore_Locked(allServices, serviceInstance, serviceInstanceId, false);

                Func <ValueTask> disposeAction = () => this.UnpublishInstanceAsync(serviceInstanceId);

                return(OwnedObject.Create(new RpcObjectRef <TService>(
                                              connectionInfo, serviceInstanceId, publishedServices.ToArray()), disposeAction));
            }
        }
Exemple #2
0
        public async Task UnavailableService_ShouldThrowRpcServiceUnavailableException(TestOperationType operationType)
        {
            var serviceRegistrator = new RpcServiceDefinitionsBuilder();

            serviceRegistrator
            .RegisterService <IBlockingService>()
            .RegisterService <ISimpleService>();

            var(host, connection) = this.CreateServerAndConnection(serviceRegistrator);
            using (var publishedInstanceScope = host.ServicePublisher.PublishInstance <IBlockingService>(new TestBlockingServiceImpl()))
            {
                var objectId = RpcObjectId.NewId();
                var blockingClientService = connection.GetServiceInstance <IBlockingServiceClient>(objectId);
                var simpleService         = connection.GetServiceInstance <ISimpleService>(objectId);
                host.Start();

                try
                {
                    // Invoke unknown service instance
                    switch (operationType)
                    {
                    case TestOperationType.BlockingBlocking:
                        Assert.Throws <RpcServiceUnavailableException>(() => blockingClientService.Add(12, 13));
                        break;

                    case TestOperationType.AsyncBlocking:
                        // Async/blocking (client/host)
                        Assert.ThrowsAsync <RpcServiceUnavailableException>(() => blockingClientService.AddAsync(12, 13));
                        break;

                    case TestOperationType.BlockingBlockingVoid:
                        Assert.Throws <RpcServiceUnavailableException>(() => blockingClientService.Value = 23);
                        break;

                    case TestOperationType.AsyncBlockingVoid:
                        // Async/blocking void (client/host)
                        Assert.ThrowsAsync <RpcServiceUnavailableException>(() => blockingClientService.SetValueAsync(13));
                        break;

                    case TestOperationType.AsyncAsync:
                        // Async/async (client/host)
                        Assert.ThrowsAsync <RpcServiceUnavailableException>(() => simpleService.AddAsync(12, 13));
                        break;

                    case TestOperationType.AsyncAsyncVoid:
                        // Async/async void (client/host)
                        Assert.ThrowsAsync <RpcServiceUnavailableException>(() => simpleService.SetValueAsync(12));
                        break;
                    }

                    var exisingService = connection.GetServiceInstance <IBlockingServiceClient>(publishedInstanceScope.Value);
                    // Make sure that the connection is still usable after exception
                    Assert.AreEqual(12 + 13, exisingService.Add(12, 13));
                }
                finally
                {
                    await host.ShutdownAsync();
                }
            }
        }
        private (TService, Mock <TestCallInvoker>) CreateServiceInstance <TService>() where TService : class
        {
            var(moduleBuilder, definedTypes) = this.CreateModuleBuilder();
            var proxyBuilder = new RpcServiceProxyBuilder <GrpcProxyBase, GrpcProxyMethod>(RpcBuilderUtil.GetAllServices <TService>(true), moduleBuilder, definedTypes);

            var(proxyType, proxyMethods) = proxyBuilder.BuildObjectProxyType(new Type[] { typeof(GrpcProxyArgs), typeof(GrpcProxyMethod[]) });

            ValidateProxyType <TService>(proxyType);

            var factory = RpcServiceProxyBuilder <GrpcProxyBase, GrpcProxyMethod> .CreateObjectProxyFactory <GrpcProxyArgs>(proxyType);

            var callInvokerMock = new Mock <TestCallInvoker>(MockBehavior.Strict);
            var connectionMock  = new Mock <IRpcConnection>(MockBehavior.Strict);

            connectionMock.Setup(m => m.Options).Returns(ImmutableRpcClientOptions.Empty);
            var serializer = new ProtobufRpcSerializer();

            var args = new GrpcProxyArgs
                       (
                objectId: RpcObjectId.NewId(),
                connection: connectionMock.Object,
                callInvoker: callInvokerMock.Object,
                serializer: serializer,
                methodsCache: new GrpcMethodsCache(serializer),
                implementedServices: null,
                syncContext: null
                       );

            var serviceInstance = factory(args, proxyMethods);

            return((TService)(object)serviceInstance, callInvokerMock);
        }
Exemple #4
0
        public async Task GenerateSimpleServiceStubTest()
        {
            var binder = new TestLightweightMethodBinder();

            CreateSimpleServiceStub <ISimpleService>(new TestSimpleServiceImpl(), binder);

            LightweightMethodStub addStub = binder.GetHandler <RpcObjectRequest <int, int>, RpcResponse <int> >("SciTech.Rpc.Tests.SimpleService.Add");

            Assert.NotNull(addStub);

            var objectId = RpcObjectId.NewId();
            var request  = new RpcObjectRequest <int, int>(objectId, 5, 6);
            RpcResponse <int> addResponse = await LightweightStubHelper.SendReceiveAsync <RpcObjectRequest <int, int>, RpcResponse <int> >(addStub, request, DefaultSerializer);

            Assert.AreEqual(11, addResponse.Result);

            LightweightMethodStub setStub = binder.GetHandler <RpcObjectRequest <double>, RpcResponse>("SciTech.Rpc.Tests.SimpleService.SetValue");

            Assert.NotNull(setStub);
            var setResponse = await LightweightStubHelper.SendReceiveAsync <RpcObjectRequest <double>, RpcResponse>(setStub, new RpcObjectRequest <double>(objectId, 20), DefaultSerializer);

            Assert.NotNull(setResponse);

            LightweightMethodStub getStub = binder.GetHandler <RpcObjectRequest, RpcResponse <double> >("SciTech.Rpc.Tests.SimpleService.GetValue");

            Assert.NotNull(getStub);
            var getResponse = await LightweightStubHelper.SendReceiveAsync <RpcObjectRequest, RpcResponse <double> >(getStub, new RpcObjectRequest(objectId), DefaultSerializer);

            Assert.AreEqual(20, getResponse.Result);
        }
Exemple #5
0
        public void HostNotFoundTest()
        {
            var serviceRegistrator = new RpcServiceDefinitionsBuilder();

            serviceRegistrator
            .RegisterService <IBlockingService>();;

            var(_, connection) = this.CreateServerAndConnection(serviceRegistrator);

            var objectId      = RpcObjectId.NewId();
            var clientService = connection.GetServiceInstance <IBlockingServiceClient>(objectId);

            // Invoke client operation without starting host
            Assert.Throws <RpcCommunicationException>(() => clientService.Add(12, 13));
        }
        public async Task SimpleServiceSetGetStubTest()
        {
            var binder = new TestMethodBinder();

            CreateSimpleServiceStub <ISimpleService>(new TestSimpleServiceImpl(), binder);
            var callContext = CreateServerCallContext(CancellationToken.None);

            var objectId = RpcObjectId.NewId();

            var setHandler = binder.GetHandler <UnaryServerMethod <RpcObjectRequest <double>, RpcResponse> >("SetValue");

            await setHandler(new RpcObjectRequest <double>(objectId, 123.456), callContext);

            var getHandler  = binder.GetHandler <UnaryServerMethod <RpcObjectRequest, RpcResponse <double> > >("GetValue");
            var getResponse = await getHandler(new RpcObjectRequest(objectId), callContext);

            Assert.AreEqual(123.456, getResponse.Result);
        }
        public async Task GenerateSimpleServiceStubTest()
        {
            var binder = new TestMethodBinder();

            CreateSimpleServiceStub <ISimpleService>(new TestSimpleServiceImpl(), binder);

            var callContext = CreateServerCallContext(CancellationToken.None);

            var addHandler = binder.GetHandler <GrpcCore.UnaryServerMethod <RpcObjectRequest <int, int>, RpcResponse <int> > >("Add");

            Assert.NotNull(addHandler);

            var objectId        = RpcObjectId.NewId();
            var addResponseTask = addHandler.Invoke(new RpcObjectRequest <int, int>(objectId, 5, 6), callContext);

            var response = await addResponseTask.DefaultTimeout();

            Assert.AreEqual(11, response.Result);
        }
        public IOwned <RpcObjectRef <TService> > PublishInstance <TService>(Func <IServiceProvider?, RpcObjectId, IOwned <TService> > factory)
            where TService : class
        {
            var allServices = RpcBuilderUtil.GetAllServices(typeof(TService), RpcServiceDefinitionSide.Server, true);

            this.TryRegisterServiceDefinitions(allServices, null);

            var connectionInfo = this.RetrieveConnectionInfo();

            lock (this.syncRoot)
            {
                var objectId = RpcObjectId.NewId();

                var publishedServices = this.PublishInstanceFactoryCore_Locked(allServices, objectId, factory);

                return(OwnedObject.Create(new RpcObjectRef <TService>(
                                              connectionInfo, objectId, publishedServices.ToArray()),
                                          () => this.UnpublishInstanceAsync(objectId)));
            }
        }
        public RpcObjectRef <TService> GetOrPublishInstance <TService>(TService serviceInstance) where TService : class
        {
            if (serviceInstance is null)
            {
                throw new ArgumentNullException(nameof(serviceInstance));
            }

            InstanceKey key;

            lock (this.syncRoot)
            {
                key = new InstanceKey(serviceInstance);
                if (this.serviceImplToId.TryGetValue(key, out var instanceId))
                {
                    return(new RpcObjectRef <TService>(this.connectionInfo, instanceId, this.GetPublishedServices(instanceId).ToArray()));
                }
            }

            // Not published, so we try to register the serviceInstance's service definitions
            // and then publish it.

            var allServices = RpcBuilderUtil.GetAllServices(serviceInstance.GetType(), true);

            this.TryRegisterServiceDefinitions(allServices, null);

            var connectionInfo = this.RetrieveConnectionInfo();

            lock (this.syncRoot)
            {
                // Let's try again.
                if (this.serviceImplToId.TryGetValue(key, out var instanceId))
                {
                    // Somebody beat us to it.
                    return(new RpcObjectRef <TService>(this.connectionInfo, instanceId, this.GetPublishedServices(instanceId).ToArray()));
                }

                var objectId             = RpcObjectId.NewId();
                var newPublishedServices = this.PublishInstanceCore_Locked(allServices, OwnedObject.CreateUnowned(serviceInstance), objectId, true);
                return(new RpcObjectRef <TService>(connectionInfo, objectId, newPublishedServices.ToArray()));
            }
        }
        public async Task BlockingStubTest()
        {
            // TODO: Should use a mock instead.
            var serviceImpl = new TestBlockingSimpleServiceImpl();
            var binder      = new TestMethodBinder();

            CreateSimpleServiceStub <IBlockingService>(serviceImpl, binder);
            var callContext = CreateServerCallContext(CancellationToken.None);

            var objectId = RpcObjectId.NewId();

            var setMethod = binder.methods.FirstOrDefault(p => p.Item1.Name == "SetValue");

            Assert.NotNull(setMethod);

            var setValueHandler = (UnaryServerMethod <RpcObjectRequest <double>, RpcResponse>)setMethod.Item2;

            await setValueHandler(new RpcObjectRequest <double>(objectId, 123.456), callContext);

            //await (Task<RpcResponse>)setMethod.Invoke(serviceStub, new object[] { new RpcObjectRequest<double>(objectId, 123.456), callContext });
            Assert.AreEqual(1, serviceImpl.nBlockingSetValue);

            var getMethod = binder.methods.FirstOrDefault(p => p.Item1.Name == "GetValue");

            Assert.NotNull(getMethod);

            var getValueHandler = (UnaryServerMethod <RpcObjectRequest, RpcResponse <double> >)getMethod.Item2;
            var getResponse     = await getValueHandler(new RpcObjectRequest(objectId), callContext);

            Assert.AreEqual(1, serviceImpl.nBlockingGetValue);

            Assert.AreEqual(123.456, getResponse.Result);

            var addMethod   = binder.methods.FirstOrDefault(p => p.Item1.Name == "Add");
            var addHandler  = (UnaryServerMethod <RpcObjectRequest <int, int>, RpcResponse <int> >)addMethod.Item2;
            var addResponse = await addHandler(new RpcObjectRequest <int, int>(objectId, 8, 9), callContext);

            Assert.AreEqual(1, serviceImpl.nBlockingAdd);

            Assert.AreEqual(17, addResponse.Result);
        }
        public async Task DeviceServiceTest()
        {
            var serviceImpl = new ThermostatServiceImpl();

            var implProviderMock = new Mock <IRpcServiceActivator>();

            implProviderMock.Setup(p => p.GetActivatedService <IDeviceService>(It.IsAny <IServiceProvider>(), It.IsAny <RpcObjectId>())).Returns(new ActivatedService <IDeviceService>(serviceImpl, null));

            var callContext = CreateServerCallContext(CancellationToken.None);
            var binder      = new TestMethodBinder();

            CreateSimpleServiceStub <IDeviceService>(serviceImpl, binder);

            var objectId = RpcObjectId.NewId();

            var getMethod = binder.methods.FirstOrDefault(p => p.Item1.Name == "GetDeviceAcoId");

            Assert.NotNull(getMethod);
            var getValueHandler = (UnaryServerMethod <RpcObjectRequest, RpcResponse <Guid> >)getMethod.Item2;
            var getResponse     = await getValueHandler(new RpcObjectRequest(objectId), callContext);

            Assert.AreEqual(serviceImpl.DeviceAcoId, getResponse.Result);
        }
Exemple #12
0
        public void IncorrectServiceFault_ShouldThrowDefinitionException()
        {
            var serviceRegistrator = new RpcServiceDefinitionsBuilder();

            var(_, connection) = this.CreateServerAndConnection(serviceRegistrator);

            Assert.Throws <RpcDefinitionException>(() => connection.GetServiceInstance <IIncorrectServiceFaultServiceClient>(RpcObjectId.NewId()));
        }
        public async Task EventHandlerTest()
        {
            var serviceImpl = new TestServiceWithEventsImpl();

            var binder = new TestMethodBinder();

            CreateSimpleServiceStub <ISimpleServiceWithEvents>(serviceImpl, binder);

            var beginHandler = binder.GetHandler <GrpcCore.ServerStreamingServerMethod <RpcObjectRequest, EventArgs> >("BeginValueChanged");

            var objectId = RpcObjectId.NewId();


            //var valueChangedMethod = stubType.GetMethod($"Begin{nameof(IServiceWithEvents.ValueChanged)}");
            var valueChangedStreamWriter = new ServerEventStreamWriter <EventArgs>(10);
            CancellationTokenSource eventListerCancellationSource = new CancellationTokenSource();
            var  callContext      = CreateServerCallContext(eventListerCancellationSource.Token);
            Task valueChangedTask = beginHandler(new RpcObjectRequest(objectId), valueChangedStreamWriter, callContext);


            var detailedValueChangedStreamWriter = new ServerEventStreamWriter <ValueChangedEventArgs>(10);

            var beginDetailedHandler = binder.GetHandler <GrpcCore.ServerStreamingServerMethod <RpcObjectRequest, ValueChangedEventArgs> >("BeginDetailedValueChanged");
            CancellationTokenSource detailedEventListerCancellationSource = new CancellationTokenSource();
            var  detailedCallContext      = CreateServerCallContext(detailedEventListerCancellationSource.Token);
            Task detailedValueChangedTask = beginDetailedHandler(new RpcObjectRequest(objectId), detailedValueChangedStreamWriter, detailedCallContext);

            await Task.WhenAny(Task.WhenAll(valueChangedStreamWriter.StartedTask, detailedValueChangedStreamWriter.StartedTask), Task.Delay(5000));

            Assert.IsTrue(valueChangedStreamWriter.StartedTask.IsCompletedSuccessfully());
            Assert.IsTrue(detailedValueChangedStreamWriter.StartedTask.IsCompletedSuccessfully());


            Task.Run(async() =>
            {
                List <Task> tasks = new List <Task>();
                for (int i = 0; i < 20; i++)
                {
                    tasks.Add(serviceImpl.SetValueAsync(18 + i));
                }
                await Task.WhenAll(tasks);
            }
                     ).Forget();


            await Task.WhenAny(Task.WhenAll(valueChangedStreamWriter.CompletedTask, detailedValueChangedStreamWriter.CompletedTask), Task.Delay(5000));

            Assert.IsTrue(valueChangedStreamWriter.CompletedTask.IsCompletedSuccessfully());
            Assert.IsTrue(detailedValueChangedStreamWriter.CompletedTask.IsCompletedSuccessfully());

            eventListerCancellationSource.Cancel();
            detailedEventListerCancellationSource.Cancel();

            //var endProducerHandler = binder.GetHandler<GrpcCore.UnaryServerMethod<RpcObjectEventRequest, RpcResponse>>(nameof(RpcStub<object>.EndEventProducer));

            //var endTask = endProducerHandler(new RpcObjectEventRequest(objectId, eventProducerId), callContext);
            //var endDetailedTask = endProducerHandler(new RpcObjectEventRequest(objectId, detailedEventProducerId), callContext);
            //await Task.WhenAll(endTask, endDetailedTask);
            try
            {
                await Task.WhenAll(valueChangedTask, detailedValueChangedTask);
            }
            catch (OperationCanceledException) { }

            Assert.IsTrue(valueChangedTask.IsCompletedSuccessfully() || valueChangedTask.IsCanceled);
            Assert.IsTrue(detailedValueChangedTask.IsCompletedSuccessfully() || detailedValueChangedTask.IsCanceled);

            Assert.GreaterOrEqual(valueChangedStreamWriter.GetMessages().Length, 10);
            // Too timing dependent
            //Assert.Less(valueChangedStreamWriter.GetMessages().Length, 20);

            var detailedMessages = detailedValueChangedStreamWriter.GetMessages();

            Assert.GreaterOrEqual(detailedMessages.Length, 10);
            // Too timing dependent
            //Assert.Less(detailedValueChangedStreamWriter.GetMessages().Length, 20);

            int oldValue = 0;
            int newValue = 18;

            for (int i = 0; i < 10; i++)
            {
                var msg = detailedMessages[i];
                Assert.AreEqual(oldValue, msg.OldValue);
                Assert.AreEqual(newValue, msg.NewValue);
                oldValue = msg.NewValue;
                newValue = oldValue + 1;
            }
        }
Exemple #14
0
        public async Task SimpleServiceServerTest()
        {
            Pipe requestPipe  = new Pipe();
            Pipe responsePipe = new Pipe();

            var serializer              = new ProtobufRpcSerializer();
            var serviceImpl             = new TestBlockingSimpleServiceImpl();
            var hostMock                = new Mock <IRpcServerCore>();
            var serviceImplProviderMock = new Mock <IRpcServiceActivator>();

            serviceImplProviderMock.Setup(p => p.GetActivatedService <ISimpleService>(It.IsAny <IServiceProvider>(), It.IsAny <RpcObjectId>())).Returns(new ActivatedService <ISimpleService>(serviceImpl, null));

            hostMock.Setup(p => p.ServiceActivator).Returns(serviceImplProviderMock.Object);
            hostMock.Setup(p => p.CallInterceptors).Returns(ImmutableArrayList <RpcServerCallInterceptor> .Empty);

            var serviceRegistrator = new RpcServiceDefinitionsBuilder();

            serviceRegistrator.RegisterService <ISimpleService>();

            _ = RpcServerId.NewId();
            using (var host = new LightweightRpcServer(Mock.Of <IRpcServicePublisher>(), serviceImplProviderMock.Object, serviceRegistrator, null, new RpcServerOptions {
                Serializer = serializer
            }))
            {
                host.AddEndPoint(new InprocRpcEndPoint(new DirectDuplexPipe(requestPipe.Reader, responsePipe.Writer)));

                host.Start();

                var objectId = RpcObjectId.NewId();

                var requestFrame = new LightweightRpcFrame(RpcFrameType.UnaryRequest, 1, "SciTech.Rpc.Tests.SimpleService.Add", ImmutableArray <KeyValuePair <string, ImmutableArray <byte> > > .Empty);

                using (var frameWriter = new BufferWriterStreamImpl())
                {
                    var writeState = requestFrame.BeginWrite(frameWriter);

                    var request = new RpcObjectRequest <int, int>(objectId, 5, 6);
                    serializer.Serialize(frameWriter, request, request.GetType());
                    int frameLength = checked ((int)frameWriter.Length);

                    LightweightRpcFrame.EndWrite(frameLength, writeState);

                    frameWriter.CopyTo(requestPipe.Writer);
                }

                await requestPipe.Writer.FlushAsync();

                RpcResponse <int> response = null;
                while (response == null)
                {
                    var readResult = await responsePipe.Reader.ReadAsync();

                    if (!readResult.IsCanceled)
                    {
                        var buffer = readResult.Buffer;
                        if (LightweightRpcFrame.TryRead(ref buffer, LightweightRpcFrame.DefaultMaxFrameLength, out var responseFrame) == RpcFrameState.Full)
                        {
                            Assert.AreEqual(requestFrame.RpcOperation, responseFrame.RpcOperation);
                            Assert.AreEqual(requestFrame.MessageNumber, responseFrame.MessageNumber);

                            response = (RpcResponse <int>)serializer.Deserialize(responseFrame.Payload, typeof(RpcResponse <int>));

                            responsePipe.Reader.AdvanceTo(buffer.Start);
                        }
                        else
                        {
                            if (readResult.IsCompleted)
                            {
                                break;
                            }

                            responsePipe.Reader.AdvanceTo(buffer.Start, buffer.End);
                        }
                    }
Exemple #15
0
        public void RefObjOfTypeToRefObjTest()
        {
            var ms = new MemoryStream();

            ToStream(ms, false, new RpcObjectRef <ISimpleService>(new RpcConnectionInfo("Test", null, RpcServerId.NewId()), RpcObjectId.NewId(), null));
            string text = Encoding.UTF8.GetString(ms.GetBuffer());

            var ms2 = new MemoryStream();

            ToStream(ms2, true, new RpcObjectRef <ISimpleService>(new RpcConnectionInfo("Test", null, RpcServerId.NewId()), RpcObjectId.NewId(), null));

            ms.Seek(0, SeekOrigin.Begin);
            var ref1 = FromStream(typeof(RpcObjectRef <IBlockingService>), false, ms);

            ms2.Seek(0, SeekOrigin.Begin);
            var ref2 = FromStream(typeof(RpcObjectRef <IBlockingService>), true, ms2);


            Assert.IsTrue(text.Length > 0);
        }