-
Notifications
You must be signed in to change notification settings - Fork 43
/
plugin_test.go
161 lines (141 loc) · 4.04 KB
/
plugin_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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package hotswap
import (
"os"
"path/filepath"
"plugin"
"reflect"
"strings"
"testing"
"github.com/edwingeng/hotswap/internal/hutils"
"github.com/edwingeng/hotswap/vault"
)
func TestPlugin(t *testing.T) {
const exe = "cli/hotswap/hotswap"
const pluginDir = "cli/hotswap/trial/arya"
const outputDir = pluginDir
hutils.BuildPlugin(t, exe, pluginDir, outputDir)
so := filepath.Join(outputDir, "arya.so")
if _, err := os.Stat(so); err != nil {
t.Fatal(err)
}
plug, err := plugin.Open(so)
if err != nil {
t.Fatal(err)
}
p := newPlugin()
p.Name = pluginName(so)
p.P = plug
m := map[string]interface{}{
"OnLoad": &p.fOnLoad,
"OnInit": &p.fOnInit,
"OnFree": &p.fOnFree,
"Export": &p.fExport,
"Import": &p.fImport,
"InvokeFunc": &p.InvokeFunc,
"Reloadable": &p.fReloadable,
"HotswapLiveFuncs": &p.hotswapLiveFuncs,
"HotswapLiveTypes": &p.hotswapLiveTypes,
}
for k, v := range m {
if err := p.Lookup(k, v); err != nil {
t.Fatalf("Lookup() does not work as expected [1]. k: %s, err: % v", k, err)
}
if isNil(v) {
t.Fatalf("Lookup() does not work as expected [2]. k: %s", k)
}
}
ptr := &PluginFuncs{}
if err := p.Lookup("", ptr); err == nil {
t.Fatalf("Lookup() should fail when symName is empty")
}
if err := p.Lookup("alpha", nil); err == nil {
t.Fatalf("Lookup() should fail when out is nil")
}
if err := p.Lookup("alpha", ""); err == nil {
t.Fatalf("Lookup() should fail when out is not a pointer")
}
if err := p.Lookup("alpha", ptr); err != ErrNotExist {
t.Fatalf("Lookup() should return ErrNotExist when symName is not found. err: %v", err)
}
var finalBlow1 int
if err := p.Lookup("FinalBlow1", &finalBlow1); err != nil {
t.Fatalf(`FinalBlow1. err: %v`, err)
} else if finalBlow1 != 100 {
t.Fatalf("finalBlow1 != 100")
}
var finalBlow2 *int
if err := p.Lookup("FinalBlow2", &finalBlow2); err != nil {
t.Fatalf(`FinalBlow2. err: %v`, err)
} else if *finalBlow2 != 100 {
t.Fatalf("*finalBlow2 != 100")
}
var finalBlow3 int64
if err := p.Lookup("FinalBlow3", &finalBlow3); err == nil {
t.Fatalf("FinalBlow3")
}
// Func: OnLoad
if err := p.fOnLoad(nil); err != nil {
t.Fatalf("OnLoad() should not return an error. err: %v", err)
}
// Func: OnInit
vault1 := &vault.Vault{
LiveFuncs: make(map[string]interface{}),
LiveTypes: make(map[string]func() interface{}),
DataBag: make(map[string]interface{}),
}
if err := p.fOnInit(vault1); err != nil {
t.Fatalf("OnInit() should not return an error. err: %v", err)
}
// Func: OnFree
p.fOnFree()
// Func: Export
if ret := p.fExport(); isNil(ret) {
t.Fatalf("Export() should not return nil")
}
// Func: Import
if ret := p.fImport(); ret != nil {
t.Fatalf("Import() should return nil")
}
// Func: InvokeFunc
ret, err := p.InvokeFunc("polish", 1)
if err != nil || reflect.ValueOf(ret).Kind() != reflect.String || !strings.HasPrefix(ret.(string), "Polished") {
t.Fatalf("unexpected return value of InvokeFunc(). ret: %v, err: %v", ret, err)
}
// Func: Reloadable
if reloadable := p.fReloadable(); !reloadable {
t.Fatalf("Reloadable() should return true")
}
// Func: HotswapLiveFuncs
if p.hotswapLiveFuncs() == nil {
t.Fatalf("p.hotswapLiveFuncs() == nil")
}
if len(p.hotswapLiveFuncs()) != 2 {
t.Fatalf("len(p.hotswapLiveFuncs()) != 2")
}
for k, v := range p.hotswapLiveFuncs() {
if k != "live_NotToday" && k != "Live_Anyone" {
t.Fatalf("unexpected live function: %s", k)
}
if reflect.TypeOf(v).Kind() != reflect.Func {
t.Fatalf("reflect.TypeOf(v).Kind() != reflect.Func")
}
}
// Func: HotswapLiveTypes
if p.hotswapLiveTypes() == nil {
t.Fatalf("p.hotswapLiveTypes() == nil")
}
if len(p.hotswapLiveTypes()) != 1 {
t.Fatalf("len(p.hotswapLiveTypes()) != 1")
}
for k, v := range p.hotswapLiveTypes() {
if k != "Live_AryaKill" {
t.Fatalf("unexpected live type: %s", k)
}
if reflect.TypeOf(v).Kind() != reflect.Func {
t.Fatalf("reflect.TypeOf(v).Kind() != reflect.Func")
}
if v == nil || v() == nil {
t.Fatalf("v == nil || v() == nil")
}
}
}