context_test.go 15 KB

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