blob: b7f2625f47799e1d105d810be1f52b153c94c513 [file] [log] [blame]
Serge Bazanski4166a712021-06-07 21:58:54 +02001package combinectx
2
3import (
4 "context"
5 "errors"
6 "testing"
7 "time"
8)
9
10func TestCancel(t *testing.T) {
11 a, aC := context.WithCancel(context.Background())
12 b, bC := context.WithCancel(context.Background())
13
14 c := Combine(a, b)
15 if want, got := error(nil), c.Err(); want != got {
16 t.Fatalf("Newly combined context should return %v, got %v", want, got)
17 }
18 if _, ok := c.Deadline(); ok {
19 t.Errorf("Newly combined context should have no deadline")
20 }
21
22 // Cancel A.
23 aC()
24 // Cancels are not synchronous - wait for it to propagate...
25 <-c.Done()
26 // ...then cancel B (no-op).
27 bC()
28
29 if c.Err() == nil {
30 t.Fatalf("After cancel, ctx.Err() should be non-nil")
31 }
32 if !errors.Is(c.Err(), a.Err()) {
33 t.Errorf("After cancel, ctx.Err() should be a.Err()")
34 }
35 if !errors.Is(c.Err(), c.Err()) {
36 t.Errorf("After cancel, ctx.Err() should be ctx.Err()")
37 }
38 if !errors.Is(c.Err(), context.Canceled) {
39 t.Errorf("After cancel, ctx.Err() should be context.Canceled")
40 }
41 if !errors.Is(c.Err(), &Error{}) {
42 t.Errorf("After cancel, ctx.Err() should be a Error pointer")
43 }
44 cerr := &Error{}
45 if !errors.As(c.Err(), &cerr) {
46 t.Fatalf("After cancel, ctx.Err() should be usable as *Error")
47 }
48 if !cerr.First() {
49 t.Errorf("ctx.Err().First() should be true")
50 }
51 if cerr.Second() {
52 t.Errorf("ctx.Err().Second() should be false")
53 }
54 if want, got := a.Err(), cerr.Unwrap(); want != got {
55 t.Errorf("ctx.Err().Unwrap() should be %v, got %v", want, got)
56 }
57}
58
59func TestDeadline(t *testing.T) {
60 now := time.Now()
61 aD := now.Add(100 * time.Millisecond)
62 bD := now.Add(10 * time.Millisecond)
63
64 a, aC := context.WithDeadline(context.Background(), aD)
65 b, bC := context.WithDeadline(context.Background(), bD)
66
67 defer aC()
68 defer bC()
69
70 c := Combine(a, b)
71 if want, got := error(nil), c.Err(); want != got {
72 t.Fatalf("Newly combined context should return %v, got %v", want, got)
73 }
74 if d, ok := c.Deadline(); !ok || !d.Equal(bD) {
75 t.Errorf("Newly combined context should have deadline %v, got %v", bD, d)
76 }
77
78 <-c.Done()
79
80 if c.Err() == nil {
81 t.Fatalf("After deadline, ctx.Err() should be non-nil")
82 }
83 if !errors.Is(c.Err(), b.Err()) {
84 t.Errorf("After deadline, ctx.Err() should be b.Err()")
85 }
86 if !errors.Is(c.Err(), context.DeadlineExceeded) {
87 t.Errorf("After cancel, ctx.Err() should be context.DeadlineExceeded")
88 }
89 if !errors.Is(c.Err(), &Error{}) {
90 t.Errorf("After cancel, ctx.Err() should be a Error pointer")
91 }
92 cerr := &Error{}
93 if !errors.As(c.Err(), &cerr) {
94 t.Fatalf("After cancel, ctx.Err() should be usable as *Error")
95 }
96 if cerr.First() {
97 t.Errorf("ctx.Err().First() should be false")
98 }
99 if !cerr.Second() {
100 t.Errorf("ctx.Err().Second() should be true")
101 }
102 if want, got := b.Err(), cerr.Unwrap(); want != got {
103 t.Errorf("ctx.Err().Unwrap() should be %v, got %v", want, got)
104 }
105}
106