diff --git a/clientv3/integration/watch_test.go b/clientv3/integration/watch_test.go index 3482f31bdf02..bf751d6793ba 100644 --- a/clientv3/integration/watch_test.go +++ b/clientv3/integration/watch_test.go @@ -1133,3 +1133,24 @@ func TestWatchCancelDisconnected(t *testing.T) { t.Fatal("took too long to cancel disconnected watcher") } } + +// TestWatchClose ensures that close does not return error +func TestWatchClose(t *testing.T) { + runWatchTest(t, testWatchClose) +} + +func testWatchClose(t *testing.T, wctx *watchctx) { + ctx, cancel := context.WithCancel(context.Background()) + wch := wctx.w.Watch(ctx, "a") + cancel() + if wch == nil { + t.Fatalf("expected watcher channel, got nil") + } + if wctx.w.Close() != nil { + t.Fatalf("watch did not close successfully") + } + wresp, ok := <-wch + if ok { + t.Fatalf("read wch got %v; expected closed channel", wresp) + } +} diff --git a/clientv3/watch.go b/clientv3/watch.go index 8ec58bb14695..671aeb63db70 100644 --- a/clientv3/watch.go +++ b/clientv3/watch.go @@ -371,6 +371,10 @@ func (w *watcher) Close() (err error) { err = werr } } + // Take context.Canceled as a successul close + if err == context.Canceled { + err = nil + } return err }