1 package gval
2
3 import (
4 "context"
5 "fmt"
6 "reflect"
7 "testing"
8 "time"
9 )
10
11 func Test_toFunc(t *testing.T) {
12 myError := fmt.Errorf("my error")
13 tests := []struct {
14 name string
15 function interface{}
16 arguments []interface{}
17 want interface{}
18 wantErr error
19 wantAnyErr bool
20 }{
21 {
22 name: "empty",
23 function: func() {},
24 },
25 {
26 name: "one arg",
27 function: func(a interface{}) {
28 if a != true {
29 panic("fail")
30 }
31 },
32 arguments: []interface{}{true},
33 },
34 {
35 name: "three args",
36 function: func(a, b, c interface{}) {
37 if a != 1 || b != 2 || c != 3 {
38 panic("fail")
39 }
40 },
41 arguments: []interface{}{1, 2, 3},
42 },
43 {
44 name: "input types",
45 function: func(a int, b string, c bool) {
46 if a != 1 || b != "2" || !c {
47 panic("fail")
48 }
49 },
50 arguments: []interface{}{1, "2", true},
51 },
52 {
53 name: "wronge input type int",
54 function: func(a int, b string, c bool) {},
55 arguments: []interface{}{"1", "2", true},
56 wantAnyErr: true,
57 },
58 {
59 name: "wronge input type string",
60 function: func(a int, b string, c bool) {},
61 arguments: []interface{}{1, 2, true},
62 wantAnyErr: true,
63 },
64 {
65 name: "wronge input type bool",
66 function: func(a int, b string, c bool) {},
67 arguments: []interface{}{1, "2", "true"},
68 wantAnyErr: true,
69 },
70 {
71 name: "wronge input number",
72 function: func(a int, b string, c bool) {},
73 arguments: []interface{}{1, "2"},
74 wantAnyErr: true,
75 },
76 {
77 name: "one return",
78 function: func() bool {
79 return true
80 },
81 want: true,
82 },
83 {
84 name: "three returns",
85 function: func() (bool, string, int) {
86 return true, "2", 3
87 },
88 want: []interface{}{true, "2", 3},
89 },
90 {
91 name: "error",
92 function: func() error {
93 return myError
94 },
95 wantErr: myError,
96 },
97 {
98 name: "none error",
99 function: func() error {
100 return nil
101 },
102 },
103 {
104 name: "one return with error",
105 function: func() (bool, error) {
106 return false, myError
107 },
108 want: false,
109 wantErr: myError,
110 },
111 {
112 name: "three returns with error",
113 function: func() (bool, string, int, error) {
114 return false, "", 0, myError
115 },
116 want: []interface{}{false, "", 0},
117 wantErr: myError,
118 },
119 {
120 name: "context not expiring",
121 function: func(ctx context.Context) error {
122 return nil
123 },
124 },
125 {
126 name: "context expires",
127 function: func(ctx context.Context) error {
128 time.Sleep(20 * time.Millisecond)
129 return nil
130 },
131 wantErr: context.DeadlineExceeded,
132 },
133 {
134 name: "nil arg",
135 function: func(a interface{}) bool {
136 if a != nil {
137 return true
138 }
139 return false
140 },
141 arguments: []interface{}{nil},
142 want: true,
143 },
144 }
145 for _, tt := range tests {
146 t.Run(tt.name, func(t *testing.T) {
147 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
148 got, err := toFunc(tt.function)(ctx, tt.arguments...)
149 cancel()
150
151 if tt.wantAnyErr {
152 if err != nil {
153 return
154 }
155 t.Fatalf("toFunc()(args...) = error(nil), but wantAnyErr")
156 }
157 if err != tt.wantErr {
158 t.Fatalf("toFunc()(args...) = error(%v), wantErr (%v)", err, tt.wantErr)
159 }
160 if !reflect.DeepEqual(got, tt.want) {
161 t.Errorf("toFunc()(args...) = %v, want %v", got, tt.want)
162 }
163 })
164 }
165 }
166
View as plain text