forked from yarpc/yarpc-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinject_test.go
203 lines (183 loc) · 4.84 KB
/
inject_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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package yarpc_test
import (
"fmt"
"reflect"
"testing"
"go.uber.org/yarpc"
"go.uber.org/yarpc/api/transport"
"go.uber.org/yarpc/api/transport/transporttest"
"go.uber.org/yarpc/encoding/json"
"go.uber.org/yarpc/encoding/raw"
"go.uber.org/yarpc/internal/clientconfig"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
func TestRegisterClientBuilderPanics(t *testing.T) {
tests := []struct {
name string
give interface{}
}{
{name: "nil", give: nil},
{name: "wrong kind", give: 42},
{
name: "already registered",
give: func(transport.ClientConfig) json.Client { return nil },
},
{
name: "wrong argument type",
give: func(int) json.Client { return nil },
},
{
name: "wrong return type",
give: func(transport.ClientConfig) string { return "" },
},
{
name: "wrong number of arguments",
give: func(transport.ClientConfig, ...string) json.Client { return nil },
},
{
name: "wrong number of returns",
give: func(transport.ClientConfig) (json.Client, error) { return nil, nil },
},
}
for _, tt := range tests {
assert.Panics(t, func() { yarpc.RegisterClientBuilder(tt.give) }, tt.name)
}
}
func TestInjectClientsPanics(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
type unknownClient interface{}
tests := []struct {
name string
failOnServices []string
target interface{}
}{
{
name: "not a pointer to a struct",
target: struct{}{},
},
{
name: "unknown service",
failOnServices: []string{"foo"},
target: &struct {
Client json.Client `service:"foo"`
}{},
},
{
name: "unknown client",
target: &struct {
Client unknownClient `service:"bar"`
}{},
},
}
for _, tt := range tests {
cp := newMockClientConfigProvider(mockCtrl)
for _, s := range tt.failOnServices {
cp.EXPECT().ClientConfig(s).Do(func(s string) {
panic(fmt.Sprintf("unknown service %q", s))
})
}
assert.Panics(t, func() {
yarpc.InjectClients(cp, tt.target)
}, tt.name)
}
}
func TestInjectClientSuccess(t *testing.T) {
type unknownClient interface{}
type knownClient interface{}
clear := yarpc.RegisterClientBuilder(
func(transport.ClientConfig) knownClient { return knownClient(struct{}{}) })
defer clear()
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
tests := []struct {
name string
target interface{}
// list of services for which ClientConfig() should return successfully
knownServices []string
// list of field names in target we expect to be nil or non-nil
wantNil []string
wantNonNil []string
}{
{
name: "empty",
target: &struct{}{},
},
{
name: "unknown service non-nil",
target: &struct {
Client json.Client `service:"foo"`
}{
Client: json.New(clientconfig.MultiOutbound(
"foo",
"bar",
transport.Outbounds{
Unary: transporttest.NewMockUnaryOutbound(mockCtrl),
})),
},
wantNonNil: []string{"Client"},
},
{
name: "unknown type untagged",
target: &struct {
Client unknownClient `notservice:"foo"`
}{},
wantNil: []string{"Client"},
},
{
name: "unknown type non-nil",
target: &struct {
Client unknownClient `service:"foo"`
}{Client: unknownClient(struct{}{})},
wantNonNil: []string{"Client"},
},
{
name: "known type",
knownServices: []string{"foo"},
target: &struct {
Client knownClient `service:"foo"`
}{},
wantNonNil: []string{"Client"},
},
{
name: "default encodings",
knownServices: []string{"jsontest", "rawtest"},
target: &struct {
JSON json.Client `service:"jsontest"`
Raw raw.Client `service:"rawtest"`
}{},
wantNonNil: []string{"JSON", "Raw"},
},
{
name: "unexported field",
target: &struct {
rawClient raw.Client `service:"rawtest"`
}{},
wantNil: []string{"rawClient"},
},
}
for _, tt := range tests {
cp := newMockClientConfigProvider(mockCtrl, tt.knownServices...)
assert.NotPanics(t, func() {
yarpc.InjectClients(cp, tt.target)
}, tt.name)
for _, fieldName := range tt.wantNil {
field := reflect.ValueOf(tt.target).Elem().FieldByName(fieldName)
assert.True(t, field.IsNil(), "expected %q to be nil", fieldName)
}
for _, fieldName := range tt.wantNonNil {
field := reflect.ValueOf(tt.target).Elem().FieldByName(fieldName)
assert.False(t, field.IsNil(), "expected %q to be non-nil", fieldName)
}
}
}
// newMockClientConfigProvider builds a MockClientConfigProvider which expects ClientConfig()
// calls for the given services and returns mock ClientConfigs for them.
func newMockClientConfigProvider(ctrl *gomock.Controller, services ...string) *transporttest.MockClientConfigProvider {
cp := transporttest.NewMockClientConfigProvider(ctrl)
for _, s := range services {
cp.EXPECT().ClientConfig(s).Return(transporttest.NewMockClientConfig(ctrl))
}
return cp
}