public async Task TestSeparateHandlersDefaultRequestType() { var configWatcher = new MockConfigWatcher(false, CreateResponses()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher) .ConfigureDiscoveryService <ClusterDiscoveryService>() .ConfigureDiscoveryService <EndpointDiscoveryService>() .ConfigureDiscoveryService <ListenerDiscoveryService>() .ConfigureDiscoveryService <RouteDiscoveryService>() .ConfigureDiscoveryService <SecretDiscoveryService>() .Build(); await server.StartAsync(); var channel = CreateGrpcChannel(); var clusterClient = new ClusterDiscoveryServiceClient(channel); var endpointClient = new EndpointDiscoveryServiceClient(channel); var listenerClient = new ListenerDiscoveryServiceClient(channel); var routeClient = new RouteDiscoveryServiceClient(channel); var secretClient = new SecretDiscoveryServiceClient(channel); foreach (var typeUrl in Resources.TYPE_URLS) { Task <(List <string>, List <DiscoveryResponse>, bool, bool)> clientTask = null; AsyncDuplexStreamingCall <DiscoveryRequest, DiscoveryResponse> duplex = null; switch (typeUrl) { case Resources.CLUSTER_TYPE_URL: duplex = clusterClient.StreamClusters(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.ENDPOINT_TYPE_URL: duplex = endpointClient.StreamEndpoints(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.LISTENER_TYPE_URL: duplex = listenerClient.StreamListeners(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.ROUTE_TYPE_URL: duplex = routeClient.StreamRoutes(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.SECRET_TYPE_URL: duplex = secretClient.StreamSecrets(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; default: Assert.True(false, "Unsupported resource type: " + typeUrl); break; } // Leave off the type URL. For xDS requests it should default to the value for that handler's type. var discoveryRequest = new DiscoveryRequest { Node = NODE, }; await duplex.RequestStream.WriteAsync(discoveryRequest); await duplex.RequestStream.CompleteAsync(); var(responseErrors, _, _, _) = await clientTask; responseErrors.Should().BeEmpty(); } }
public async Task TestCallbacksSeparateHandlers() { var streamCloses = new ConcurrentDictionary <string, StrongBox <int> >(); var streamOpens = new ConcurrentDictionary <string, StrongBox <int> >(); var streamRequests = new ConcurrentDictionary <string, StrongBox <int> >(); var streamResponses = new ConcurrentDictionary <string, StrongBox <int> >(); Resources.TYPE_URLS.ForEach(typeUrl => { streamCloses[typeUrl] = new StrongBox <int>(0); streamOpens[typeUrl] = new StrongBox <int>(0); streamRequests[typeUrl] = new StrongBox <int>(0); streamResponses[typeUrl] = new StrongBox <int>(0); }); var assertionErrors = new List <string>(); var callbacks = Substitute.For <IDiscoveryServerCallbacks>(); void ValidateTypeUrl(string typeUrl, string caller) { if (!Resources.TYPE_URLS.Contains(typeUrl)) { assertionErrors.Add($"{caller}#typeUrl => expected {Resources.ANY_TYPE_URL}, got {typeUrl}"); } } callbacks .When(x => x.OnStreamClose(Arg.Any <long>(), Arg.Any <string>())) .Do(args => { var typeUrl = args.ArgAt <string>(1); ValidateTypeUrl(typeUrl, "OnStreamClose"); Interlocked.Increment(ref streamCloses[typeUrl].Value); }); callbacks .When(x => x.OnStreamOpen(Arg.Any <long>(), Arg.Any <string>())) .Do(args => { var typeUrl = args.ArgAt <string>(1); ValidateTypeUrl(typeUrl, "OnStreamOpen"); Interlocked.Increment(ref streamOpens[typeUrl].Value); }); callbacks .When(x => x.OnStreamRequest(Arg.Any <long>(), Arg.Any <DiscoveryRequest>())) .Do(args => Interlocked.Increment(ref streamRequests[args.ArgAt <DiscoveryRequest>(1).TypeUrl].Value)); callbacks .When(x => x.OnStreamResponse(Arg.Any <long>(), Arg.Any <DiscoveryRequest>(), Arg.Any <DiscoveryResponse>())) .Do(args => Interlocked.Increment(ref streamResponses[args.ArgAt <DiscoveryRequest>(1).TypeUrl].Value)); var configWatcher = new MockConfigWatcher(false, CreateResponses()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher, callbacks) .ConfigureDiscoveryService <ClusterDiscoveryService>() .ConfigureDiscoveryService <EndpointDiscoveryService>() .ConfigureDiscoveryService <ListenerDiscoveryService>() .ConfigureDiscoveryService <RouteDiscoveryService>() .ConfigureDiscoveryService <SecretDiscoveryService>() .Build(); await server.StartAsync(); var channel = CreateGrpcChannel(); var clusterClient = new ClusterDiscoveryServiceClient(channel); var endpointClient = new EndpointDiscoveryServiceClient(channel); var listenerClient = new ListenerDiscoveryServiceClient(channel); var routeClient = new RouteDiscoveryServiceClient(channel); var secretClient = new SecretDiscoveryServiceClient(channel); foreach (var typeUrl in Resources.TYPE_URLS) { Task <(List <string>, List <DiscoveryResponse>, bool, bool)> clientTask = null; AsyncDuplexStreamingCall <DiscoveryRequest, DiscoveryResponse> duplex = null; switch (typeUrl) { case Resources.CLUSTER_TYPE_URL: duplex = clusterClient.StreamClusters(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.ENDPOINT_TYPE_URL: duplex = endpointClient.StreamEndpoints(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.LISTENER_TYPE_URL: duplex = listenerClient.StreamListeners(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.ROUTE_TYPE_URL: duplex = routeClient.StreamRoutes(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.SECRET_TYPE_URL: duplex = secretClient.StreamSecrets(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; default: Assert.True(false, "Unsupported resource type: " + typeUrl); break; } var discoveryRequest = new DiscoveryRequest { Node = NODE, TypeUrl = typeUrl }; await duplex.RequestStream.WriteAsync(discoveryRequest); WaitUntil(ref streamOpens[typeUrl].Value, 1); streamOpens[typeUrl].Value.Should().Be(1); WaitUntil(ref streamRequests[typeUrl].Value, 1); streamRequests[typeUrl].Value.Should().Be(1); await duplex.RequestStream.CompleteAsync(); WaitUntil(ref streamResponses[typeUrl].Value, 1); streamResponses[typeUrl].Value.Should().Be(1); WaitUntil(ref streamCloses[typeUrl].Value, 1); streamCloses[typeUrl].Value.Should().Be(1); } assertionErrors.Should().BeEmpty(); }
public async Task TestSeparateHandlers() { var configWatcher = new MockConfigWatcher(false, CreateResponses()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher) .ConfigureDiscoveryService <ClusterDiscoveryService>() .ConfigureDiscoveryService <EndpointDiscoveryService>() .ConfigureDiscoveryService <ListenerDiscoveryService>() .ConfigureDiscoveryService <RouteDiscoveryService>() .ConfigureDiscoveryService <SecretDiscoveryService>() .Build(); await server.StartAsync(); var channel = CreateGrpcChannel(); var clusterClient = new ClusterDiscoveryServiceClient(channel); var endpointClient = new EndpointDiscoveryServiceClient(channel); var listenerClient = new ListenerDiscoveryServiceClient(channel); var routeClient = new RouteDiscoveryServiceClient(channel); var secretClient = new SecretDiscoveryServiceClient(channel); foreach (var typeUrl in Resources.TYPE_URLS) { var discoveryRequest = new DiscoveryRequest { Node = NODE, TypeUrl = typeUrl }; Task <(List <string>, List <DiscoveryResponse>, bool, bool)> clientTask = null; AsyncDuplexStreamingCall <DiscoveryRequest, DiscoveryResponse> duplex = null; switch (typeUrl) { case Resources.CLUSTER_TYPE_URL: duplex = clusterClient.StreamClusters(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.ENDPOINT_TYPE_URL: duplex = endpointClient.StreamEndpoints(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); discoveryRequest.ResourceNames.Add(CLUSTER_NAME); break; case Resources.LISTENER_TYPE_URL: duplex = listenerClient.StreamListeners(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); break; case Resources.ROUTE_TYPE_URL: duplex = routeClient.StreamRoutes(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); discoveryRequest.ResourceNames.Add(ROUTE_NAME); break; case Resources.SECRET_TYPE_URL: duplex = secretClient.StreamSecrets(); clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); discoveryRequest.ResourceNames.Add(SECRET_NAME); break; default: Assert.True(false, "Unsupported resource type: " + typeUrl); break; } await duplex.RequestStream.WriteAsync(discoveryRequest); await duplex.RequestStream.CompleteAsync(); var(responseErrors, responses, completed, error) = await clientTask; completed.Should().BeTrue(); error.Should().BeFalse(); responseErrors.Should().BeEmpty(); configWatcher.counts.Should().Contain(typeUrl, 1); responses.Should().Contain( r => r.TypeUrl == typeUrl && r.VersionInfo == VERSION, "missing expected response of type %s", typeUrl); } configWatcher.counts.Should().HaveCount(Resources.TYPE_URLS.Count()); }