Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(245)

Side by Side Diff: common/clock/clockcontext_test.go

Issue 1679023005: Add Context cancellation to clock. (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: Actually upload the patch. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « common/clock/clockcontext.go ('k') | common/clock/external.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package clock 5 package clock
6 6
7 import ( 7 import (
8 "testing" 8 "testing"
9 "time" 9 "time"
10 10
11 . "github.com/smartystreets/goconvey/convey" 11 . "github.com/smartystreets/goconvey/convey"
12 "golang.org/x/net/context" 12 "golang.org/x/net/context"
13 ) 13 )
14 14
15 // A test blocking operation. 15 // manualClock is a partial Clock implementation that allows us to release
16 func blockingOperation(ctx context.Context, releaseC chan struct{}) (bool, error ) { 16 // blocking calls.
17 » select { 17 type manualClock struct {
18 » case <-ctx.Done(): 18 » Clock
19 » » return false, ctx.Err()
20 19
21 » case <-releaseC: 20 » now time.Time
22 » » return true, nil 21 » timeoutCallback func(time.Duration) bool
23 » } 22 » testFinishedC chan struct{}
23 }
24
25 func (mc *manualClock) Now() time.Time {
26 » return mc.now
27 }
28
29 func (mc *manualClock) After(ctx context.Context, d time.Duration) <-chan TimerR esult {
30 » resultC := make(chan TimerResult)
31 » go func() {
32 » » ar := TimerResult{}
33 » » defer func() {
34 » » » resultC <- ar
35 » » }()
36
37 » » // If we are instructed to immediately timeout, do so.
38 » » if cb := mc.timeoutCallback; cb != nil && cb(d) {
39 » » » return
40 » » }
41
42 » » select {
43 » » case <-ctx.Done():
44 » » » ar.Err = ctx.Err()
45 » » case <-mc.testFinishedC:
46 » » » break
47 » » }
48 » }()
49
50 » return resultC
51 }
52
53 func wait(c context.Context) error {
54 » <-c.Done()
55 » return c.Err()
24 } 56 }
25 57
26 func TestClockContext(t *testing.T) { 58 func TestClockContext(t *testing.T) {
27 t.Parallel() 59 t.Parallel()
28 60
29 » Convey(`A context with a deadline wrapping a cancellable parent`, t, fun c() { 61 » Convey(`A manual testing clock`, t, func() {
30 » » now := time.Now() 62 » » mc := manualClock{
31 » » cctx, pcf := context.WithCancel(context.Background()) 63 » » » now: time.Date(2016, 1, 1, 0, 0, 0, 0, time.Lo cal),
32 » » ctx, cf := WithTimeout(cctx, 10*time.Millisecond) 64 » » » testFinishedC: make(chan struct{}),
33 » » releaseC := make(chan struct{}) 65 » » }
66 » » defer close(mc.testFinishedC)
34 67
35 » » Convey(`Successfully reports its deadline.`, func() { 68 » » Convey(`A context with a deadline wrapping a cancellable parent` , func() {
36 » » » deadline, ok := ctx.Deadline() 69 » » » cctx, pcf := context.WithCancel(Set(context.Background() , &mc))
37 » » » So(ok, ShouldBeTrue) 70 » » » ctx, cf := WithTimeout(cctx, 10*time.Millisecond)
38 » » » So(deadline.After(now), ShouldBeTrue) 71
72 » » » Convey(`Successfully reports its deadline.`, func() {
73 » » » » deadline, ok := ctx.Deadline()
74 » » » » So(ok, ShouldBeTrue)
75 » » » » So(deadline.After(mc.now), ShouldBeTrue)
76 » » » })
77
78 » » » Convey(`Will successfully time out.`, func() {
79 » » » » mc.timeoutCallback = func(time.Duration) bool {
80 » » » » » return true
81 » » » » }
82 » » » » So(wait(ctx), ShouldEqual, context.DeadlineExcee ded)
83 » » » })
84
85 » » » Convey(`Will successfully cancel with its cancel func.`, func() {
86 » » » » go func() {
87 » » » » » cf()
88 » » » » }()
89 » » » » So(wait(ctx), ShouldEqual, context.Canceled)
90 » » » })
91
92 » » » Convey(`Will successfully cancel if the parent is cancel ed.`, func() {
93 » » » » go func() {
94 » » » » » pcf()
95 » » » » }()
96 » » » » So(wait(ctx), ShouldEqual, context.Canceled)
97 » » » })
39 }) 98 })
40 99
41 » » Convey(`Will successfully time out.`, func() { 100 » » Convey(`A context with a deadline wrapping a parent with a short er deadline`, func() {
42 » » » released, err := blockingOperation(ctx, releaseC) 101 » » » cctx, _ := context.WithTimeout(context.Background(), 10* time.Millisecond)
43 » » » So(released, ShouldBeFalse) 102 » » » ctx, cf := WithTimeout(cctx, 1*time.Hour)
44 » » » So(err, ShouldEqual, context.DeadlineExceeded) 103
104 » » » Convey(`Will successfully time out.`, func() {
105 » » » » mc.timeoutCallback = func(d time.Duration) bool {
106 » » » » » return d == 10*time.Millisecond
107 » » » » }
108
109 » » » » So(wait(ctx), ShouldEqual, context.DeadlineExcee ded)
110 » » » })
111
112 » » » Convey(`Will successfully cancel with its cancel func.`, func() {
113 » » » » go func() {
114 » » » » » cf()
115 » » » » }()
116 » » » » So(wait(ctx), ShouldEqual, context.Canceled)
117 » » » })
45 }) 118 })
46 119
47 » » Convey(`Will successfully cancel with its cancel func.`, func() { 120 » » Convey(`A context with a deadline in the past`, func() {
48 » » » go func() { 121 » » » ctx, _ := WithDeadline(context.Background(), mc.now.Add( -time.Second))
49 » » » » cf()
50 » » » }()
51 » » » released, err := blockingOperation(ctx, releaseC)
52 » » » So(released, ShouldBeFalse)
53 » » » So(err, ShouldEqual, context.Canceled)
54 » » })
55 122
56 » » Convey(`Will successfully cancel if the parent is cancelled.`, f unc() { 123 » » » Convey(`Will time out immediately.`, func() {
57 » » » go func() { 124 » » » » So(wait(ctx), ShouldEqual, context.DeadlineExcee ded)
58 » » » » pcf() 125 » » » })
59 » » » }()
60 » » » released, err := blockingOperation(ctx, releaseC)
61 » » » So(released, ShouldBeFalse)
62 » » » So(err, ShouldEqual, context.Canceled)
63 » » })
64
65 » » Convey(`Will release before the deadline.`, func() {
66 » » » go func() {
67 » » » » close(releaseC)
68 » » » }()
69 » » » released, err := blockingOperation(ctx, releaseC)
70 » » » So(released, ShouldBeTrue)
71 » » » So(err, ShouldBeNil)
72 » » })
73 » })
74
75 » Convey(`A context with a deadline wrapping a parent with a shorter deadl ine`, t, func() {
76 » » cctx, _ := context.WithTimeout(context.Background(), 10*time.Mil lisecond)
77 » » ctx, cf := WithTimeout(cctx, 1*time.Hour)
78 » » releaseC := make(chan struct{})
79
80 » » Convey(`Will successfully time out.`, func() {
81 » » » released, err := blockingOperation(ctx, releaseC)
82 » » » So(released, ShouldBeFalse)
83 » » » So(err, ShouldEqual, context.DeadlineExceeded)
84 » » })
85
86 » » Convey(`Will successfully cancel with its cancel func.`, func() {
87 » » » go func() {
88 » » » » cf()
89 » » » }()
90 » » » released, err := blockingOperation(ctx, releaseC)
91 » » » So(released, ShouldBeFalse)
92 » » » So(err, ShouldEqual, context.Canceled)
93 » » })
94 » })
95
96 » Convey(`A context with a deadline in the past`, t, func() {
97 » » ctx, _ := WithDeadline(context.Background(), time.Unix(0, 0))
98 » » releaseC := make(chan struct{})
99
100 » » Convey(`Will time out immediately.`, func() {
101 » » » go func() {
102 » » » » defer close(releaseC)
103 » » » » time.Sleep(50 * time.Millisecond)
104 » » » }()
105 » » » released, err := blockingOperation(ctx, releaseC)
106 » » » So(released, ShouldBeFalse)
107 » » » So(err, ShouldEqual, context.DeadlineExceeded)
108 }) 126 })
109 }) 127 })
110 } 128 }
OLDNEW
« no previous file with comments | « common/clock/clockcontext.go ('k') | common/clock/external.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698