context_test.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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. "runtime"
  8. "sync"
  9. "testing"
  10. "time"
  11. )
  12. // otherContext is a Context that's not a *ctx. This lets us test code paths
  13. // that differ based on the underlying type of the Context.
  14. type otherContext struct {
  15. Context
  16. }
  17. func TestBackground(t *testing.T) {
  18. c := Background()
  19. if c == nil {
  20. t.Fatalf("Background returned nil")
  21. }
  22. select {
  23. case x := <-c.Done():
  24. t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
  25. default:
  26. }
  27. }
  28. func TestWithCancel(t *testing.T) {
  29. c1, cancel := WithCancel(Background())
  30. o := otherContext{c1}
  31. c2 := newCtx(o, maybeCanceled)
  32. contexts := []Context{c1, o, c2}
  33. for i, c := range contexts {
  34. if d := c.Done(); d == nil {
  35. t.Errorf("c[%d].Done() == %v want non-nil", i, d)
  36. }
  37. if e := c.Err(); e != nil {
  38. t.Errorf("c[%d].Err() == %v want nil", i, e)
  39. }
  40. select {
  41. case x := <-c.Done():
  42. t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
  43. default:
  44. }
  45. }
  46. cancel()
  47. time.Sleep(100 * time.Millisecond) // let cancellation propagate
  48. for i, c := range contexts {
  49. select {
  50. case <-c.Done():
  51. default:
  52. t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i)
  53. }
  54. if e := c.Err(); e != Canceled {
  55. t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled)
  56. }
  57. }
  58. }
  59. func TestParentFinishesChild(t *testing.T) {
  60. parent, cancel := WithCancel(Background())
  61. pctx := parent.(*ctx)
  62. child1 := newCtx(parent, maybeCanceled)
  63. child2 := newCtx(parent, neverCanceled)
  64. select {
  65. case x := <-parent.Done():
  66. t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
  67. case x := <-child1.Done():
  68. t.Errorf("<-child1.Done() == %v want nothing (it should block)", x)
  69. case x := <-child2.Done():
  70. t.Errorf("<-child2.Done() == %v want nothing (it should block)", x)
  71. default:
  72. }
  73. pctx.mu.Lock()
  74. if len(pctx.children) != 2 ||
  75. !pctx.children[child1] || child1.parent != pctx ||
  76. !pctx.children[child2] || child2.parent != pctx {
  77. t.Errorf("bad linkage: pctx.children = %v, child1.parent = %v, child2.parent = %v",
  78. pctx.children, child1.parent, child2.parent)
  79. }
  80. pctx.mu.Unlock()
  81. cancel()
  82. pctx.mu.Lock()
  83. if len(pctx.children) != 0 {
  84. t.Errorf("pctx.cancel didn't clear pctx.children = %v", pctx.children)
  85. }
  86. pctx.mu.Unlock()
  87. // parent and children should all be finished.
  88. select {
  89. case <-parent.Done():
  90. default:
  91. t.Errorf("<-parent.Done() blocked, but shouldn't have")
  92. }
  93. if e := parent.Err(); e != Canceled {
  94. t.Errorf("parent.Err() == %v want %v", e, Canceled)
  95. }
  96. select {
  97. case <-child1.Done():
  98. default:
  99. t.Errorf("<-child1.Done() blocked, but shouldn't have")
  100. }
  101. if e := child1.Err(); e != Canceled {
  102. t.Errorf("child1.Err() == %v want %v", e, Canceled)
  103. }
  104. select {
  105. case <-child2.Done():
  106. default:
  107. t.Errorf("<-child2.Done() blocked, but shouldn't have")
  108. }
  109. if e := child2.Err(); e != Canceled {
  110. t.Errorf("child2.Err() == %v want %v", e, Canceled)
  111. }
  112. // New should return a canceled context on a canceled parent.
  113. child3 := newCtx(parent, neverCanceled)
  114. select {
  115. case <-child3.Done():
  116. default:
  117. t.Errorf("<-child3.Done() blocked, but shouldn't have")
  118. }
  119. if e := child3.Err(); e != Canceled {
  120. t.Errorf("child3.Err() == %v want %v", e, Canceled)
  121. }
  122. }
  123. func TestChildFinishesFirst(t *testing.T) {
  124. for _, parentMayCancel := range []bool{neverCanceled, maybeCanceled} {
  125. parent := newCtx(nil, parentMayCancel)
  126. child, cancel := WithCancel(parent)
  127. pctx := parent
  128. cctx := child.(*ctx)
  129. select {
  130. case x := <-parent.Done():
  131. t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
  132. case x := <-child.Done():
  133. t.Errorf("<-child.Done() == %v want nothing (it should block)", x)
  134. default:
  135. }
  136. if cctx.parent != pctx {
  137. t.Errorf("bad linkage: cctx.parent = %v, parent = %v", cctx.parent, pctx)
  138. }
  139. if parentMayCancel {
  140. pctx.mu.Lock()
  141. if len(pctx.children) != 1 || !pctx.children[cctx] {
  142. t.Errorf("bad linkage: pctx.children = %v, cctx = %v", pctx.children, cctx)
  143. }
  144. pctx.mu.Unlock()
  145. }
  146. cancel()
  147. pctx.mu.Lock()
  148. if len(pctx.children) != 0 {
  149. t.Errorf("child.Cancel didn't remove self from pctx.children = %v", pctx.children)
  150. }
  151. pctx.mu.Unlock()
  152. // child should be finished.
  153. select {
  154. case <-child.Done():
  155. default:
  156. t.Errorf("<-child.Done() blocked, but shouldn't have")
  157. }
  158. if e := child.Err(); e != Canceled {
  159. t.Errorf("child.Err() == %v want %v", e, Canceled)
  160. }
  161. // parent should not be finished.
  162. select {
  163. case x := <-parent.Done():
  164. t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
  165. default:
  166. }
  167. if e := parent.Err(); e != nil {
  168. t.Errorf("parent.Err() == %v want nil", e)
  169. }
  170. }
  171. }
  172. func testDeadline(c Context, wait time.Duration, t *testing.T) {
  173. select {
  174. case <-time.After(wait):
  175. t.Fatalf("context should have timed out")
  176. case <-c.Done():
  177. }
  178. if e := c.Err(); e != DeadlineExceeded {
  179. t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded)
  180. }
  181. }
  182. func TestDeadline(t *testing.T) {
  183. c, _ := WithDeadline(nil, time.Now().Add(100*time.Millisecond))
  184. testDeadline(c, 200*time.Millisecond, t)
  185. c, _ = WithDeadline(nil, time.Now().Add(100*time.Millisecond))
  186. o := otherContext{c}
  187. testDeadline(o, 200*time.Millisecond, t)
  188. c, _ = WithDeadline(nil, time.Now().Add(100*time.Millisecond))
  189. o = otherContext{c}
  190. c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond))
  191. testDeadline(c, 200*time.Millisecond, t)
  192. }
  193. func TestTimeout(t *testing.T) {
  194. c, _ := WithTimeout(nil, 100*time.Millisecond)
  195. testDeadline(c, 200*time.Millisecond, t)
  196. c, _ = WithTimeout(nil, 100*time.Millisecond)
  197. o := otherContext{c}
  198. testDeadline(o, 200*time.Millisecond, t)
  199. c, _ = WithTimeout(nil, 100*time.Millisecond)
  200. o = otherContext{c}
  201. c, _ = WithTimeout(o, 300*time.Millisecond)
  202. testDeadline(c, 200*time.Millisecond, t)
  203. }
  204. func TestCancelledTimeout(t *testing.T) {
  205. c, _ := WithTimeout(nil, 200*time.Millisecond)
  206. o := otherContext{c}
  207. c, cancel := WithTimeout(o, 400*time.Millisecond)
  208. cancel()
  209. time.Sleep(100 * time.Millisecond) // let cancellation propagate
  210. select {
  211. case <-c.Done():
  212. default:
  213. t.Errorf("<-c.Done() blocked, but shouldn't have")
  214. }
  215. if e := c.Err(); e != Canceled {
  216. t.Errorf("c.Err() == %v want %v", e, Canceled)
  217. }
  218. }
  219. type key1 int
  220. type key2 int
  221. var k1 = key1(1)
  222. var k2 = key2(1) // same int as k1, different type
  223. var k3 = key2(3) // same type as k2, different int
  224. func TestValues(t *testing.T) {
  225. check := func(c Context, nm, v1, v2, v3 string) {
  226. if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
  227. t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
  228. }
  229. if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
  230. t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
  231. }
  232. if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 {
  233. t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0)
  234. }
  235. }
  236. c0 := Background()
  237. check(c0, "c0", "", "", "")
  238. c1 := WithValue(nil, k1, "c1k1")
  239. check(c1, "c1", "c1k1", "", "")
  240. c2 := WithValue(c1, k2, "c2k2")
  241. check(c2, "c2", "c1k1", "c2k2", "")
  242. c3 := WithValue(c2, k3, "c3k3")
  243. check(c3, "c2", "c1k1", "c2k2", "c3k3")
  244. c4 := WithValue(c3, k1, nil)
  245. check(c4, "c4", "", "c2k2", "c3k3")
  246. o0 := otherContext{Background()}
  247. check(o0, "o0", "", "", "")
  248. o1 := otherContext{WithValue(nil, k1, "c1k1")}
  249. check(o1, "o1", "c1k1", "", "")
  250. o2 := WithValue(o1, k2, "o2k2")
  251. check(o2, "o2", "c1k1", "o2k2", "")
  252. o3 := otherContext{c4}
  253. check(o3, "o3", "", "c2k2", "c3k3")
  254. o4 := WithValue(o3, k3, nil)
  255. check(o4, "o4", "", "c2k2", "")
  256. }
  257. func TestAllocs(t *testing.T) {
  258. bg := Background()
  259. for _, test := range []struct {
  260. desc string
  261. f func()
  262. limit float64
  263. gccgoLimit float64
  264. }{
  265. {
  266. desc: "Background()",
  267. f: func() { Background() },
  268. limit: 0,
  269. gccgoLimit: 0,
  270. },
  271. {
  272. desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1),
  273. f: func() {
  274. c := WithValue(bg, k1, nil)
  275. c.Value(k1)
  276. },
  277. limit: 3,
  278. gccgoLimit: 3,
  279. },
  280. {
  281. desc: "WithTimeout(bg, 15*time.Millisecond)",
  282. f: func() {
  283. c, _ := WithTimeout(bg, 15*time.Millisecond)
  284. <-c.Done()
  285. },
  286. limit: 9,
  287. gccgoLimit: 13,
  288. },
  289. {
  290. desc: "WithCancel(bg)",
  291. f: func() {
  292. c, cancel := WithCancel(bg)
  293. cancel()
  294. <-c.Done()
  295. },
  296. limit: 7,
  297. gccgoLimit: 8,
  298. },
  299. {
  300. desc: "WithTimeout(bg, 100*time.Millisecond)",
  301. f: func() {
  302. c, cancel := WithTimeout(bg, 100*time.Millisecond)
  303. cancel()
  304. <-c.Done()
  305. },
  306. limit: 16,
  307. gccgoLimit: 25,
  308. },
  309. } {
  310. limit := test.limit
  311. if runtime.Compiler == "gccgo" {
  312. // gccgo does not yet do escape analysis.
  313. // TOOD(iant): Remove this when gccgo does do escape analysis.
  314. limit = test.gccgoLimit
  315. }
  316. if n := testing.AllocsPerRun(100, test.f); n > limit {
  317. t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
  318. }
  319. }
  320. }
  321. func TestSimultaneousCancels(t *testing.T) {
  322. root, cancel := WithCancel(Background())
  323. m := map[Context]CancelFunc{root: cancel}
  324. q := []Context{root}
  325. // Create a tree of contexts.
  326. for len(q) != 0 && len(m) < 100 {
  327. parent := q[0]
  328. q = q[1:]
  329. for i := 0; i < 4; i++ {
  330. ctx, cancel := WithCancel(parent)
  331. m[ctx] = cancel
  332. q = append(q, ctx)
  333. }
  334. }
  335. // Start all the cancels in a random order.
  336. var wg sync.WaitGroup
  337. wg.Add(len(m))
  338. for _, cancel := range m {
  339. go func(cancel CancelFunc) {
  340. cancel()
  341. wg.Done()
  342. }(cancel)
  343. }
  344. // Wait on all the contexts in a random order.
  345. for ctx := range m {
  346. select {
  347. case <-ctx.Done():
  348. case <-time.After(1 * time.Second):
  349. buf := make([]byte, 10<<10)
  350. n := runtime.Stack(buf, true)
  351. t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n])
  352. }
  353. }
  354. // Wait for all the cancel functions to return.
  355. done := make(chan struct{})
  356. go func() {
  357. wg.Wait()
  358. close(done)
  359. }()
  360. select {
  361. case <-done:
  362. case <-time.After(1 * time.Second):
  363. buf := make([]byte, 10<<10)
  364. n := runtime.Stack(buf, true)
  365. t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n])
  366. }
  367. }
  368. func TestInterlockedCancels(t *testing.T) {
  369. parent, cancelParent := WithCancel(Background())
  370. child, cancelChild := WithCancel(parent)
  371. go func() {
  372. parent.Done()
  373. cancelChild()
  374. }()
  375. cancelParent()
  376. select {
  377. case <-child.Done():
  378. case <-time.After(1 * time.Second):
  379. buf := make([]byte, 10<<10)
  380. n := runtime.Stack(buf, true)
  381. t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n])
  382. }
  383. }