-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshutdownhandler_test.go
More file actions
138 lines (112 loc) · 3.33 KB
/
shutdownhandler_test.go
File metadata and controls
138 lines (112 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package app
import (
"container/heap"
"context"
"errors"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestShutdownhandlerHeap(t *testing.T) {
h := shutdownHeap{}
heap.Init(&h)
assert.Equal(t, h.Len(), 0, "a new heap must be empty")
assert.Panics(t, func() {
heap.Push(&h, nil)
}, "Push should panic if value is nil")
assert.Panics(t, func() {
heap.Push(&h, ShutdownHandler{})
}, "Push should panic if if value type is not *ShutdownHandler")
sh1 := &ShutdownHandler{
Name: "sh1",
Priority: ShutdownPriority(0),
}
sh2 := &ShutdownHandler{
Name: "sh2",
Priority: ShutdownPriority(10),
}
sh3 := &ShutdownHandler{
Name: "sh3",
Priority: ShutdownPriority(5),
}
sh4 := &ShutdownHandler{
Name: "sh4",
Priority: ShutdownPriority(5),
}
heap.Push(&h, sh1)
heap.Push(&h, sh2)
heap.Push(&h, sh4)
heap.Push(&h, sh3)
assert.Equal(t, h.Len(), 4, "heap should have 4 elements")
p1 := heap.Pop(&h)
p2 := heap.Pop(&h)
p3 := heap.Pop(&h)
p4 := heap.Pop(&h)
assert.Equal(t, sh1, p4, "sh1 has de lowest priority and must be popped last")
assert.Equal(t, sh2, p1, "sh2 has the highest priority and must be popped first")
assert.Equal(t, sh3, p3, "sh3 must be popped after sh4 and before sh1")
assert.Equal(t, sh4, p2, "sh4 must be popped after sh2 and before sh3")
assert.Equal(t, h.Len(), 0, "heap should be empty")
}
func TestShutdownHandlerExecute(t *testing.T) {
assert.Panics(t, func() {
sh := &ShutdownHandler{}
err := sh.Execute(context.Background())
assert.NoError(t, err)
}, "should panic if Handler is not set")
sh := &ShutdownHandler{
Name: "my_shutdown_handler",
Handler: func(context.Context) error {
return nil
},
}
assert.NoError(t, sh.err)
err := sh.Execute(context.TODO())
assert.NoError(t, err)
assert.NoError(t, sh.err)
sh = &ShutdownHandler{
Name: "my_failed_shutdown_handler",
Handler: func(context.Context) error {
return errors.New("my error")
},
Policy: ErrorPolicyAbort,
}
err = sh.Execute(context.TODO())
assert.EqualError(t, err, "shutdown handler 'my_failed_shutdown_handler' failed: my error")
err2 := sh.Execute(context.TODO())
assert.Equal(t, err, err2, "a second execution of handler should return the first error")
}
func TestShutdownHandlerExecute_CanceledContext(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
sh := &ShutdownHandler{
Name: "my_failed_shutdown_handler",
Handler: func(context.Context) error {
return errors.New("my error")
},
Policy: ErrorPolicyAbort,
}
err := sh.Execute(ctx)
assert.EqualError(t, err, "shutdown handler 'my_failed_shutdown_handler' failed: context canceled")
}
func TestShutdownHandlerExecute_Timeout(t *testing.T) {
sh := &ShutdownHandler{
Name: "my_failed_shutdown_handler",
Handler: func(ctx context.Context) error {
// We will simulate a long-running operation that exceeds the timeout
// Reading from a nil channel will block indefinitely
var c <-chan struct{}
select {
case <-c:
return nil
case <-ctx.Done():
return errors.New("custom handler error on deadline exceeded")
}
},
Policy: ErrorPolicyAbort,
Timeout: time.Nanosecond,
}
ctx := context.Background()
err := sh.Execute(ctx)
assert.EqualError(t, err, "shutdown handler 'my_failed_shutdown_handler' failed: custom handler error on deadline exceeded")
}