public void Stop()
        {
            var sequence = new TestSequence();

            sequence.ExpectConnect(null, StreamInitializationCause.WatchStarting);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            sequence.WaitForCancellation();

            Task task = sequence.RunToStability();

            sequence.WatchStream.Stop(CancellationToken.None);
            task.Wait();
            sequence.Verify();
        }
        public void InitialTokenCancellation_WhileStateMachineHanging()
        {
            var tokenSource = new CancellationTokenSource();
            var sequence    = new TestSequence(tokenSource.Token);

            sequence.ExpectConnect(null, StreamInitializationCause.WatchStarting);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            sequence.ProvideResponseHangingInStateMachine();

            Task task = sequence.RunToStability();

            tokenSource.Cancel();
            AssertTaskIsCancelledSoon(task);
            sequence.Verify();
        }
        public void NonRetriableRpcException()
        {
            ByteString token1   = ByteString.CopyFromUtf8("token1");
            ByteString token2   = ByteString.CopyFromUtf8("token2");
            var        sequence = new TestSequence();

            sequence.ExpectConnect(null, StreamInitializationCause.WatchStarting);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            sequence.ProvideResponse(WatchResponseResult.StreamHealthy, token1);
            sequence.ProvideResponse(WatchResponseResult.StreamHealthy, token2);
            // This exception is not retriable.
            var exception = new RpcException(new Status(StatusCode.InvalidArgument, "This exception is permanent"));

            sequence.RpcException(exception);

            Task task = sequence.RunToStability();

            Assert.Equal(TaskStatus.Faulted, task.Status);
            Assert.Equal(exception, task.Exception.InnerException);
            sequence.Verify();
        }
        public void StreamComplete()
        {
            ByteString token1   = ByteString.CopyFromUtf8("token1");
            ByteString token2   = ByteString.CopyFromUtf8("token2");
            var        sequence = new TestSequence();

            sequence.ExpectConnect(null, StreamInitializationCause.WatchStarting);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            sequence.ProvideResponse(WatchResponseResult.StreamHealthy, token1);
            sequence.ProvideResponse(WatchResponseResult.StreamHealthy, token2);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            // The stream ended. Restart with the last token.
            sequence.ExpectConnect(token2, StreamInitializationCause.StreamCompleted);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            sequence.WaitForCancellation();

            Task task = sequence.RunToStability();

            sequence.WatchStream.Stop(CancellationToken.None);
            task.Wait();
            sequence.Verify();
        }
        public void StreamReset()
        {
            ByteString token    = ByteString.CopyFromUtf8("token");
            var        sequence = new TestSequence();

            sequence.ExpectConnect(null, StreamInitializationCause.WatchStarting);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            sequence.ProvideResponse(WatchResponseResult.ResetStream);
            // First reset doesn't get a token
            sequence.ExpectConnect(null, StreamInitializationCause.ResetRequested);
            sequence.ProvideResponse(WatchResponseResult.StreamHealthy, token);
            sequence.ProvideResponse(WatchResponseResult.ResetStream);
            // Second reset does
            sequence.ExpectConnect(token, StreamInitializationCause.ResetRequested);
            sequence.WaitForCancellation();

            Task task = sequence.RunToStability();

            sequence.WatchStream.Stop(CancellationToken.None);
            task.Wait();
            sequence.Verify();
        }
        public void RetriableRpcException()
        {
            ByteString token1   = ByteString.CopyFromUtf8("token1");
            ByteString token2   = ByteString.CopyFromUtf8("token2");
            var        sequence = new TestSequence();

            sequence.ExpectConnect(null, StreamInitializationCause.WatchStarting);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            sequence.ProvideResponse(WatchResponseResult.StreamHealthy, token1);
            sequence.ProvideResponse(WatchResponseResult.StreamHealthy, token2);
            sequence.RpcException(new RpcException(new Status(StatusCode.DeadlineExceeded, "This exception is transient")));
            // The server threw a retriable exception. Reinitialize.
            sequence.ExpectConnect(token2, StreamInitializationCause.RpcError);
            sequence.ProvideResponse(WatchResponseResult.Continue);
            sequence.WaitForCancellation();

            Task task = sequence.RunToStability();

            sequence.WatchStream.Stop(CancellationToken.None);
            task.Wait();
            sequence.Verify();
        }