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);
        }
        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));
            }
        }
Beispiel #3
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();
                }
            }
        }
        public async Task EmptyDerivedProxyTest()
        {
            var(serviceInstance, callInvokerMock) = CreateServiceInstance <IEmptyDerivedService>();

            RpcObjectId objectId = ((IRpcProxy)serviceInstance).ObjectId;

            // Test Add and Sub, defined on different interfaces
            callInvokerMock.Setup(p => p.UnaryFunc <RpcObjectRequest <int, int>, RpcResponse <int> >("Add", It.IsAny <RpcObjectRequest <int, int> >()))
            .Returns((string op, RpcObjectRequest <int, int> r) =>
            {
                Assert.AreEqual(objectId, r.Id);
                return(new RpcResponse <int> {
                    Result = r.Value1 + r.Value2
                });
            });

            var addRes = await serviceInstance.AddAsync(18, 19);

            Assert.AreEqual(18 + 19, addRes);

            callInvokerMock.Setup(p => p.UnaryFunc <RpcObjectRequest <int, int>, RpcResponse <int> >("Sub", It.IsAny <RpcObjectRequest <int, int> >()))
            .Returns((string op, RpcObjectRequest <int, int> r) =>
            {
                Assert.AreEqual(objectId, r.Id);
                return(new RpcResponse <int> {
                    Result = r.Value1 - r.Value2
                });
            });

            var subRes = await serviceInstance.SubAsync(1218, 119);

            Assert.AreEqual(1218 - 119, subRes);
        }
Beispiel #5
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);
        }
Beispiel #6
0
        public static void UnpublishInstance(this IRpcServer server, RpcObjectId serviceInstanceId)
        {
            if (server is null)
            {
                throw new ArgumentNullException(nameof(server));
            }

            server.ServicePublisher.UnpublishInstance(serviceInstanceId);
        }
        public static void UnpublishInstance(this IRpcServicePublisher publisher, RpcObjectId serviceInstanceId)
        {
            if (publisher is null)
            {
                throw new ArgumentNullException(nameof(publisher));
            }

            publisher.UnpublishInstanceAsync(serviceInstanceId).AsTask().AwaiterResult();
        }
Beispiel #8
0
 public RpcProxyArgs(
     IRpcChannel connection, RpcObjectId objectId, IRpcSerializer serializer,
     IReadOnlyCollection <string>?implementedServices,
     SynchronizationContext?syncContext)
 {
     this.Channel             = connection ?? throw new ArgumentNullException(nameof(connection));
     this.ObjectId            = objectId;
     this.Serializer          = serializer;
     this.ImplementedServices = implementedServices;
     this.SyncContext         = syncContext;
 }
Beispiel #9
0
 internal GrpcProxyArgs(IRpcChannel connection,
                        GrpcCore.CallInvoker callInvoker,
                        RpcObjectId objectId,
                        GrpcMethodsCache methodsCache,
                        IRpcSerializer serializer,
                        IReadOnlyCollection <string>?implementedServices,
                        SynchronizationContext?syncContext)
     : base(connection, objectId, serializer, implementedServices, syncContext)
 {
     this.CallInvoker  = callInvoker;
     this.MethodsCache = methodsCache;
 }
Beispiel #10
0
        /// <inheritdoc/>
        public TService GetServiceInstance <TService>(
            RpcObjectId objectId,
            IReadOnlyCollection <string>?implementedServices,
            SynchronizationContext?syncContext) where TService : class
        {
            if (objectId == RpcObjectId.Empty)
            {
                throw new ArgumentException("ObjectId should not be empty.", nameof(objectId));
            }

            return(GetServiceInstanceCore <TService>(objectId, implementedServices, syncContext));
        }
        public ImmutableArray <string> GetPublishedServices(RpcObjectId objectId)
        {
            lock (this.syncRoot)
            {
                if (this.idToPublishedServices.TryGetValue(objectId, out var servicesList))
                {
                    return(servicesList.ServiceNames);
                }

                return(ImmutableArray <string> .Empty);
            }
        }
Beispiel #12
0
        private TService GetServiceInstanceCore <TService>(
            RpcObjectId refObjectId,
            IReadOnlyCollection <string>?implementedServices,
            SynchronizationContext?syncContext) where TService : class
        {
            lock (this.SyncRoot)
            {
                if (this.serviceInstances.TryGetValue(refObjectId, out var servicesList))
                {
                    foreach (var wService in servicesList)
                    {
                        if (wService.TryGetTarget(out var proxyBase) &&
                            proxyBase is TService service &&
                            proxyBase.SyncContext == syncContext &&
                            proxyBase.ImplementsServices(implementedServices))
                        {
                            return(service);
                        }
                    }
                }
            }

            RpcObjectProxyFactory serviceProxyCreator
                = this.proxyGenerator.GenerateObjectProxyFactory <TService>(implementedServices, this.Options.KnownServiceTypesDictionary);

            lock (this.SyncRoot)
            {
                if (this.serviceInstances.TryGetValue(refObjectId, out var servicesList))
                {
                    foreach (var wService in servicesList)
                    {
                        if (wService.TryGetTarget(out var proxyBase) &&
                            proxyBase is TService service &&
                            proxyBase.SyncContext == syncContext &&
                            proxyBase.ImplementsServices(implementedServices))
                        {
                            return(service);
                        }
                    }
                }
                else
                {
                    servicesList = new List <WeakReference <RpcProxyBase> >();
                    this.serviceInstances.Add(refObjectId, servicesList);
                }

                var serviceInstance = serviceProxyCreator(refObjectId, this, syncContext);
                servicesList.Add(new WeakReference <RpcProxyBase>(serviceInstance));

                return((TService)(object)serviceInstance);
            }
        }
Beispiel #13
0
 internal LightweightProxyArgs(
     LightweightRpcConnection connection,
     IReadOnlyList <RpcClientCallInterceptor> callInterceptors,
     RpcObjectId objectId,
     IRpcSerializer serializer,
     LightweightSerializersCache methodSerializersCache,
     IReadOnlyCollection <string>?implementedServices,
     SynchronizationContext?syncContext)
     : base(connection, objectId, serializer, implementedServices, syncContext)
 {
     this.MethodSerializersCache = methodSerializersCache;
     this.CallInterceptors       = callInterceptors;
 }
Beispiel #14
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 SimpleProxyTest()
        {
            var(serviceInstance, callInvokerMock) = CreateServiceInstance <ISimpleService>();

            RpcObjectId objectId = ((IRpcProxy)serviceInstance).ObjectId;

            callInvokerMock.Setup(p => p.UnaryFunc <RpcObjectRequest <int, int>, RpcResponse <int> >("Add", It.IsAny <RpcObjectRequest <int, int> >()))
            .Returns((string op, RpcObjectRequest <int, int> r) =>
            {
                Assert.AreEqual(objectId, r.Id);
                return(new RpcResponse <int> {
                    Result = r.Value1 + r.Value2
                });
            });

            var m  = serviceInstance.GetType().GetMethod("SimpleService.AddAsync", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
            var mb = m.GetMethodBody();
            var il = mb.GetILAsByteArray();

            var res = await serviceInstance.AddAsync(5, 6);

            Assert.AreEqual(11, res);

            callInvokerMock.Setup(p => p.UnaryFunc <RpcObjectRequest <double>, RpcResponse>("SetValue", It.IsAny <RpcObjectRequest <double> >()))
            .Returns((string op, RpcObjectRequest <double> r) =>
            {
                Assert.AreEqual(objectId, r.Id);
                Assert.AreEqual(123.45, r.Value1);
                return(new RpcResponse());
            });

            await serviceInstance.SetValueAsync(123.45);

            callInvokerMock.Setup(p => p.UnaryFunc <RpcObjectRequest, RpcResponse <double> >("GetValue", It.IsAny <RpcObjectRequest>()))
            .Returns((string op, RpcObjectRequest r) =>
            {
                Assert.AreEqual(objectId, r.Id);
                return(new RpcResponse <double> {
                    Result = 543.21
                });
            });

            var getRes = await serviceInstance.GetValueAsync();

            Assert.AreEqual(543.21, getRes);
        }
        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 ValueTask UnpublishInstanceAsync(RpcObjectId serviceInstanceId)
        {
            PublishedInstance?removedInstance = null;

            lock (this.syncRoot)
            {
                if (this.idToPublishedServices.TryGetValue(serviceInstanceId, out var publishedServices))
                {
                    foreach (var serviceType in publishedServices.ServiceTypes)
                    {
                        var serviceKey = new ServiceImplKey(serviceInstanceId, serviceType);
                        if (this.idToServiceImpl.TryGetValue(serviceKey, out var publishedInstance))
                        {
                            this.idToServiceImpl.Remove(serviceKey);
                            if (removedInstance == null)
                            {
                                removedInstance = publishedInstance;
                            }
                            else
                            {
                                Debug.Assert(Equals(removedInstance, publishedInstance));
                            }
                        }

                        this.idToServiceFactory.Remove(serviceKey);
                    }
                }

                if (removedInstance != null)
                {
                    var instance = removedInstance.Value.GetInstance();
                    if (instance != null)
                    {
                        this.serviceImplToId.Remove(new InstanceKey(instance));
                    }
                }
            }

            if (removedInstance?.GetOwnedInstance() is IAsyncDisposable disposable)
            {
                return(disposable.DisposeAsync());
            }

            return(default);
        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 void BlockingProxyTest()
        {
            var(serviceInstance, callInvokerMock) = CreateServiceInstance <IBlockingService>();

            RpcObjectId objectId = ((IRpcProxy)serviceInstance).ObjectId;

            callInvokerMock.Setup(p => p.UnaryFunc <RpcObjectRequest <int, int>, RpcResponse <int> >("Add", It.IsAny <RpcObjectRequest <int, int> >()))
            .Returns((string op, RpcObjectRequest <int, int> r) =>
            {
                Assert.AreEqual(objectId, r.Id);
                return(new RpcResponse <int> {
                    Result = r.Value1 + r.Value2
                });
            });

            var res = serviceInstance.Add(5, 6);

            Assert.AreEqual(11, res);

            callInvokerMock.Setup(p => p.UnaryFunc <RpcObjectRequest <double>, RpcResponse>("SetValue", It.IsAny <RpcObjectRequest <double> >()))
            .Returns((string op, RpcObjectRequest <double> r) =>
            {
                Assert.AreEqual(objectId, r.Id);
                Assert.AreEqual(123.45, r.Value1);
                return(new RpcResponse());
            });

            serviceInstance.Value = 123.45;

            callInvokerMock.Setup(p => p.UnaryFunc <RpcObjectRequest, RpcResponse <double> >("GetValue", It.IsAny <RpcObjectRequest>()))
            .Returns((string op, RpcObjectRequest r) =>
            {
                Assert.AreEqual(objectId, r.Id);
                return(new RpcResponse <double> {
                    Result = 543.21
                });
            });

            var getRes = serviceInstance.Value;

            Assert.AreEqual(543.21, getRes);
        }
        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 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 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 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);
        }
Beispiel #24
0
 internal RpcObjectRef(RpcConnectionInfo?connectionInfo, RpcObjectId objectId, string[]?implementedServices)
 {
     this.ServerConnection    = connectionInfo;
     this.ObjectId            = objectId;
     this.ImplementedServices = implementedServices;
 }
        public async Task EventHandlersTest()
        {
            var(serviceInstance, callInvokerMock) = CreateServiceInstance <ISimpleServiceWithEvents>();

            RpcObjectId objectId = ((IRpcProxy)serviceInstance).ObjectId;

            callInvokerMock.Setup(p => p.ServerStreamingFunc <RpcObjectRequest, EventArgs>(It.IsAny <string>(), It.IsAny <RpcObjectRequest>(), It.IsAny <CancellationToken>()))
            .Returns((string op, RpcObjectRequest r, CancellationToken ct) =>
            {
                Assert.AreEqual(objectId, r.Id);
                return(new AsyncStreamReader <EventArgs>(() => (EventArgs.Empty, true), 0, 20, ct));
            });

            int currValue = 4;

            callInvokerMock.Setup(p => p.ServerStreamingFunc <RpcObjectRequest, ValueChangedEventArgs>(It.IsAny <string>(), It.IsAny <RpcObjectRequest>(), It.IsAny <CancellationToken>()))
            .Returns((string op, RpcObjectRequest r, CancellationToken ct) =>
            {
                Assert.AreEqual(objectId, r.Id);
                return(new AsyncStreamReader <ValueChangedEventArgs>(() =>
                {
                    var oldValue = currValue++;
                    return (new ValueChangedEventArgs(currValue, oldValue), true);
                }, 10, 10, ct));;
            });

            //callInvokerMock.Setup(p => p.UnaryFunc<RpcObjectEventRequest, RpcResponse>("EndEventProducer", It.IsAny<RpcObjectEventRequest>()))
            //    .Returns(()=>new RpcResponse());

            int simpleChangeCount = 0;
            TaskCompletionSource <bool> simpleTcs = new TaskCompletionSource <bool>();
            EventHandler eventHandler             = (s, e) => { simpleChangeCount++; if (simpleChangeCount == 2)
                                                                {
                                                                    simpleTcs.SetResult(true);
                                                                }
            };

            int?expectedOldValue    = null;
            int detailedChangeCount = 0;
            TaskCompletionSource <bool>          detailedTcs          = new TaskCompletionSource <bool>();
            EventHandler <ValueChangedEventArgs> detailedEventHandler = (s, e) =>
            {
                if (expectedOldValue != null)
                {
                    Assert.AreEqual(expectedOldValue.Value, e.OldValue);
                }
                Assert.AreEqual(e.OldValue + 1, e.NewValue);
                expectedOldValue = e.NewValue;
                detailedChangeCount++;
                if (detailedChangeCount == 3)
                {
                    detailedTcs.SetResult(true);
                }
            };

            serviceInstance.ValueChanged += eventHandler;
            await((IRpcProxy)serviceInstance).WaitForPendingEventHandlersAsync();

            serviceInstance.DetailedValueChanged += detailedEventHandler;

            await Task.WhenAny(Task.WhenAll(simpleTcs.Task, detailedTcs.Task), Task.Delay(1000));

            Assert.AreEqual(TaskStatus.RanToCompletion, simpleTcs.Task.Status);
            Assert.AreEqual(TaskStatus.RanToCompletion, detailedTcs.Task.Status);

            serviceInstance.ValueChanged         -= eventHandler;
            serviceInstance.DetailedValueChanged -= detailedEventHandler;

            // TODO: Assert that Remove event method has been called for both handlers.
        }
Beispiel #26
0
        public void IncorrectServiceFault_ShouldThrowDefinitionException()
        {
            var serviceRegistrator = new RpcServiceDefinitionsBuilder();

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

            Assert.Throws <RpcDefinitionException>(() => connection.GetServiceInstance <IIncorrectServiceFaultServiceClient>(RpcObjectId.NewId()));
        }
 public void Clear()
 {
     this.Id = default;
 }
 public RpcObjectRequest(RpcObjectId id)
 {
     this.Id = id;
 }
        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;
            }
        }
Beispiel #30
0
        /// <summary>
        /// Gets a proxy to the service instance specified by <paramref name="objectId"/>.
        /// </summary>
        /// <typeparam name="TService"></typeparam>
        /// <param name="objectId"></param>
        /// <param name="useSyncContext">Indicates that the current synchronization context should be used for the service intance.</param>
        /// <returns>The service proxy.</returns>
        /// <exception cref="RpcDefinitionException">Thrown if the RPC definition of <typeparamref name="TService"/> is not correct.</exception>
        public static TService GetServiceInstance <TService>(this IRpcChannel connection, RpcObjectId objectId, bool useSyncContext = true) where TService : class
        {
            if (connection is null)
            {
                throw new ArgumentNullException(nameof(connection));
            }

            return(connection.GetServiceInstance <TService>(objectId, default, useSyncContext ? SynchronizationContext.Current : null));