v / vlib / context / cause_test.v
116 lines · 88 sloc · 2.66 KB · 3c9244f3caa2adc467525a8c13a1c9a23855ca9c
Raw
1// vtest retry: 3
2module context
3
4import time
5
6fn test_with_cancel_cause_no_cause() {
7 mut bg := background()
8 mut ctx, cancel := with_cancel_cause(mut bg)
9 defer {
10 cancel(none)
11 }
12
13 assert ctx.err() is none
14 assert cause(ctx) is none
15
16 cancel(none)
17 assert ctx.err().str() == 'context canceled'
18 // cause falls back to err() when no cause was set
19 assert cause(ctx).str() == 'context canceled'
20}
21
22fn test_with_cancel_cause_with_cause() {
23 my_err := error('my custom cause')
24
25 mut bg := background()
26 mut ctx, cancel := with_cancel_cause(mut bg)
27 defer {
28 cancel(none)
29 }
30
31 assert ctx.err() is none
32
33 cancel(my_err)
34 assert ctx.err().str() == 'context canceled'
35 assert cause(ctx).str() == 'my custom cause'
36}
37
38fn test_with_cancel_cause_first_cause_wins() {
39 first := error('first cause')
40 second := error('second cause')
41
42 mut bg := background()
43 mut ctx, cancel := with_cancel_cause(mut bg)
44
45 cancel(first)
46 cancel(second) // should be ignored
47 cancel(none) // should be ignored
48
49 assert cause(ctx).str() == 'first cause'
50}
51
52fn test_with_cancel_cause_parent_cancel_propagates() {
53 mut bg := background()
54 mut parent, parent_cancel := with_cancel(mut bg)
55 mut ctx, _ := with_cancel_cause(mut parent)
56
57 assert ctx.err() is none
58
59 parent_cancel()
60 // give goroutine a moment to propagate
61 time.sleep(5 * time.millisecond)
62
63 assert ctx.err().str() == 'context canceled'
64}
65
66fn test_with_timeout_cause_fires_cause() {
67 my_cause := error('timed out for testing')
68
69 mut bg := background()
70 mut ctx, cancel := with_timeout_cause(mut bg, 30 * time.millisecond, my_cause)
71 defer {
72 cancel()
73 }
74
75 // not done yet
76 assert ctx.err() is none
77
78 // poll for the deadline goroutine to record the cancellation; busy CI
79 // runners can take well over 60ms to schedule it.
80 deadline := time.now().add(2 * time.second)
81 for ctx.err() is none && time.now() < deadline {
82 time.sleep(5 * time.millisecond)
83 }
84
85 assert ctx.err().str() == 'context deadline exceeded'
86 assert cause(ctx).str() == 'timed out for testing'
87}
88
89fn test_with_timeout_cause_cancel_before_deadline() {
90 my_cause := error('deadline cause')
91
92 mut bg := background()
93 mut ctx, cancel := with_timeout_cause(mut bg, 500 * time.millisecond, my_cause)
94
95 // cancel before deadline fires
96 cancel()
97 time.sleep(5 * time.millisecond)
98
99 assert ctx.err().str() == 'context canceled'
100 // no cause was set via CancelCauseFunc; cause falls back to err()
101 assert cause(ctx).str() == 'context canceled'
102}
103
104fn test_cause_on_plain_cancel_context() {
105 // cause() on a non-cause context should just return ctx.err()
106 mut bg := background()
107 mut ctx, cancel := with_cancel(mut bg)
108 defer {
109 cancel()
110 }
111
112 assert cause(ctx) is none
113
114 cancel()
115 assert cause(ctx).str() == 'context canceled'
116}
117