public async Task TestAggregateHandlerDefaultRequestType() { var configWatcher = new MockConfigWatcher(true, new Dictionary <string, (string, IEnumerable <IMessage>)>()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher) .ConfigureDiscoveryService <AggregatedDiscoveryService>() .Build(); await server.StartAsync(); var client = new AggregatedDiscoveryServiceClient(CreateGrpcChannel()); var duplex = client.StreamAggregatedResources(); var clientTask = HandleResponses(duplex.ResponseStream); // Leave off the type URL. For ADS requests it should fail because the type URL is required. await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, }); await duplex.RequestStream.CompleteAsync(); var(responseErrors, responses, completed, error) = await clientTask; }
public async Task TestCallbacksOnError() { int streamClosesWithErrors = 0; var callbacks = Substitute.For <IDiscoveryServerCallbacks>(); callbacks .When(x => x.OnStreamCloseWithError(Arg.Any <long>(), Arg.Any <string>(), Arg.Any <Exception>())) .Do(_ => Interlocked.Increment(ref streamClosesWithErrors)); var configWatcher = new MockConfigWatcher(false, CreateResponses()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher, callbacks) .ConfigureDiscoveryService <AggregatedDiscoveryService>() .Build(); await server.StartAsync(); var client = new AggregatedDiscoveryServiceClient(CreateGrpcChannel()); var ctx = new CancellationTokenSource(); var duplex = client.StreamAggregatedResources(cancellationToken: ctx.Token); await duplex.RequestStream.WriteAsync(new DiscoveryRequest()); ctx.Cancel(); WaitUntil(ref streamClosesWithErrors, 1, TimeSpan.FromSeconds(1)); streamClosesWithErrors.Should().Be(1); }
public async Task TestSendError() { var configWatcher = new MockConfigWatcher(false, CreateResponses()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher) .ConfigureDiscoveryService <AggregatedDiscoveryService>() .Build(); await server.StartAsync(); var client = new AggregatedDiscoveryServiceClient(CreateGrpcChannel()); foreach (var typeUrl in Resources.TYPE_URLS) { var duplex = client.StreamAggregatedResources(); var clientTask = HandleResponses(duplex.ResponseStream, sendError: true); await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = typeUrl }); var(responseErrors, responses, completed, error) = await clientTask; completed.Should().BeFalse(); error.Should().BeTrue(); responseErrors.Should().BeEmpty(); } }
public async Task TestWatchClosed() { var configWatcher = new MockConfigWatcher(true, new Dictionary <string, (string, IEnumerable <IMessage>)>()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher) .ConfigureDiscoveryService <AggregatedDiscoveryService>() .Build(); await server.StartAsync(); var client = new AggregatedDiscoveryServiceClient(CreateGrpcChannel()); foreach (var typeUrl in Resources.TYPE_URLS) { // MockDiscoveryResponseObserver responseObserver = new MockDiscoveryResponseObserver(); var ctx = new CancellationTokenSource(); var duplex = client.StreamAggregatedResources(cancellationToken: ctx.Token); var clientTask = HandleResponses(duplex.ResponseStream); await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = typeUrl }); ctx.Cancel(); var(responseErrors, responses, completed, error) = await clientTask; error.Should().BeTrue(); completed.Should().BeFalse(); responseErrors.Should().BeEmpty(); } }
public async Task TestStaleNonce() { var configWatcher = new MockConfigWatcher(false, CreateResponses()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher) .ConfigureDiscoveryService <AggregatedDiscoveryService>() .Build(); await server.StartAsync(); var client = new AggregatedDiscoveryServiceClient(CreateGrpcChannel()); foreach (var typeUrl in Resources.TYPE_URLS) { var duplex = client.StreamAggregatedResources(); var clientTask = HandleResponses(duplex.ResponseStream); await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = typeUrl, }); // Stale request, should not create a new watch. await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = typeUrl, ResponseNonce = "xyz" }); // Fresh request, should create a new watch. await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = typeUrl, ResponseNonce = "1", VersionInfo = "0" }); await duplex.RequestStream.CompleteAsync(); var(responseErrors, responses, completed, error) = await clientTask; // Assert that 2 watches have been created for this resource type. configWatcher.counts[typeUrl].Should().Be(2); } }
public async Task TestAggregatedHandler() { var configWatcher = new MockConfigWatcher(false, CreateResponses()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher) .ConfigureDiscoveryService <AggregatedDiscoveryService>() .Build(); await server.StartAsync(); var client = new AggregatedDiscoveryServiceClient(CreateGrpcChannel()); var duplex = client.StreamAggregatedResources(); var clientTask = Task.Run(async() => await HandleResponses(duplex.ResponseStream)); await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = Resources.LISTENER_TYPE_URL }); await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = Resources.CLUSTER_TYPE_URL, }); var clusterRequest = new DiscoveryRequest { Node = NODE, TypeUrl = Resources.ENDPOINT_TYPE_URL, }; clusterRequest.ResourceNames.Add(CLUSTER_NAME); await duplex.RequestStream.WriteAsync(clusterRequest); var routeRequest = new DiscoveryRequest { Node = NODE, TypeUrl = Resources.ROUTE_TYPE_URL, }; routeRequest.ResourceNames.Add(ROUTE_NAME); await duplex.RequestStream.WriteAsync(routeRequest); var secretRequest = new DiscoveryRequest { Node = NODE, TypeUrl = Resources.SECRET_TYPE_URL, }; secretRequest.ResourceNames.Add(SECRET_NAME); await duplex.RequestStream.WriteAsync(secretRequest); await duplex.RequestStream.CompleteAsync(); var(responseErrors, responses, completed, error) = await clientTask; completed.Should().BeTrue(); error.Should().BeFalse(); responseErrors.Should().BeEmpty(); foreach (var typeUrl in Resources.TYPE_URLS) { configWatcher.counts.Should().Contain(typeUrl, 1); } configWatcher.counts.Should().HaveCount(Resources.TYPE_URLS.Count()); foreach (var typeUrl in Resources.TYPE_URLS) { responses.Should().Contain(r => r.TypeUrl == typeUrl && r.VersionInfo == VERSION, "missing expected response of type %s", typeUrl); } }
public async Task TestCallbacksAggregateHandler() { var assertionErrors = new List <string>(); int streamCloses = 0, streamOpens = 0, streamRequests = 0, streamResponses = 0; var callbacks = Substitute.For <IDiscoveryServerCallbacks>(); void ValidateTypeUrl(string typeUrl, string caller) { if (typeUrl != Resources.ANY_TYPE_URL) { assertionErrors.Add($"{caller}#typeUrl => expected {Resources.ANY_TYPE_URL}, got {typeUrl}"); } } callbacks .When(x => x.OnStreamClose(Arg.Any <long>(), Arg.Any <string>())) .Do(args => { ValidateTypeUrl(args.ArgAt <string>(1), "OnStreamClose"); Interlocked.Increment(ref streamCloses); }); callbacks .When(x => x.OnStreamOpen(Arg.Any <long>(), Arg.Any <string>())) .Do(args => { ValidateTypeUrl(args.ArgAt <string>(1), "OnStreamOpen"); Interlocked.Increment(ref streamOpens); }); callbacks .When(x => x.OnStreamRequest(Arg.Any <long>(), Arg.Any <DiscoveryRequest>())) .Do(_ => Interlocked.Increment(ref streamRequests)); callbacks .When(x => x.OnStreamResponse(Arg.Any <long>(), Arg.Any <DiscoveryRequest>(), Arg.Any <DiscoveryResponse>())) .Do(_ => Interlocked.Increment(ref streamResponses)); var configWatcher = new MockConfigWatcher(false, CreateResponses()); using var server = DiscoveryServerBuilder .CreateFor(configWatcher, callbacks) .ConfigureDiscoveryService <AggregatedDiscoveryService>() .Build(); await server.StartAsync(); var client = new AggregatedDiscoveryServiceClient(CreateGrpcChannel()); var duplex = client.StreamAggregatedResources(); var clientTask = HandleResponses(duplex.ResponseStream); await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = Resources.LISTENER_TYPE_URL }); WaitUntil(ref streamOpens, 1); streamOpens.Should().Be(1); await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, TypeUrl = Resources.CLUSTER_TYPE_URL }); var cluster = new DiscoveryRequest { Node = NODE, TypeUrl = Resources.ENDPOINT_TYPE_URL, }; cluster.ResourceNames.Add(CLUSTER_NAME); await duplex.RequestStream.WriteAsync(cluster); var route = new DiscoveryRequest { Node = NODE, TypeUrl = Resources.ROUTE_TYPE_URL }; route.ResourceNames.Add(ROUTE_NAME); await duplex.RequestStream.WriteAsync(route); var secret = new DiscoveryRequest { Node = NODE, TypeUrl = Resources.SECRET_TYPE_URL, }; secret.ResourceNames.Add(SECRET_NAME); await duplex.RequestStream.WriteAsync(secret); WaitUntil(ref streamRequests, Resources.TYPE_URLS.Count()); streamRequests.Should().Be(Resources.TYPE_URLS.Count()); WaitUntil(ref streamRequests, Resources.TYPE_URLS.Count()); streamResponses.Should().Be(Resources.TYPE_URLS.Count()); // Send another round of requests. These should not trigger any responses. streamResponses = 0; streamRequests = 0; await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, ResponseNonce = "0", VersionInfo = VERSION, TypeUrl = Resources.LISTENER_TYPE_URL }); await duplex.RequestStream.WriteAsync(new DiscoveryRequest { Node = NODE, ResponseNonce = "1", TypeUrl = Resources.CLUSTER_TYPE_URL, VersionInfo = VERSION, }); var cluster2 = new DiscoveryRequest { Node = NODE, ResponseNonce = "2", TypeUrl = Resources.ENDPOINT_TYPE_URL, VersionInfo = VERSION }; cluster2.ResourceNames.Add(CLUSTER_NAME); await duplex.RequestStream.WriteAsync(cluster2); var route2 = new DiscoveryRequest { Node = NODE, ResponseNonce = "3", TypeUrl = Resources.ROUTE_TYPE_URL, VersionInfo = VERSION }; route2.ResourceNames.Add(ROUTE_NAME); await duplex.RequestStream.WriteAsync(route2); var secert2 = new DiscoveryRequest { Node = NODE, ResponseNonce = "4", TypeUrl = Resources.SECRET_TYPE_URL, VersionInfo = VERSION, }; secert2.ResourceNames.Add(SECRET_NAME); await duplex.RequestStream.WriteAsync(secert2); WaitUntil(ref streamRequests, Resources.TYPE_URLS.Count()); streamRequests.Should().Be(Resources.TYPE_URLS.Count()); streamResponses.Should().Be(0); await duplex.RequestStream.CompleteAsync(); WaitUntil(ref streamCloses, 1); streamCloses.Should().Be(1); assertionErrors.Should().BeEmpty(); }