public async Task Watch_ExceedMaximumCapacitySize_DiscardOldValues() { var cts = new CancellationTokenSource(); var context = new TestServerCallContext(cts.Token); var writer = new TestResponseStreamWriter(started: false); var impl = new HealthServiceImpl(); var callTask = impl.Watch(new HealthCheckRequest { Service = "" }, writer, context); // Write new statuses. Only last statuses will be returned when we read them from watch writer for (var i = 0; i < HealthServiceImpl.MaxStatusBufferSize * 2; i++) { // These statuses aren't "valid" but it is useful for testing to have an incrementing number impl.SetStatus("", (HealthCheckResponse.Types.ServingStatus)i + 10); } // Start reading responses now that statuses have been queued up // This is to keep the test non-flakey writer.Start(); // Read messages in a background task var statuses = new List <HealthCheckResponse.Types.ServingStatus>(); var readStatusesTask = Task.Run(async() => { while (await writer.WrittenMessagesReader.WaitToReadAsync()) { if (writer.WrittenMessagesReader.TryRead(out var response)) { statuses.Add(response.Status); } } }); // Tell server we're done watching and it can write what it has left and then exit cts.Cancel(); await callTask; // Ensure we've read all the queued statuses writer.Complete(); await readStatusesTask; // Collection will contain initial written message (ServiceUnknown) plus 5 queued messages Assert.AreEqual(HealthServiceImpl.MaxStatusBufferSize + 1, statuses.Count); // Initial written message Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, statuses[0]); // Last 5 queued messages Assert.AreEqual((HealthCheckResponse.Types.ServingStatus) 15, statuses[statuses.Count - 5]); Assert.AreEqual((HealthCheckResponse.Types.ServingStatus) 16, statuses[statuses.Count - 4]); Assert.AreEqual((HealthCheckResponse.Types.ServingStatus) 17, statuses[statuses.Count - 3]); Assert.AreEqual((HealthCheckResponse.Types.ServingStatus) 18, statuses[statuses.Count - 2]); Assert.AreEqual((HealthCheckResponse.Types.ServingStatus) 19, statuses[statuses.Count - 1]); }
public async Task Watch() { var cts = new CancellationTokenSource(); var context = new TestServerCallContext(cts.Token); var writer = new TestResponseStreamWriter(); var impl = new HealthServiceImpl(); var callTask = impl.Watch(new HealthCheckRequest { Service = "" }, writer, context); // Calling Watch on a service that doesn't have a value set will initially return ServiceUnknown var nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask).Status); nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Serving); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, (await nextWriteTask).Status); nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.NotServing); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NotServing, (await nextWriteTask).Status); nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); impl.SetStatus("", HealthCheckResponse.Types.ServingStatus.Unknown); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Unknown, (await nextWriteTask).Status); // Setting status for a different service name will not update Watch results nextWriteTask = writer.WrittenMessagesReader.ReadAsync(); impl.SetStatus("grpc.test.TestService", HealthCheckResponse.Types.ServingStatus.Serving); Assert.IsFalse(nextWriteTask.IsCompleted); impl.ClearStatus(""); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask).Status); Assert.IsFalse(callTask.IsCompleted); cts.Cancel(); await callTask; }
public async Task Watch_MultipleWatchesForDifferentServices() { var cts = new CancellationTokenSource(); var context = new TestServerCallContext(cts.Token); var writer1 = new TestResponseStreamWriter(); var writer2 = new TestResponseStreamWriter(); var impl = new HealthServiceImpl(); var callTask1 = impl.Watch(new HealthCheckRequest { Service = "One" }, writer1, context); var callTask2 = impl.Watch(new HealthCheckRequest { Service = "Two" }, writer2, context); // Calling Watch on a service that doesn't have a value set will initially return ServiceUnknown var nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); var nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask1).Status); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask2).Status); nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); impl.SetStatus("One", HealthCheckResponse.Types.ServingStatus.Serving); impl.SetStatus("Two", HealthCheckResponse.Types.ServingStatus.NotServing); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.Serving, (await nextWriteTask1).Status); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.NotServing, (await nextWriteTask2).Status); nextWriteTask1 = writer1.WrittenMessagesReader.ReadAsync(); nextWriteTask2 = writer2.WrittenMessagesReader.ReadAsync(); impl.ClearAll(); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask1).Status); Assert.AreEqual(HealthCheckResponse.Types.ServingStatus.ServiceUnknown, (await nextWriteTask2).Status); cts.Cancel(); await callTask1; await callTask2; }