forked from Leo-Guo/monkey
-
Notifications
You must be signed in to change notification settings - Fork 4
/
monkey_test.go
127 lines (107 loc) · 2.26 KB
/
monkey_test.go
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
package monkey_test
import (
"reflect"
"runtime"
"testing"
"time"
"bou.ke/monkey"
)
func no() bool { return false }
func yes() bool { return true }
func TestTimePatch(t *testing.T) {
before := time.Now()
monkey.Patch(time.Now, func() time.Time {
return time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC)
})
during := time.Now()
assert(t, monkey.Unpatch(time.Now))
after := time.Now()
assert(t, time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC) == during)
assert(t, before != during)
assert(t, during != after)
}
func TestGC(t *testing.T) {
value := true
monkey.Patch(no, func() bool {
return value
})
defer monkey.UnpatchAll()
runtime.GC()
assert(t, no())
}
func TestSimple(t *testing.T) {
assert(t, !no())
monkey.Patch(no, yes)
assert(t, no())
assert(t, monkey.Unpatch(no))
assert(t, !no())
assert(t, !monkey.Unpatch(no))
}
func TestGuard(t *testing.T) {
var guard *monkey.PatchGuard
guard = monkey.Patch(no, func() bool {
guard.Unpatch()
defer guard.Restore()
return !no()
})
for i := 0; i < 100; i++ {
assert(t, no())
}
monkey.Unpatch(no)
}
func TestUnpatchAll(t *testing.T) {
assert(t, !no())
monkey.Patch(no, yes)
assert(t, no())
monkey.UnpatchAll()
assert(t, !no())
}
type s struct{}
func (s *s) yes() bool { return true }
func TestWithInstanceMethod(t *testing.T) {
i := &s{}
assert(t, !no())
monkey.Patch(no, i.yes)
assert(t, no())
monkey.Unpatch(no)
assert(t, !no())
}
type f struct{}
func (f *f) No() bool { return false }
func TestOnInstanceMethod(t *testing.T) {
i := &f{}
assert(t, !i.No())
monkey.PatchInstanceMethod(reflect.TypeOf(i), "No", func(_ *f) bool { return true })
assert(t, i.No())
assert(t, monkey.UnpatchInstanceMethod(reflect.TypeOf(i), "No"))
assert(t, !i.No())
}
func TestNotFunction(t *testing.T) {
panics(t, func() {
monkey.Patch(no, 1)
})
panics(t, func() {
monkey.Patch(1, yes)
})
}
func TestNotCompatible(t *testing.T) {
panics(t, func() {
monkey.Patch(no, func() {})
})
}
func assert(t *testing.T, b bool, args ...interface{}) {
t.Helper()
if !b {
t.Fatal(append([]interface{}{"assertion failed"}, args...))
}
}
func panics(t *testing.T, f func()) {
t.Helper()
defer func() {
t.Helper()
if v := recover(); v == nil {
t.Fatal("expected panic")
}
}()
f()
}