1 // Copyright 2014 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
16 type testingT
interface {
17 Error(args
...interface{})
18 Errorf(format
string, args
...interface{})
22 Fatal(args
...interface{})
23 Fatalf(format
string, args
...interface{})
24 Log(args
...interface{})
25 Logf(format
string, args
...interface{})
27 Skip(args
...interface{})
29 Skipf(format
string, args
...interface{})
33 // otherContext is a Context that's not one of the types defined in context.go.
34 // This lets us test code paths that differ based on the underlying type of the
36 type otherContext
struct {
40 func XTestBackground(t testingT
) {
43 t
.Fatalf("Background returned nil")
47 t
.Errorf("<-c.Done() == %v want nothing (it should block)", x
)
50 if got
, want
:= fmt
.Sprint(c
), "context.Background"; got
!= want
{
51 t
.Errorf("Background().String() = %q want %q", got
, want
)
55 func XTestTODO(t testingT
) {
58 t
.Fatalf("TODO returned nil")
62 t
.Errorf("<-c.Done() == %v want nothing (it should block)", x
)
65 if got
, want
:= fmt
.Sprint(c
), "context.TODO"; got
!= want
{
66 t
.Errorf("TODO().String() = %q want %q", got
, want
)
70 func XTestWithCancel(t testingT
) {
71 c1
, cancel
:= WithCancel(Background())
73 if got
, want
:= fmt
.Sprint(c1
), "context.Background.WithCancel"; got
!= want
{
74 t
.Errorf("c1.String() = %q want %q", got
, want
)
78 c2
, _
:= WithCancel(o
)
79 contexts
:= []Context
{c1
, o
, c2
}
81 for i
, c
:= range contexts
{
82 if d
:= c
.Done(); d
== nil {
83 t
.Errorf("c[%d].Done() == %v want non-nil", i
, d
)
85 if e
:= c
.Err(); e
!= nil {
86 t
.Errorf("c[%d].Err() == %v want nil", i
, e
)
91 t
.Errorf("<-c.Done() == %v want nothing (it should block)", x
)
97 time
.Sleep(100 * time
.Millisecond
) // let cancelation propagate
99 for i
, c
:= range contexts
{
103 t
.Errorf("<-c[%d].Done() blocked, but shouldn't have", i
)
105 if e
:= c
.Err(); e
!= Canceled
{
106 t
.Errorf("c[%d].Err() == %v want %v", i
, e
, Canceled
)
111 func contains(m
map[canceler
]struct{}, key canceler
) bool {
116 func XTestParentFinishesChild(t testingT
) {
118 // parent -> cancelChild
119 // parent -> valueChild -> timerChild
120 parent
, cancel
:= WithCancel(Background())
121 cancelChild
, stop
:= WithCancel(parent
)
123 valueChild
:= WithValue(parent
, "key", "value")
124 timerChild
, stop
:= WithTimeout(valueChild
, 10000*time
.Hour
)
128 case x
:= <-parent
.Done():
129 t
.Errorf("<-parent.Done() == %v want nothing (it should block)", x
)
130 case x
:= <-cancelChild
.Done():
131 t
.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x
)
132 case x
:= <-timerChild
.Done():
133 t
.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x
)
134 case x
:= <-valueChild
.Done():
135 t
.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x
)
139 // The parent's children should contain the two cancelable children.
140 pc
:= parent
.(*cancelCtx
)
141 cc
:= cancelChild
.(*cancelCtx
)
142 tc
:= timerChild
.(*timerCtx
)
144 if len(pc
.children
) != 2 ||
!contains(pc
.children
, cc
) ||
!contains(pc
.children
, tc
) {
145 t
.Errorf("bad linkage: pc.children = %v, want %v and %v",
150 if p
, ok
:= parentCancelCtx(cc
.Context
); !ok || p
!= pc
{
151 t
.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p
, ok
, pc
)
153 if p
, ok
:= parentCancelCtx(tc
.Context
); !ok || p
!= pc
{
154 t
.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p
, ok
, pc
)
160 if len(pc
.children
) != 0 {
161 t
.Errorf("pc.cancel didn't clear pc.children = %v", pc
.children
)
165 // parent and children should all be finished.
166 check
:= func(ctx Context
, name
string) {
170 t
.Errorf("<-%s.Done() blocked, but shouldn't have", name
)
172 if e
:= ctx
.Err(); e
!= Canceled
{
173 t
.Errorf("%s.Err() == %v want %v", name
, e
, Canceled
)
176 check(parent
, "parent")
177 check(cancelChild
, "cancelChild")
178 check(valueChild
, "valueChild")
179 check(timerChild
, "timerChild")
181 // WithCancel should return a canceled context on a canceled parent.
182 precanceledChild
:= WithValue(parent
, "key", "value")
184 case <-precanceledChild
.Done():
186 t
.Errorf("<-precanceledChild.Done() blocked, but shouldn't have")
188 if e
:= precanceledChild
.Err(); e
!= Canceled
{
189 t
.Errorf("precanceledChild.Err() == %v want %v", e
, Canceled
)
193 func XTestChildFinishesFirst(t testingT
) {
194 cancelable
, stop
:= WithCancel(Background())
196 for _
, parent
:= range []Context
{Background(), cancelable
} {
197 child
, cancel
:= WithCancel(parent
)
200 case x
:= <-parent
.Done():
201 t
.Errorf("<-parent.Done() == %v want nothing (it should block)", x
)
202 case x
:= <-child
.Done():
203 t
.Errorf("<-child.Done() == %v want nothing (it should block)", x
)
207 cc
:= child
.(*cancelCtx
)
208 pc
, pcok
:= parent
.(*cancelCtx
) // pcok == false when parent == Background()
209 if p
, ok
:= parentCancelCtx(cc
.Context
); ok
!= pcok ||
(ok
&& pc
!= p
) {
210 t
.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p
, ok
, pc
, pcok
)
215 if len(pc
.children
) != 1 ||
!contains(pc
.children
, cc
) {
216 t
.Errorf("bad linkage: pc.children = %v, cc = %v", pc
.children
, cc
)
225 if len(pc
.children
) != 0 {
226 t
.Errorf("child's cancel didn't remove self from pc.children = %v", pc
.children
)
231 // child should be finished.
235 t
.Errorf("<-child.Done() blocked, but shouldn't have")
237 if e
:= child
.Err(); e
!= Canceled
{
238 t
.Errorf("child.Err() == %v want %v", e
, Canceled
)
241 // parent should not be finished.
243 case x
:= <-parent
.Done():
244 t
.Errorf("<-parent.Done() == %v want nothing (it should block)", x
)
247 if e
:= parent
.Err(); e
!= nil {
248 t
.Errorf("parent.Err() == %v want nil", e
)
253 func testDeadline(c Context
, name
string, failAfter time
.Duration
, t testingT
) {
255 case <-time
.After(failAfter
):
256 t
.Fatalf("%s: context should have timed out", name
)
259 if e
:= c
.Err(); e
!= DeadlineExceeded
{
260 t
.Errorf("%s: c.Err() == %v; want %v", name
, e
, DeadlineExceeded
)
264 func XTestDeadline(t testingT
) {
265 c
, _
:= WithDeadline(Background(), time
.Now().Add(50*time
.Millisecond
))
266 if got
, prefix
:= fmt
.Sprint(c
), "context.Background.WithDeadline("; !strings
.HasPrefix(got
, prefix
) {
267 t
.Errorf("c.String() = %q want prefix %q", got
, prefix
)
269 testDeadline(c
, "WithDeadline", time
.Second
, t
)
271 c
, _
= WithDeadline(Background(), time
.Now().Add(50*time
.Millisecond
))
273 testDeadline(o
, "WithDeadline+otherContext", time
.Second
, t
)
275 c
, _
= WithDeadline(Background(), time
.Now().Add(50*time
.Millisecond
))
277 c
, _
= WithDeadline(o
, time
.Now().Add(4*time
.Second
))
278 testDeadline(c
, "WithDeadline+otherContext+WithDeadline", 2*time
.Second
, t
)
280 c
, _
= WithDeadline(Background(), time
.Now().Add(-time
.Millisecond
))
281 testDeadline(c
, "WithDeadline+inthepast", time
.Second
, t
)
283 c
, _
= WithDeadline(Background(), time
.Now())
284 testDeadline(c
, "WithDeadline+now", time
.Second
, t
)
287 func XTestTimeout(t testingT
) {
288 c
, _
:= WithTimeout(Background(), 50*time
.Millisecond
)
289 if got
, prefix
:= fmt
.Sprint(c
), "context.Background.WithDeadline("; !strings
.HasPrefix(got
, prefix
) {
290 t
.Errorf("c.String() = %q want prefix %q", got
, prefix
)
292 testDeadline(c
, "WithTimeout", time
.Second
, t
)
294 c
, _
= WithTimeout(Background(), 50*time
.Millisecond
)
296 testDeadline(o
, "WithTimeout+otherContext", time
.Second
, t
)
298 c
, _
= WithTimeout(Background(), 50*time
.Millisecond
)
300 c
, _
= WithTimeout(o
, 3*time
.Second
)
301 testDeadline(c
, "WithTimeout+otherContext+WithTimeout", 2*time
.Second
, t
)
304 func XTestCanceledTimeout(t testingT
) {
305 c
, _
:= WithTimeout(Background(), time
.Second
)
307 c
, cancel
:= WithTimeout(o
, 2*time
.Second
)
309 time
.Sleep(100 * time
.Millisecond
) // let cancelation propagate
313 t
.Errorf("<-c.Done() blocked, but shouldn't have")
315 if e
:= c
.Err(); e
!= Canceled
{
316 t
.Errorf("c.Err() == %v want %v", e
, Canceled
)
324 var k2
= key2(1) // same int as k1, different type
325 var k3
= key2(3) // same type as k2, different int
327 func XTestValues(t testingT
) {
328 check
:= func(c Context
, nm
, v1
, v2
, v3
string) {
329 if v
, ok
:= c
.Value(k1
).(string); ok
== (len(v1
) == 0) || v
!= v1
{
330 t
.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm
, v
, ok
, v1
, len(v1
) != 0)
332 if v
, ok
:= c
.Value(k2
).(string); ok
== (len(v2
) == 0) || v
!= v2
{
333 t
.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm
, v
, ok
, v2
, len(v2
) != 0)
335 if v
, ok
:= c
.Value(k3
).(string); ok
== (len(v3
) == 0) || v
!= v3
{
336 t
.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm
, v
, ok
, v3
, len(v3
) != 0)
341 check(c0
, "c0", "", "", "")
343 c1
:= WithValue(Background(), k1
, "c1k1")
344 check(c1
, "c1", "c1k1", "", "")
346 if got
, want
:= fmt
.Sprint(c1
), `context.Background.WithValue(1, "c1k1")`; got
!= want
{
347 t
.Errorf("c.String() = %q want %q", got
, want
)
350 c2
:= WithValue(c1
, k2
, "c2k2")
351 check(c2
, "c2", "c1k1", "c2k2", "")
353 c3
:= WithValue(c2
, k3
, "c3k3")
354 check(c3
, "c2", "c1k1", "c2k2", "c3k3")
356 c4
:= WithValue(c3
, k1
, nil)
357 check(c4
, "c4", "", "c2k2", "c3k3")
359 o0
:= otherContext
{Background()}
360 check(o0
, "o0", "", "", "")
362 o1
:= otherContext
{WithValue(Background(), k1
, "c1k1")}
363 check(o1
, "o1", "c1k1", "", "")
365 o2
:= WithValue(o1
, k2
, "o2k2")
366 check(o2
, "o2", "c1k1", "o2k2", "")
368 o3
:= otherContext
{c4
}
369 check(o3
, "o3", "", "c2k2", "c3k3")
371 o4
:= WithValue(o3
, k3
, nil)
372 check(o4
, "o4", "", "c2k2", "")
375 func XTestAllocs(t testingT
, testingShort
func() bool, testingAllocsPerRun
func(int, func()) float64) {
377 for _
, test
:= range []struct {
384 desc
: "Background()",
385 f
: func() { Background() },
390 desc
: fmt
.Sprintf("WithValue(bg, %v, nil)", k1
),
392 c
:= WithValue(bg
, k1
, nil)
399 desc
: "WithTimeout(bg, 15*time.Millisecond)",
401 c
, _
:= WithTimeout(bg
, 15*time
.Millisecond
)
408 desc
: "WithCancel(bg)",
410 c
, cancel
:= WithCancel(bg
)
418 desc
: "WithTimeout(bg, 5*time.Millisecond)",
420 c
, cancel
:= WithTimeout(bg
, 5*time
.Millisecond
)
429 if runtime
.Compiler
== "gccgo" {
430 // gccgo does not yet do escape analysis.
431 // TODO(iant): Remove this when gccgo does do escape analysis.
432 limit
= test
.gccgoLimit
438 if n
:= testingAllocsPerRun(numRuns
, test
.f
); n
> limit
{
439 t
.Errorf("%s allocs = %f want %d", test
.desc
, n
, int(limit
))
444 func XTestSimultaneousCancels(t testingT
) {
445 root
, cancel
:= WithCancel(Background())
446 m
:= map[Context
]CancelFunc
{root
: cancel
}
448 // Create a tree of contexts.
449 for len(q
) != 0 && len(m
) < 100 {
452 for i
:= 0; i
< 4; i
++ {
453 ctx
, cancel
:= WithCancel(parent
)
458 // Start all the cancels in a random order.
459 var wg sync
.WaitGroup
461 for _
, cancel
:= range m
{
462 go func(cancel CancelFunc
) {
467 // Wait on all the contexts in a random order.
471 case <-time
.After(1 * time
.Second
):
472 buf
:= make([]byte, 10<<10)
473 n
:= runtime
.Stack(buf
, true)
474 t
.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf
[:n
])
477 // Wait for all the cancel functions to return.
478 done
:= make(chan struct{})
485 case <-time
.After(1 * time
.Second
):
486 buf
:= make([]byte, 10<<10)
487 n
:= runtime
.Stack(buf
, true)
488 t
.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf
[:n
])
492 func XTestInterlockedCancels(t testingT
) {
493 parent
, cancelParent
:= WithCancel(Background())
494 child
, cancelChild
:= WithCancel(parent
)
502 case <-time
.After(1 * time
.Second
):
503 buf
:= make([]byte, 10<<10)
504 n
:= runtime
.Stack(buf
, true)
505 t
.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf
[:n
])
509 func XTestLayersCancel(t testingT
) {
510 testLayers(t
, time
.Now().UnixNano(), false)
513 func XTestLayersTimeout(t testingT
) {
514 testLayers(t
, time
.Now().UnixNano(), true)
517 func testLayers(t testingT
, seed
int64, testTimeout
bool) {
519 errorf
:= func(format
string, a
...interface{}) {
520 t
.Errorf(fmt
.Sprintf("seed=%d: %s", seed
, format
), a
...)
523 timeout
= 200 * time
.Millisecond
533 for i
:= 0; i
< minLayers || numTimers
== 0 ||
len(cancels
) == 0 ||
len(vals
) == 0; i
++ {
534 switch rand
.Intn(3) {
537 ctx
= WithValue(ctx
, v
, v
)
538 vals
= append(vals
, v
)
540 var cancel CancelFunc
541 ctx
, cancel
= WithCancel(ctx
)
542 cancels
= append(cancels
, cancel
)
544 var cancel CancelFunc
545 ctx
, cancel
= WithTimeout(ctx
, timeout
)
546 cancels
= append(cancels
, cancel
)
550 checkValues
:= func(when
string) {
551 for _
, key
:= range vals
{
552 if val
:= ctx
.Value(key
).(*value
); key
!= val
{
553 errorf("%s: ctx.Value(%p) = %p want %p", when
, key
, val
, key
)
559 errorf("ctx should not be canceled yet")
562 if s
, prefix
:= fmt
.Sprint(ctx
), "context.Background."; !strings
.HasPrefix(s
, prefix
) {
563 t
.Errorf("ctx.String() = %q want prefix %q", s
, prefix
)
566 checkValues("before cancel")
570 case <-time
.After(timeout
+ time
.Second
):
571 errorf("ctx should have timed out")
573 checkValues("after timeout")
575 cancel
:= cancels
[rand
.Intn(len(cancels
))]
580 errorf("ctx should be canceled")
582 checkValues("after cancel")
586 func XTestCancelRemoves(t testingT
) {
587 checkChildren
:= func(when
string, ctx Context
, want
int) {
588 if got
:= len(ctx
.(*cancelCtx
).children
); got
!= want
{
589 t
.Errorf("%s: context has %d children, want %d", when
, got
, want
)
593 ctx
, _
:= WithCancel(Background())
594 checkChildren("after creation", ctx
, 0)
595 _
, cancel
:= WithCancel(ctx
)
596 checkChildren("with WithCancel child ", ctx
, 1)
598 checkChildren("after canceling WithCancel child", ctx
, 0)
600 ctx
, _
= WithCancel(Background())
601 checkChildren("after creation", ctx
, 0)
602 _
, cancel
= WithTimeout(ctx
, 60*time
.Minute
)
603 checkChildren("with WithTimeout child ", ctx
, 1)
605 checkChildren("after canceling WithTimeout child", ctx
, 0)
608 func XTestWithCancelCanceledParent(t testingT
) {
609 parent
, pcancel
:= WithCancel(Background())
612 c
, _
:= WithCancel(parent
)
615 case <-time
.After(5 * time
.Second
):
616 t
.Fatal("timeout waiting for Done")
618 if got
, want
:= c
.Err(), Canceled
; got
!= want
{
619 t
.Errorf("child not cancelled; got = %v, want = %v", got
, want
)
623 func XTestWithValueChecksKey(t testingT
) {
624 panicVal
:= recoveredValue(func() { WithValue(Background(), []byte("foo"), "bar") })
626 t
.Error("expected panic")
628 panicVal
= recoveredValue(func() { WithValue(Background(), nil, "bar") })
629 if got
, want
:= fmt
.Sprint(panicVal
), "nil key"; got
!= want
{
630 t
.Errorf("panic = %q; want %q", got
, want
)
634 func recoveredValue(fn
func()) (v
interface{}) {
635 defer func() { v
= recover() }()
640 func XTestDeadlineExceededSupportsTimeout(t testingT
) {
641 i
, ok
:= DeadlineExceeded
.(interface {
645 t
.Fatal("DeadlineExceeded does not support Timeout interface")
648 t
.Fatal("wrong value for timeout")