github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/context/context_test.go (about)

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