...

Source file src/context/context_test.go

Documentation: context

		 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.
		 4  
		 5  package context
		 6  
		 7  import (
		 8  	"fmt"
		 9  	"math/rand"
		10  	"runtime"
		11  	"strings"
		12  	"sync"
		13  	"sync/atomic"
		14  	"time"
		15  )
		16  
		17  type testingT interface {
		18  	Deadline() (time.Time, bool)
		19  	Error(args ...interface{})
		20  	Errorf(format string, args ...interface{})
		21  	Fail()
		22  	FailNow()
		23  	Failed() bool
		24  	Fatal(args ...interface{})
		25  	Fatalf(format string, args ...interface{})
		26  	Helper()
		27  	Log(args ...interface{})
		28  	Logf(format string, args ...interface{})
		29  	Name() string
		30  	Parallel()
		31  	Skip(args ...interface{})
		32  	SkipNow()
		33  	Skipf(format string, args ...interface{})
		34  	Skipped() bool
		35  }
		36  
		37  // otherContext is a Context that's not one of the types defined in context.go.
		38  // This lets us test code paths that differ based on the underlying type of the
		39  // Context.
		40  type otherContext struct {
		41  	Context
		42  }
		43  
		44  const (
		45  	shortDuration		= 1 * time.Millisecond // a reasonable duration to block in a test
		46  	veryLongDuration = 1000 * time.Hour		 // an arbitrary upper bound on the test's running time
		47  )
		48  
		49  // quiescent returns an arbitrary duration by which the program should have
		50  // completed any remaining work and reached a steady (idle) state.
		51  func quiescent(t testingT) time.Duration {
		52  	deadline, ok := t.Deadline()
		53  	if !ok {
		54  		return 5 * time.Second
		55  	}
		56  
		57  	const arbitraryCleanupMargin = 1 * time.Second
		58  	return time.Until(deadline) - arbitraryCleanupMargin
		59  }
		60  
		61  func XTestBackground(t testingT) {
		62  	c := Background()
		63  	if c == nil {
		64  		t.Fatalf("Background returned nil")
		65  	}
		66  	select {
		67  	case x := <-c.Done():
		68  		t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
		69  	default:
		70  	}
		71  	if got, want := fmt.Sprint(c), "context.Background"; got != want {
		72  		t.Errorf("Background().String() = %q want %q", got, want)
		73  	}
		74  }
		75  
		76  func XTestTODO(t testingT) {
		77  	c := TODO()
		78  	if c == nil {
		79  		t.Fatalf("TODO returned nil")
		80  	}
		81  	select {
		82  	case x := <-c.Done():
		83  		t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
		84  	default:
		85  	}
		86  	if got, want := fmt.Sprint(c), "context.TODO"; got != want {
		87  		t.Errorf("TODO().String() = %q want %q", got, want)
		88  	}
		89  }
		90  
		91  func XTestWithCancel(t testingT) {
		92  	c1, cancel := WithCancel(Background())
		93  
		94  	if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want {
		95  		t.Errorf("c1.String() = %q want %q", got, want)
		96  	}
		97  
		98  	o := otherContext{c1}
		99  	c2, _ := WithCancel(o)
	 100  	contexts := []Context{c1, o, c2}
	 101  
	 102  	for i, c := range contexts {
	 103  		if d := c.Done(); d == nil {
	 104  			t.Errorf("c[%d].Done() == %v want non-nil", i, d)
	 105  		}
	 106  		if e := c.Err(); e != nil {
	 107  			t.Errorf("c[%d].Err() == %v want nil", i, e)
	 108  		}
	 109  
	 110  		select {
	 111  		case x := <-c.Done():
	 112  			t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
	 113  		default:
	 114  		}
	 115  	}
	 116  
	 117  	cancel() // Should propagate synchronously.
	 118  	for i, c := range contexts {
	 119  		select {
	 120  		case <-c.Done():
	 121  		default:
	 122  			t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i)
	 123  		}
	 124  		if e := c.Err(); e != Canceled {
	 125  			t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled)
	 126  		}
	 127  	}
	 128  }
	 129  
	 130  func contains(m map[canceler]struct{}, key canceler) bool {
	 131  	_, ret := m[key]
	 132  	return ret
	 133  }
	 134  
	 135  func XTestParentFinishesChild(t testingT) {
	 136  	// Context tree:
	 137  	// parent -> cancelChild
	 138  	// parent -> valueChild -> timerChild
	 139  	parent, cancel := WithCancel(Background())
	 140  	cancelChild, stop := WithCancel(parent)
	 141  	defer stop()
	 142  	valueChild := WithValue(parent, "key", "value")
	 143  	timerChild, stop := WithTimeout(valueChild, veryLongDuration)
	 144  	defer stop()
	 145  
	 146  	select {
	 147  	case x := <-parent.Done():
	 148  		t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
	 149  	case x := <-cancelChild.Done():
	 150  		t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x)
	 151  	case x := <-timerChild.Done():
	 152  		t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x)
	 153  	case x := <-valueChild.Done():
	 154  		t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x)
	 155  	default:
	 156  	}
	 157  
	 158  	// The parent's children should contain the two cancelable children.
	 159  	pc := parent.(*cancelCtx)
	 160  	cc := cancelChild.(*cancelCtx)
	 161  	tc := timerChild.(*timerCtx)
	 162  	pc.mu.Lock()
	 163  	if len(pc.children) != 2 || !contains(pc.children, cc) || !contains(pc.children, tc) {
	 164  		t.Errorf("bad linkage: pc.children = %v, want %v and %v",
	 165  			pc.children, cc, tc)
	 166  	}
	 167  	pc.mu.Unlock()
	 168  
	 169  	if p, ok := parentCancelCtx(cc.Context); !ok || p != pc {
	 170  		t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc)
	 171  	}
	 172  	if p, ok := parentCancelCtx(tc.Context); !ok || p != pc {
	 173  		t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc)
	 174  	}
	 175  
	 176  	cancel()
	 177  
	 178  	pc.mu.Lock()
	 179  	if len(pc.children) != 0 {
	 180  		t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children)
	 181  	}
	 182  	pc.mu.Unlock()
	 183  
	 184  	// parent and children should all be finished.
	 185  	check := func(ctx Context, name string) {
	 186  		select {
	 187  		case <-ctx.Done():
	 188  		default:
	 189  			t.Errorf("<-%s.Done() blocked, but shouldn't have", name)
	 190  		}
	 191  		if e := ctx.Err(); e != Canceled {
	 192  			t.Errorf("%s.Err() == %v want %v", name, e, Canceled)
	 193  		}
	 194  	}
	 195  	check(parent, "parent")
	 196  	check(cancelChild, "cancelChild")
	 197  	check(valueChild, "valueChild")
	 198  	check(timerChild, "timerChild")
	 199  
	 200  	// WithCancel should return a canceled context on a canceled parent.
	 201  	precanceledChild := WithValue(parent, "key", "value")
	 202  	select {
	 203  	case <-precanceledChild.Done():
	 204  	default:
	 205  		t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have")
	 206  	}
	 207  	if e := precanceledChild.Err(); e != Canceled {
	 208  		t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled)
	 209  	}
	 210  }
	 211  
	 212  func XTestChildFinishesFirst(t testingT) {
	 213  	cancelable, stop := WithCancel(Background())
	 214  	defer stop()
	 215  	for _, parent := range []Context{Background(), cancelable} {
	 216  		child, cancel := WithCancel(parent)
	 217  
	 218  		select {
	 219  		case x := <-parent.Done():
	 220  			t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
	 221  		case x := <-child.Done():
	 222  			t.Errorf("<-child.Done() == %v want nothing (it should block)", x)
	 223  		default:
	 224  		}
	 225  
	 226  		cc := child.(*cancelCtx)
	 227  		pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background()
	 228  		if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) {
	 229  			t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok)
	 230  		}
	 231  
	 232  		if pcok {
	 233  			pc.mu.Lock()
	 234  			if len(pc.children) != 1 || !contains(pc.children, cc) {
	 235  				t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc)
	 236  			}
	 237  			pc.mu.Unlock()
	 238  		}
	 239  
	 240  		cancel()
	 241  
	 242  		if pcok {
	 243  			pc.mu.Lock()
	 244  			if len(pc.children) != 0 {
	 245  				t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children)
	 246  			}
	 247  			pc.mu.Unlock()
	 248  		}
	 249  
	 250  		// child should be finished.
	 251  		select {
	 252  		case <-child.Done():
	 253  		default:
	 254  			t.Errorf("<-child.Done() blocked, but shouldn't have")
	 255  		}
	 256  		if e := child.Err(); e != Canceled {
	 257  			t.Errorf("child.Err() == %v want %v", e, Canceled)
	 258  		}
	 259  
	 260  		// parent should not be finished.
	 261  		select {
	 262  		case x := <-parent.Done():
	 263  			t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
	 264  		default:
	 265  		}
	 266  		if e := parent.Err(); e != nil {
	 267  			t.Errorf("parent.Err() == %v want nil", e)
	 268  		}
	 269  	}
	 270  }
	 271  
	 272  func testDeadline(c Context, name string, t testingT) {
	 273  	t.Helper()
	 274  	d := quiescent(t)
	 275  	timer := time.NewTimer(d)
	 276  	defer timer.Stop()
	 277  	select {
	 278  	case <-timer.C:
	 279  		t.Fatalf("%s: context not timed out after %v", name, d)
	 280  	case <-c.Done():
	 281  	}
	 282  	if e := c.Err(); e != DeadlineExceeded {
	 283  		t.Errorf("%s: c.Err() == %v; want %v", name, e, DeadlineExceeded)
	 284  	}
	 285  }
	 286  
	 287  func XTestDeadline(t testingT) {
	 288  	t.Parallel()
	 289  
	 290  	c, _ := WithDeadline(Background(), time.Now().Add(shortDuration))
	 291  	if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
	 292  		t.Errorf("c.String() = %q want prefix %q", got, prefix)
	 293  	}
	 294  	testDeadline(c, "WithDeadline", t)
	 295  
	 296  	c, _ = WithDeadline(Background(), time.Now().Add(shortDuration))
	 297  	o := otherContext{c}
	 298  	testDeadline(o, "WithDeadline+otherContext", t)
	 299  
	 300  	c, _ = WithDeadline(Background(), time.Now().Add(shortDuration))
	 301  	o = otherContext{c}
	 302  	c, _ = WithDeadline(o, time.Now().Add(veryLongDuration))
	 303  	testDeadline(c, "WithDeadline+otherContext+WithDeadline", t)
	 304  
	 305  	c, _ = WithDeadline(Background(), time.Now().Add(-shortDuration))
	 306  	testDeadline(c, "WithDeadline+inthepast", t)
	 307  
	 308  	c, _ = WithDeadline(Background(), time.Now())
	 309  	testDeadline(c, "WithDeadline+now", t)
	 310  }
	 311  
	 312  func XTestTimeout(t testingT) {
	 313  	t.Parallel()
	 314  
	 315  	c, _ := WithTimeout(Background(), shortDuration)
	 316  	if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
	 317  		t.Errorf("c.String() = %q want prefix %q", got, prefix)
	 318  	}
	 319  	testDeadline(c, "WithTimeout", t)
	 320  
	 321  	c, _ = WithTimeout(Background(), shortDuration)
	 322  	o := otherContext{c}
	 323  	testDeadline(o, "WithTimeout+otherContext", t)
	 324  
	 325  	c, _ = WithTimeout(Background(), shortDuration)
	 326  	o = otherContext{c}
	 327  	c, _ = WithTimeout(o, veryLongDuration)
	 328  	testDeadline(c, "WithTimeout+otherContext+WithTimeout", t)
	 329  }
	 330  
	 331  func XTestCanceledTimeout(t testingT) {
	 332  	c, _ := WithTimeout(Background(), time.Second)
	 333  	o := otherContext{c}
	 334  	c, cancel := WithTimeout(o, veryLongDuration)
	 335  	cancel() // Should propagate synchronously.
	 336  	select {
	 337  	case <-c.Done():
	 338  	default:
	 339  		t.Errorf("<-c.Done() blocked, but shouldn't have")
	 340  	}
	 341  	if e := c.Err(); e != Canceled {
	 342  		t.Errorf("c.Err() == %v want %v", e, Canceled)
	 343  	}
	 344  }
	 345  
	 346  type key1 int
	 347  type key2 int
	 348  
	 349  var k1 = key1(1)
	 350  var k2 = key2(1) // same int as k1, different type
	 351  var k3 = key2(3) // same type as k2, different int
	 352  
	 353  func XTestValues(t testingT) {
	 354  	check := func(c Context, nm, v1, v2, v3 string) {
	 355  		if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
	 356  			t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
	 357  		}
	 358  		if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
	 359  			t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
	 360  		}
	 361  		if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 {
	 362  			t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0)
	 363  		}
	 364  	}
	 365  
	 366  	c0 := Background()
	 367  	check(c0, "c0", "", "", "")
	 368  
	 369  	c1 := WithValue(Background(), k1, "c1k1")
	 370  	check(c1, "c1", "c1k1", "", "")
	 371  
	 372  	if got, want := fmt.Sprint(c1), `context.Background.WithValue(type context.key1, val c1k1)`; got != want {
	 373  		t.Errorf("c.String() = %q want %q", got, want)
	 374  	}
	 375  
	 376  	c2 := WithValue(c1, k2, "c2k2")
	 377  	check(c2, "c2", "c1k1", "c2k2", "")
	 378  
	 379  	c3 := WithValue(c2, k3, "c3k3")
	 380  	check(c3, "c2", "c1k1", "c2k2", "c3k3")
	 381  
	 382  	c4 := WithValue(c3, k1, nil)
	 383  	check(c4, "c4", "", "c2k2", "c3k3")
	 384  
	 385  	o0 := otherContext{Background()}
	 386  	check(o0, "o0", "", "", "")
	 387  
	 388  	o1 := otherContext{WithValue(Background(), k1, "c1k1")}
	 389  	check(o1, "o1", "c1k1", "", "")
	 390  
	 391  	o2 := WithValue(o1, k2, "o2k2")
	 392  	check(o2, "o2", "c1k1", "o2k2", "")
	 393  
	 394  	o3 := otherContext{c4}
	 395  	check(o3, "o3", "", "c2k2", "c3k3")
	 396  
	 397  	o4 := WithValue(o3, k3, nil)
	 398  	check(o4, "o4", "", "c2k2", "")
	 399  }
	 400  
	 401  func XTestAllocs(t testingT, testingShort func() bool, testingAllocsPerRun func(int, func()) float64) {
	 402  	bg := Background()
	 403  	for _, test := range []struct {
	 404  		desc			 string
	 405  		f					func()
	 406  		limit			float64
	 407  		gccgoLimit float64
	 408  	}{
	 409  		{
	 410  			desc:			 "Background()",
	 411  			f:					func() { Background() },
	 412  			limit:			0,
	 413  			gccgoLimit: 0,
	 414  		},
	 415  		{
	 416  			desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1),
	 417  			f: func() {
	 418  				c := WithValue(bg, k1, nil)
	 419  				c.Value(k1)
	 420  			},
	 421  			limit:			3,
	 422  			gccgoLimit: 3,
	 423  		},
	 424  		{
	 425  			desc: "WithTimeout(bg, 1*time.Nanosecond)",
	 426  			f: func() {
	 427  				c, _ := WithTimeout(bg, 1*time.Nanosecond)
	 428  				<-c.Done()
	 429  			},
	 430  			limit:			12,
	 431  			gccgoLimit: 15,
	 432  		},
	 433  		{
	 434  			desc: "WithCancel(bg)",
	 435  			f: func() {
	 436  				c, cancel := WithCancel(bg)
	 437  				cancel()
	 438  				<-c.Done()
	 439  			},
	 440  			limit:			5,
	 441  			gccgoLimit: 8,
	 442  		},
	 443  		{
	 444  			desc: "WithTimeout(bg, 5*time.Millisecond)",
	 445  			f: func() {
	 446  				c, cancel := WithTimeout(bg, 5*time.Millisecond)
	 447  				cancel()
	 448  				<-c.Done()
	 449  			},
	 450  			limit:			8,
	 451  			gccgoLimit: 25,
	 452  		},
	 453  	} {
	 454  		limit := test.limit
	 455  		if runtime.Compiler == "gccgo" {
	 456  			// gccgo does not yet do escape analysis.
	 457  			// TODO(iant): Remove this when gccgo does do escape analysis.
	 458  			limit = test.gccgoLimit
	 459  		}
	 460  		numRuns := 100
	 461  		if testingShort() {
	 462  			numRuns = 10
	 463  		}
	 464  		if n := testingAllocsPerRun(numRuns, test.f); n > limit {
	 465  			t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
	 466  		}
	 467  	}
	 468  }
	 469  
	 470  func XTestSimultaneousCancels(t testingT) {
	 471  	root, cancel := WithCancel(Background())
	 472  	m := map[Context]CancelFunc{root: cancel}
	 473  	q := []Context{root}
	 474  	// Create a tree of contexts.
	 475  	for len(q) != 0 && len(m) < 100 {
	 476  		parent := q[0]
	 477  		q = q[1:]
	 478  		for i := 0; i < 4; i++ {
	 479  			ctx, cancel := WithCancel(parent)
	 480  			m[ctx] = cancel
	 481  			q = append(q, ctx)
	 482  		}
	 483  	}
	 484  	// Start all the cancels in a random order.
	 485  	var wg sync.WaitGroup
	 486  	wg.Add(len(m))
	 487  	for _, cancel := range m {
	 488  		go func(cancel CancelFunc) {
	 489  			cancel()
	 490  			wg.Done()
	 491  		}(cancel)
	 492  	}
	 493  
	 494  	d := quiescent(t)
	 495  	stuck := make(chan struct{})
	 496  	timer := time.AfterFunc(d, func() { close(stuck) })
	 497  	defer timer.Stop()
	 498  
	 499  	// Wait on all the contexts in a random order.
	 500  	for ctx := range m {
	 501  		select {
	 502  		case <-ctx.Done():
	 503  		case <-stuck:
	 504  			buf := make([]byte, 10<<10)
	 505  			n := runtime.Stack(buf, true)
	 506  			t.Fatalf("timed out after %v waiting for <-ctx.Done(); stacks:\n%s", d, buf[:n])
	 507  		}
	 508  	}
	 509  	// Wait for all the cancel functions to return.
	 510  	done := make(chan struct{})
	 511  	go func() {
	 512  		wg.Wait()
	 513  		close(done)
	 514  	}()
	 515  	select {
	 516  	case <-done:
	 517  	case <-stuck:
	 518  		buf := make([]byte, 10<<10)
	 519  		n := runtime.Stack(buf, true)
	 520  		t.Fatalf("timed out after %v waiting for cancel functions; stacks:\n%s", d, buf[:n])
	 521  	}
	 522  }
	 523  
	 524  func XTestInterlockedCancels(t testingT) {
	 525  	parent, cancelParent := WithCancel(Background())
	 526  	child, cancelChild := WithCancel(parent)
	 527  	go func() {
	 528  		<-parent.Done()
	 529  		cancelChild()
	 530  	}()
	 531  	cancelParent()
	 532  	d := quiescent(t)
	 533  	timer := time.NewTimer(d)
	 534  	defer timer.Stop()
	 535  	select {
	 536  	case <-child.Done():
	 537  	case <-timer.C:
	 538  		buf := make([]byte, 10<<10)
	 539  		n := runtime.Stack(buf, true)
	 540  		t.Fatalf("timed out after %v waiting for child.Done(); stacks:\n%s", d, buf[:n])
	 541  	}
	 542  }
	 543  
	 544  func XTestLayersCancel(t testingT) {
	 545  	testLayers(t, time.Now().UnixNano(), false)
	 546  }
	 547  
	 548  func XTestLayersTimeout(t testingT) {
	 549  	testLayers(t, time.Now().UnixNano(), true)
	 550  }
	 551  
	 552  func testLayers(t testingT, seed int64, testTimeout bool) {
	 553  	t.Parallel()
	 554  
	 555  	r := rand.New(rand.NewSource(seed))
	 556  	errorf := func(format string, a ...interface{}) {
	 557  		t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...)
	 558  	}
	 559  	const (
	 560  		minLayers = 30
	 561  	)
	 562  	type value int
	 563  	var (
	 564  		vals			[]*value
	 565  		cancels	 []CancelFunc
	 566  		numTimers int
	 567  		ctx			 = Background()
	 568  	)
	 569  	for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ {
	 570  		switch r.Intn(3) {
	 571  		case 0:
	 572  			v := new(value)
	 573  			ctx = WithValue(ctx, v, v)
	 574  			vals = append(vals, v)
	 575  		case 1:
	 576  			var cancel CancelFunc
	 577  			ctx, cancel = WithCancel(ctx)
	 578  			cancels = append(cancels, cancel)
	 579  		case 2:
	 580  			var cancel CancelFunc
	 581  			d := veryLongDuration
	 582  			if testTimeout {
	 583  				d = shortDuration
	 584  			}
	 585  			ctx, cancel = WithTimeout(ctx, d)
	 586  			cancels = append(cancels, cancel)
	 587  			numTimers++
	 588  		}
	 589  	}
	 590  	checkValues := func(when string) {
	 591  		for _, key := range vals {
	 592  			if val := ctx.Value(key).(*value); key != val {
	 593  				errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key)
	 594  			}
	 595  		}
	 596  	}
	 597  	if !testTimeout {
	 598  		select {
	 599  		case <-ctx.Done():
	 600  			errorf("ctx should not be canceled yet")
	 601  		default:
	 602  		}
	 603  	}
	 604  	if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) {
	 605  		t.Errorf("ctx.String() = %q want prefix %q", s, prefix)
	 606  	}
	 607  	t.Log(ctx)
	 608  	checkValues("before cancel")
	 609  	if testTimeout {
	 610  		d := quiescent(t)
	 611  		timer := time.NewTimer(d)
	 612  		defer timer.Stop()
	 613  		select {
	 614  		case <-ctx.Done():
	 615  		case <-timer.C:
	 616  			errorf("ctx should have timed out after %v", d)
	 617  		}
	 618  		checkValues("after timeout")
	 619  	} else {
	 620  		cancel := cancels[r.Intn(len(cancels))]
	 621  		cancel()
	 622  		select {
	 623  		case <-ctx.Done():
	 624  		default:
	 625  			errorf("ctx should be canceled")
	 626  		}
	 627  		checkValues("after cancel")
	 628  	}
	 629  }
	 630  
	 631  func XTestCancelRemoves(t testingT) {
	 632  	checkChildren := func(when string, ctx Context, want int) {
	 633  		if got := len(ctx.(*cancelCtx).children); got != want {
	 634  			t.Errorf("%s: context has %d children, want %d", when, got, want)
	 635  		}
	 636  	}
	 637  
	 638  	ctx, _ := WithCancel(Background())
	 639  	checkChildren("after creation", ctx, 0)
	 640  	_, cancel := WithCancel(ctx)
	 641  	checkChildren("with WithCancel child ", ctx, 1)
	 642  	cancel()
	 643  	checkChildren("after canceling WithCancel child", ctx, 0)
	 644  
	 645  	ctx, _ = WithCancel(Background())
	 646  	checkChildren("after creation", ctx, 0)
	 647  	_, cancel = WithTimeout(ctx, 60*time.Minute)
	 648  	checkChildren("with WithTimeout child ", ctx, 1)
	 649  	cancel()
	 650  	checkChildren("after canceling WithTimeout child", ctx, 0)
	 651  }
	 652  
	 653  func XTestWithCancelCanceledParent(t testingT) {
	 654  	parent, pcancel := WithCancel(Background())
	 655  	pcancel()
	 656  
	 657  	c, _ := WithCancel(parent)
	 658  	select {
	 659  	case <-c.Done():
	 660  	default:
	 661  		t.Errorf("child not done immediately upon construction")
	 662  	}
	 663  	if got, want := c.Err(), Canceled; got != want {
	 664  		t.Errorf("child not canceled; got = %v, want = %v", got, want)
	 665  	}
	 666  }
	 667  
	 668  func XTestWithValueChecksKey(t testingT) {
	 669  	panicVal := recoveredValue(func() { WithValue(Background(), []byte("foo"), "bar") })
	 670  	if panicVal == nil {
	 671  		t.Error("expected panic")
	 672  	}
	 673  	panicVal = recoveredValue(func() { WithValue(Background(), nil, "bar") })
	 674  	if got, want := fmt.Sprint(panicVal), "nil key"; got != want {
	 675  		t.Errorf("panic = %q; want %q", got, want)
	 676  	}
	 677  }
	 678  
	 679  func XTestInvalidDerivedFail(t testingT) {
	 680  	panicVal := recoveredValue(func() { WithCancel(nil) })
	 681  	if panicVal == nil {
	 682  		t.Error("expected panic")
	 683  	}
	 684  	panicVal = recoveredValue(func() { WithDeadline(nil, time.Now().Add(shortDuration)) })
	 685  	if panicVal == nil {
	 686  		t.Error("expected panic")
	 687  	}
	 688  	panicVal = recoveredValue(func() { WithValue(nil, "foo", "bar") })
	 689  	if panicVal == nil {
	 690  		t.Error("expected panic")
	 691  	}
	 692  }
	 693  
	 694  func recoveredValue(fn func()) (v interface{}) {
	 695  	defer func() { v = recover() }()
	 696  	fn()
	 697  	return
	 698  }
	 699  
	 700  func XTestDeadlineExceededSupportsTimeout(t testingT) {
	 701  	i, ok := DeadlineExceeded.(interface {
	 702  		Timeout() bool
	 703  	})
	 704  	if !ok {
	 705  		t.Fatal("DeadlineExceeded does not support Timeout interface")
	 706  	}
	 707  	if !i.Timeout() {
	 708  		t.Fatal("wrong value for timeout")
	 709  	}
	 710  }
	 711  
	 712  type myCtx struct {
	 713  	Context
	 714  }
	 715  
	 716  type myDoneCtx struct {
	 717  	Context
	 718  }
	 719  
	 720  func (d *myDoneCtx) Done() <-chan struct{} {
	 721  	c := make(chan struct{})
	 722  	return c
	 723  }
	 724  
	 725  func XTestCustomContextGoroutines(t testingT) {
	 726  	g := atomic.LoadInt32(&goroutines)
	 727  	checkNoGoroutine := func() {
	 728  		t.Helper()
	 729  		now := atomic.LoadInt32(&goroutines)
	 730  		if now != g {
	 731  			t.Fatalf("%d goroutines created", now-g)
	 732  		}
	 733  	}
	 734  	checkCreatedGoroutine := func() {
	 735  		t.Helper()
	 736  		now := atomic.LoadInt32(&goroutines)
	 737  		if now != g+1 {
	 738  			t.Fatalf("%d goroutines created, want 1", now-g)
	 739  		}
	 740  		g = now
	 741  	}
	 742  
	 743  	_, cancel0 := WithCancel(&myDoneCtx{Background()})
	 744  	cancel0()
	 745  	checkCreatedGoroutine()
	 746  
	 747  	_, cancel0 = WithTimeout(&myDoneCtx{Background()}, veryLongDuration)
	 748  	cancel0()
	 749  	checkCreatedGoroutine()
	 750  
	 751  	checkNoGoroutine()
	 752  	defer checkNoGoroutine()
	 753  
	 754  	ctx1, cancel1 := WithCancel(Background())
	 755  	defer cancel1()
	 756  	checkNoGoroutine()
	 757  
	 758  	ctx2 := &myCtx{ctx1}
	 759  	ctx3, cancel3 := WithCancel(ctx2)
	 760  	defer cancel3()
	 761  	checkNoGoroutine()
	 762  
	 763  	_, cancel3b := WithCancel(&myDoneCtx{ctx2})
	 764  	defer cancel3b()
	 765  	checkCreatedGoroutine() // ctx1 is not providing Done, must not be used
	 766  
	 767  	ctx4, cancel4 := WithTimeout(ctx3, veryLongDuration)
	 768  	defer cancel4()
	 769  	checkNoGoroutine()
	 770  
	 771  	ctx5, cancel5 := WithCancel(ctx4)
	 772  	defer cancel5()
	 773  	checkNoGoroutine()
	 774  
	 775  	cancel5()
	 776  	checkNoGoroutine()
	 777  
	 778  	_, cancel6 := WithTimeout(ctx5, veryLongDuration)
	 779  	defer cancel6()
	 780  	checkNoGoroutine()
	 781  
	 782  	// Check applied to canceled context.
	 783  	cancel6()
	 784  	cancel1()
	 785  	_, cancel7 := WithCancel(ctx5)
	 786  	defer cancel7()
	 787  	checkNoGoroutine()
	 788  }
	 789  

View as plain text