context_test.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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. var k1, k2 = NewKey("k1"), NewKey("k2")
  220. func TestValues(t *testing.T) {
  221. check := func(c Context, nm, v1, v2 string) {
  222. if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
  223. t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
  224. }
  225. if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
  226. t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
  227. }
  228. }
  229. c0 := Background()
  230. check(c0, "c0", "", "")
  231. c1 := WithValue(nil, k1, "c1k1")
  232. check(c1, "c1", "c1k1", "")
  233. c2 := WithValue(c1, k2, "c2k2")
  234. check(c2, "c2", "c1k1", "c2k2")
  235. c3 := WithValue(c2, k1, nil)
  236. check(c3, "c3", "", "c2k2")
  237. o0 := otherContext{Background()}
  238. check(o0, "o0", "", "")
  239. o1 := otherContext{WithValue(nil, k1, "c1k1")}
  240. check(o1, "o1", "c1k1", "")
  241. o2 := WithValue(o1, k2, "o2k2")
  242. check(o2, "o2", "c1k1", "o2k2")
  243. o3 := otherContext{c3}
  244. check(o3, "o3", "", "c2k2")
  245. }
  246. func TestAllocs(t *testing.T) {
  247. bg := Background()
  248. for _, test := range []struct {
  249. desc string
  250. f func()
  251. limit float64
  252. gccgoLimit float64
  253. }{
  254. {
  255. desc: "Background()",
  256. f: func() { Background() },
  257. limit: 0,
  258. gccgoLimit: 0,
  259. },
  260. {
  261. desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1),
  262. f: func() {
  263. c := WithValue(bg, k1, nil)
  264. c.Value(k1)
  265. },
  266. limit: 3,
  267. gccgoLimit: 3,
  268. },
  269. {
  270. desc: "WithTimeout(bg, 15*time.Millisecond)",
  271. f: func() {
  272. c, _ := WithTimeout(bg, 15*time.Millisecond)
  273. <-c.Done()
  274. },
  275. limit: 9,
  276. gccgoLimit: 13,
  277. },
  278. {
  279. desc: "WithCancel(bg)",
  280. f: func() {
  281. c, cancel := WithCancel(bg)
  282. cancel()
  283. <-c.Done()
  284. },
  285. limit: 7,
  286. gccgoLimit: 8,
  287. },
  288. {
  289. desc: "WithTimeout(bg, 100*time.Millisecond)",
  290. f: func() {
  291. c, cancel := WithTimeout(bg, 100*time.Millisecond)
  292. cancel()
  293. <-c.Done()
  294. },
  295. limit: 16,
  296. gccgoLimit: 25,
  297. },
  298. } {
  299. limit := test.limit
  300. if runtime.Compiler == "gccgo" {
  301. // gccgo does not yet do escape analysis.
  302. // TOOD(iant): Remove this when gccgo does do escape analysis.
  303. limit = test.gccgoLimit
  304. }
  305. if n := testing.AllocsPerRun(100, test.f); n > limit {
  306. t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
  307. }
  308. }
  309. }
  310. func TestSimultaneousCancels(t *testing.T) {
  311. root, cancel := WithCancel(Background())
  312. m := map[Context]CancelFunc{root: cancel}
  313. q := []Context{root}
  314. // Create a tree of contexts.
  315. for len(q) != 0 && len(m) < 100 {
  316. parent := q[0]
  317. q = q[1:]
  318. for i := 0; i < 4; i++ {
  319. ctx, cancel := WithCancel(parent)
  320. m[ctx] = cancel
  321. q = append(q, ctx)
  322. }
  323. }
  324. // Start all the cancels in a random order.
  325. var wg sync.WaitGroup
  326. wg.Add(len(m))
  327. for _, cancel := range m {
  328. go func(cancel CancelFunc) {
  329. cancel()
  330. wg.Done()
  331. }(cancel)
  332. }
  333. // Wait on all the contexts in a random order.
  334. for ctx := range m {
  335. select {
  336. case <-ctx.Done():
  337. case <-time.After(1 * time.Second):
  338. buf := make([]byte, 10<<10)
  339. n := runtime.Stack(buf, true)
  340. t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n])
  341. }
  342. }
  343. // Wait for all the cancel functions to return.
  344. done := make(chan struct{})
  345. go func() {
  346. wg.Wait()
  347. close(done)
  348. }()
  349. select {
  350. case <-done:
  351. case <-time.After(1 * time.Second):
  352. buf := make([]byte, 10<<10)
  353. n := runtime.Stack(buf, true)
  354. t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n])
  355. }
  356. }
  357. func TestInterlockedCancels(t *testing.T) {
  358. parent, cancelParent := WithCancel(Background())
  359. child, cancelChild := WithCancel(parent)
  360. go func() {
  361. parent.Done()
  362. cancelChild()
  363. }()
  364. cancelParent()
  365. select {
  366. case <-child.Done():
  367. case <-time.After(1 * time.Second):
  368. buf := make([]byte, 10<<10)
  369. n := runtime.Stack(buf, true)
  370. t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n])
  371. }
  372. }