context_test.go 13 KB

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