context_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  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. package context
  5. import (
  6. "fmt"
  7. "math/rand"
  8. "runtime"
  9. "strings"
  10. "sync"
  11. "testing"
  12. "time"
  13. )
  14. // otherContext is a Context that's not one of the types defined in context.go.
  15. // This lets us test code paths that differ based on the underlying type of the
  16. // Context.
  17. type otherContext struct {
  18. Context
  19. }
  20. func TestBackground(t *testing.T) {
  21. c := Background()
  22. if c == nil {
  23. t.Fatalf("Background returned nil")
  24. }
  25. select {
  26. case x := <-c.Done():
  27. t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
  28. default:
  29. }
  30. if got, want := fmt.Sprint(c), "context.Background"; got != want {
  31. t.Errorf("Background().String() = %q want %q", got, want)
  32. }
  33. }
  34. func TestTODO(t *testing.T) {
  35. c := TODO()
  36. if c == nil {
  37. t.Fatalf("TODO returned nil")
  38. }
  39. select {
  40. case x := <-c.Done():
  41. t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
  42. default:
  43. }
  44. if got, want := fmt.Sprint(c), "context.TODO"; got != want {
  45. t.Errorf("TODO().String() = %q want %q", got, want)
  46. }
  47. }
  48. func TestWithCancel(t *testing.T) {
  49. c1, cancel := WithCancel(Background())
  50. if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want {
  51. t.Errorf("c1.String() = %q want %q", got, want)
  52. }
  53. o := otherContext{c1}
  54. c2, _ := WithCancel(o)
  55. contexts := []Context{c1, o, c2}
  56. for i, c := range contexts {
  57. if d := c.Done(); d == nil {
  58. t.Errorf("c[%d].Done() == %v want non-nil", i, d)
  59. }
  60. if e := c.Err(); e != nil {
  61. t.Errorf("c[%d].Err() == %v want nil", i, e)
  62. }
  63. select {
  64. case x := <-c.Done():
  65. t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
  66. default:
  67. }
  68. }
  69. cancel()
  70. time.Sleep(100 * time.Millisecond) // let cancelation propagate
  71. for i, c := range contexts {
  72. select {
  73. case <-c.Done():
  74. default:
  75. t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i)
  76. }
  77. if e := c.Err(); e != Canceled {
  78. t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled)
  79. }
  80. }
  81. }
  82. func TestParentFinishesChild(t *testing.T) {
  83. // Context tree:
  84. // parent -> cancelChild
  85. // parent -> valueChild -> timerChild
  86. parent, cancel := WithCancel(Background())
  87. cancelChild, stop := WithCancel(parent)
  88. defer stop()
  89. valueChild := WithValue(parent, "key", "value")
  90. timerChild, stop := WithTimeout(valueChild, 10000*time.Hour)
  91. defer stop()
  92. select {
  93. case x := <-parent.Done():
  94. t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
  95. case x := <-cancelChild.Done():
  96. t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x)
  97. case x := <-timerChild.Done():
  98. t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x)
  99. case x := <-valueChild.Done():
  100. t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x)
  101. default:
  102. }
  103. // The parent's children should contain the two cancelable children.
  104. pc := parent.(*cancelCtx)
  105. cc := cancelChild.(*cancelCtx)
  106. tc := timerChild.(*timerCtx)
  107. pc.mu.Lock()
  108. if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] {
  109. t.Errorf("bad linkage: pc.children = %v, want %v and %v",
  110. pc.children, cc, tc)
  111. }
  112. pc.mu.Unlock()
  113. if p, ok := parentCancelCtx(cc.Context); !ok || p != pc {
  114. t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc)
  115. }
  116. if p, ok := parentCancelCtx(tc.Context); !ok || p != pc {
  117. t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc)
  118. }
  119. cancel()
  120. pc.mu.Lock()
  121. if len(pc.children) != 0 {
  122. t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children)
  123. }
  124. pc.mu.Unlock()
  125. // parent and children should all be finished.
  126. check := func(ctx Context, name string) {
  127. select {
  128. case <-ctx.Done():
  129. default:
  130. t.Errorf("<-%s.Done() blocked, but shouldn't have", name)
  131. }
  132. if e := ctx.Err(); e != Canceled {
  133. t.Errorf("%s.Err() == %v want %v", name, e, Canceled)
  134. }
  135. }
  136. check(parent, "parent")
  137. check(cancelChild, "cancelChild")
  138. check(valueChild, "valueChild")
  139. check(timerChild, "timerChild")
  140. // WithCancel should return a canceled context on a canceled parent.
  141. precanceledChild := WithValue(parent, "key", "value")
  142. select {
  143. case <-precanceledChild.Done():
  144. default:
  145. t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have")
  146. }
  147. if e := precanceledChild.Err(); e != Canceled {
  148. t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled)
  149. }
  150. }
  151. func TestChildFinishesFirst(t *testing.T) {
  152. cancelable, stop := WithCancel(Background())
  153. defer stop()
  154. for _, parent := range []Context{Background(), cancelable} {
  155. child, cancel := WithCancel(parent)
  156. select {
  157. case x := <-parent.Done():
  158. t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
  159. case x := <-child.Done():
  160. t.Errorf("<-child.Done() == %v want nothing (it should block)", x)
  161. default:
  162. }
  163. cc := child.(*cancelCtx)
  164. pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background()
  165. if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) {
  166. t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok)
  167. }
  168. if pcok {
  169. pc.mu.Lock()
  170. if len(pc.children) != 1 || !pc.children[cc] {
  171. t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc)
  172. }
  173. pc.mu.Unlock()
  174. }
  175. cancel()
  176. if pcok {
  177. pc.mu.Lock()
  178. if len(pc.children) != 0 {
  179. t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children)
  180. }
  181. pc.mu.Unlock()
  182. }
  183. // child should be finished.
  184. select {
  185. case <-child.Done():
  186. default:
  187. t.Errorf("<-child.Done() blocked, but shouldn't have")
  188. }
  189. if e := child.Err(); e != Canceled {
  190. t.Errorf("child.Err() == %v want %v", e, Canceled)
  191. }
  192. // parent should not be finished.
  193. select {
  194. case x := <-parent.Done():
  195. t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
  196. default:
  197. }
  198. if e := parent.Err(); e != nil {
  199. t.Errorf("parent.Err() == %v want nil", e)
  200. }
  201. }
  202. }
  203. func testDeadline(c Context, wait time.Duration, t *testing.T) {
  204. select {
  205. case <-time.After(wait):
  206. t.Fatalf("context should have timed out")
  207. case <-c.Done():
  208. }
  209. if e := c.Err(); e != DeadlineExceeded {
  210. t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded)
  211. }
  212. }
  213. func TestDeadline(t *testing.T) {
  214. c, _ := WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
  215. if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
  216. t.Errorf("c.String() = %q want prefix %q", got, prefix)
  217. }
  218. testDeadline(c, 200*time.Millisecond, t)
  219. c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
  220. o := otherContext{c}
  221. testDeadline(o, 200*time.Millisecond, t)
  222. c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
  223. o = otherContext{c}
  224. c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond))
  225. testDeadline(c, 200*time.Millisecond, t)
  226. }
  227. func TestTimeout(t *testing.T) {
  228. c, _ := WithTimeout(Background(), 100*time.Millisecond)
  229. if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
  230. t.Errorf("c.String() = %q want prefix %q", got, prefix)
  231. }
  232. testDeadline(c, 200*time.Millisecond, t)
  233. c, _ = WithTimeout(Background(), 100*time.Millisecond)
  234. o := otherContext{c}
  235. testDeadline(o, 200*time.Millisecond, t)
  236. c, _ = WithTimeout(Background(), 100*time.Millisecond)
  237. o = otherContext{c}
  238. c, _ = WithTimeout(o, 300*time.Millisecond)
  239. testDeadline(c, 200*time.Millisecond, t)
  240. }
  241. func TestCanceledTimeout(t *testing.T) {
  242. c, _ := WithTimeout(Background(), 200*time.Millisecond)
  243. o := otherContext{c}
  244. c, cancel := WithTimeout(o, 400*time.Millisecond)
  245. cancel()
  246. time.Sleep(100 * time.Millisecond) // let cancelation propagate
  247. select {
  248. case <-c.Done():
  249. default:
  250. t.Errorf("<-c.Done() blocked, but shouldn't have")
  251. }
  252. if e := c.Err(); e != Canceled {
  253. t.Errorf("c.Err() == %v want %v", e, Canceled)
  254. }
  255. }
  256. type key1 int
  257. type key2 int
  258. var k1 = key1(1)
  259. var k2 = key2(1) // same int as k1, different type
  260. var k3 = key2(3) // same type as k2, different int
  261. func TestValues(t *testing.T) {
  262. check := func(c Context, nm, v1, v2, v3 string) {
  263. if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
  264. t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
  265. }
  266. if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
  267. t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
  268. }
  269. if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 {
  270. t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0)
  271. }
  272. }
  273. c0 := Background()
  274. check(c0, "c0", "", "", "")
  275. c1 := WithValue(Background(), k1, "c1k1")
  276. check(c1, "c1", "c1k1", "", "")
  277. if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want {
  278. t.Errorf("c.String() = %q want %q", got, want)
  279. }
  280. c2 := WithValue(c1, k2, "c2k2")
  281. check(c2, "c2", "c1k1", "c2k2", "")
  282. c3 := WithValue(c2, k3, "c3k3")
  283. check(c3, "c2", "c1k1", "c2k2", "c3k3")
  284. c4 := WithValue(c3, k1, nil)
  285. check(c4, "c4", "", "c2k2", "c3k3")
  286. o0 := otherContext{Background()}
  287. check(o0, "o0", "", "", "")
  288. o1 := otherContext{WithValue(Background(), k1, "c1k1")}
  289. check(o1, "o1", "c1k1", "", "")
  290. o2 := WithValue(o1, k2, "o2k2")
  291. check(o2, "o2", "c1k1", "o2k2", "")
  292. o3 := otherContext{c4}
  293. check(o3, "o3", "", "c2k2", "c3k3")
  294. o4 := WithValue(o3, k3, nil)
  295. check(o4, "o4", "", "c2k2", "")
  296. }
  297. func TestAllocs(t *testing.T) {
  298. bg := Background()
  299. for _, test := range []struct {
  300. desc string
  301. f func()
  302. limit float64
  303. gccgoLimit float64
  304. }{
  305. {
  306. desc: "Background()",
  307. f: func() { Background() },
  308. limit: 0,
  309. gccgoLimit: 0,
  310. },
  311. {
  312. desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1),
  313. f: func() {
  314. c := WithValue(bg, k1, nil)
  315. c.Value(k1)
  316. },
  317. limit: 3,
  318. gccgoLimit: 3,
  319. },
  320. {
  321. desc: "WithTimeout(bg, 15*time.Millisecond)",
  322. f: func() {
  323. c, _ := WithTimeout(bg, 15*time.Millisecond)
  324. <-c.Done()
  325. },
  326. limit: 8,
  327. gccgoLimit: 15,
  328. },
  329. {
  330. desc: "WithCancel(bg)",
  331. f: func() {
  332. c, cancel := WithCancel(bg)
  333. cancel()
  334. <-c.Done()
  335. },
  336. limit: 5,
  337. gccgoLimit: 8,
  338. },
  339. {
  340. desc: "WithTimeout(bg, 100*time.Millisecond)",
  341. f: func() {
  342. c, cancel := WithTimeout(bg, 100*time.Millisecond)
  343. cancel()
  344. <-c.Done()
  345. },
  346. limit: 8,
  347. gccgoLimit: 25,
  348. },
  349. } {
  350. limit := test.limit
  351. if runtime.Compiler == "gccgo" {
  352. // gccgo does not yet do escape analysis.
  353. // TOOD(iant): Remove this when gccgo does do escape analysis.
  354. limit = test.gccgoLimit
  355. }
  356. if n := testing.AllocsPerRun(100, test.f); n > limit {
  357. t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
  358. }
  359. }
  360. }
  361. func TestSimultaneousCancels(t *testing.T) {
  362. root, cancel := WithCancel(Background())
  363. m := map[Context]CancelFunc{root: cancel}
  364. q := []Context{root}
  365. // Create a tree of contexts.
  366. for len(q) != 0 && len(m) < 100 {
  367. parent := q[0]
  368. q = q[1:]
  369. for i := 0; i < 4; i++ {
  370. ctx, cancel := WithCancel(parent)
  371. m[ctx] = cancel
  372. q = append(q, ctx)
  373. }
  374. }
  375. // Start all the cancels in a random order.
  376. var wg sync.WaitGroup
  377. wg.Add(len(m))
  378. for _, cancel := range m {
  379. go func(cancel CancelFunc) {
  380. cancel()
  381. wg.Done()
  382. }(cancel)
  383. }
  384. // Wait on all the contexts in a random order.
  385. for ctx := range m {
  386. select {
  387. case <-ctx.Done():
  388. case <-time.After(1 * time.Second):
  389. buf := make([]byte, 10<<10)
  390. n := runtime.Stack(buf, true)
  391. t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n])
  392. }
  393. }
  394. // Wait for all the cancel functions to return.
  395. done := make(chan struct{})
  396. go func() {
  397. wg.Wait()
  398. close(done)
  399. }()
  400. select {
  401. case <-done:
  402. case <-time.After(1 * time.Second):
  403. buf := make([]byte, 10<<10)
  404. n := runtime.Stack(buf, true)
  405. t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n])
  406. }
  407. }
  408. func TestInterlockedCancels(t *testing.T) {
  409. parent, cancelParent := WithCancel(Background())
  410. child, cancelChild := WithCancel(parent)
  411. go func() {
  412. parent.Done()
  413. cancelChild()
  414. }()
  415. cancelParent()
  416. select {
  417. case <-child.Done():
  418. case <-time.After(1 * time.Second):
  419. buf := make([]byte, 10<<10)
  420. n := runtime.Stack(buf, true)
  421. t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n])
  422. }
  423. }
  424. func TestLayersCancel(t *testing.T) {
  425. testLayers(t, time.Now().UnixNano(), false)
  426. }
  427. func TestLayersTimeout(t *testing.T) {
  428. testLayers(t, time.Now().UnixNano(), true)
  429. }
  430. func testLayers(t *testing.T, seed int64, testTimeout bool) {
  431. rand.Seed(seed)
  432. errorf := func(format string, a ...interface{}) {
  433. t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...)
  434. }
  435. const (
  436. timeout = 200 * time.Millisecond
  437. minLayers = 30
  438. )
  439. type value int
  440. var (
  441. vals []*value
  442. cancels []CancelFunc
  443. numTimers int
  444. ctx = Background()
  445. )
  446. for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ {
  447. switch rand.Intn(3) {
  448. case 0:
  449. v := new(value)
  450. ctx = WithValue(ctx, v, v)
  451. vals = append(vals, v)
  452. case 1:
  453. var cancel CancelFunc
  454. ctx, cancel = WithCancel(ctx)
  455. cancels = append(cancels, cancel)
  456. case 2:
  457. var cancel CancelFunc
  458. ctx, cancel = WithTimeout(ctx, timeout)
  459. cancels = append(cancels, cancel)
  460. numTimers++
  461. }
  462. }
  463. checkValues := func(when string) {
  464. for _, key := range vals {
  465. if val := ctx.Value(key).(*value); key != val {
  466. errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key)
  467. }
  468. }
  469. }
  470. select {
  471. case <-ctx.Done():
  472. errorf("ctx should not be canceled yet")
  473. default:
  474. }
  475. if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) {
  476. t.Errorf("ctx.String() = %q want prefix %q", s, prefix)
  477. }
  478. t.Log(ctx)
  479. checkValues("before cancel")
  480. if testTimeout {
  481. select {
  482. case <-ctx.Done():
  483. case <-time.After(timeout + 100*time.Millisecond):
  484. errorf("ctx should have timed out")
  485. }
  486. checkValues("after timeout")
  487. } else {
  488. cancel := cancels[rand.Intn(len(cancels))]
  489. cancel()
  490. select {
  491. case <-ctx.Done():
  492. default:
  493. errorf("ctx should be canceled")
  494. }
  495. checkValues("after cancel")
  496. }
  497. }
  498. func TestCancelRemoves(t *testing.T) {
  499. checkChildren := func(when string, ctx Context, want int) {
  500. if got := len(ctx.(*cancelCtx).children); got != want {
  501. t.Errorf("%s: context has %d children, want %d", when, got, want)
  502. }
  503. }
  504. ctx, _ := WithCancel(Background())
  505. checkChildren("after creation", ctx, 0)
  506. _, cancel := WithCancel(ctx)
  507. checkChildren("with WithCancel child ", ctx, 1)
  508. cancel()
  509. checkChildren("after cancelling WithCancel child", ctx, 0)
  510. ctx, _ = WithCancel(Background())
  511. checkChildren("after creation", ctx, 0)
  512. _, cancel = WithTimeout(ctx, 60*time.Minute)
  513. checkChildren("with WithTimeout child ", ctx, 1)
  514. cancel()
  515. checkChildren("after cancelling WithTimeout child", ctx, 0)
  516. }