forked from grafadruid/go-druid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdruid_test.go
205 lines (186 loc) · 5.65 KB
/
druid_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
204
205
package druid
import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
func TestSetBaseURLWithSuffix(t *testing.T) {
assert := assert.New(t)
d, err := NewClient("localhost:8082")
assert.Nil(err, "error should be nil")
assert.NotNil(d, "client should not be nil")
wantBaseURL, _ := url.ParseRequestURI("/")
err = d.setBaseURL("")
assert.Nil(err, "error should be nil")
assert.Equal(d.baseURL, wantBaseURL, "they should not be equal")
}
func TestNewClientWithSkipVerify(t *testing.T) {
assert := assert.New(t)
var druidOpts []ClientOption
druidOpts = append(druidOpts, WithSkipTLSVerify())
d, err := NewClient("localhost:8082", druidOpts...)
assert.Nil(err, "error should be nil")
assert.NotNil(d, "client should not be nil")
assert.True(d.http.HTTPClient.Transport.(*http.Transport).TLSClientConfig.InsecureSkipVerify, "insecure skip verify should be true")
}
// TODO: at some point use https://golang.org/src/crypto/tls/example_test.go this to create server with bad cert and test
func TestDefaultRetry(t *testing.T) {
type testCase struct {
statusCode int
response string
wantErr string
wantRetry bool
}
run := func(t *testing.T, tc testCase) {
// Given
ctx := context.Background()
resp := buildMockResp(tc.statusCode, tc.response)
// When
retry, err := defaultRetry(ctx, &resp, nil)
// Then
assert := assert.New(t)
if tc.wantErr != "" {
assert.Equal(tc.wantErr, err.Error())
} else {
assert.NoError(err)
}
assert.Equal(tc.wantRetry, retry)
}
testCases := map[string]testCase{
"OK": {
statusCode: 200,
response: `{ "id"": "12345"}`,
wantErr: "",
wantRetry: false,
},
"SQL parse error": {
statusCode: 400,
response: `{
"error": "SQL parse failed", "errorMessage" : "incorrect input."
}`,
wantErr: "failed to query Druid: {Error:SQL parse failed ErrorMessage:incorrect input. ErrorClass: Host:}",
wantRetry: false,
},
"SQL plan validatio error": {
statusCode: 400,
response: `{
"error": "Plan validation failed", "errorMessage" : "validation error."
}`,
wantErr: "failed to query Druid: {Error:Plan validation failed ErrorMessage:validation error. ErrorClass: Host:}",
wantRetry: false,
},
"Resource limit error": {
statusCode: 400,
response: `{
"error": "Resource limit exceeded", "errorMessage" : "Something bad happened."
}`,
wantErr: "error response from Druid: {Error:Resource limit exceeded ErrorMessage:Something bad happened. ErrorClass: Host:}",
wantRetry: true,
},
"Query capacity exceeded": {
statusCode: 429,
response: `{
"error": "Query capacity exceeded", "errorMessage" : "capacity exceeded."
}`,
wantErr: "error response from Druid: {Error:Query capacity exceeded ErrorMessage:capacity exceeded. ErrorClass: Host:}",
wantRetry: true,
},
"Unsupported operation": {
statusCode: 501,
response: `{
"error": "Unsupported operation", "errorMessage" : "wrong operation."
}`,
wantErr: "failed to query Druid: {Error:Unsupported operation ErrorMessage:wrong operation. ErrorClass: Host:}",
wantRetry: false,
},
"Query timeout": {
statusCode: 504,
response: `{
"error": "Query timeout", "errorMessage" : "timeout."
}`,
wantErr: "error response from Druid: {Error:Query timeout ErrorMessage:timeout. ErrorClass: Host:}",
wantRetry: true,
},
"Query cancelled": {
statusCode: 500,
response: `{
"error": "Query cancelled", "errorMessage" : "cancelled."
}`,
wantErr: "failed to query Druid: {Error:Query cancelled ErrorMessage:cancelled. ErrorClass: Host:}",
wantRetry: false,
},
"Unknown exception": {
statusCode: 500,
response: `{
"error": "Unknown exception", "errorMessage" : "failure."
}`,
wantErr: "failed to query Druid: {Error:Unknown exception ErrorMessage:failure. ErrorClass: Host:}",
wantRetry: false,
},
"Invalid json": {
statusCode: 500,
response: `invalid json`,
wantErr: "failed to read the response from Druid: invalid character 'i' looking for beginning of value",
wantRetry: true,
},
"Request body content type is not in JSON format": {
statusCode: 415,
response: `{
"error": "Request body content type is not in JSON format."
}`,
wantErr: "error response from Druid: {Error:Request body content type is not in JSON format. ErrorMessage: ErrorClass: Host:}",
wantRetry: true,
},
"Query Supervisor Status: Invalid supervisor ID": {
statusCode: 404,
response: `{
"error": "Invalid supervisor ID."
}`,
wantErr: "error response from Druid: {Error:Invalid supervisor ID. ErrorMessage: ErrorClass: Host:}",
wantRetry: true,
},
"Terminate Query Supervisor: Invalid supervisor ID": {
statusCode: 404,
response: `{
"error": "Invalid supervisor ID or supervisor not running."
}`,
wantErr: "error response from Druid: {Error:Invalid supervisor ID or supervisor not running. ErrorMessage: ErrorClass: Host:}",
wantRetry: true,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) { run(t, tc) })
}
}
func buildMockResp(statusCode int, body string) http.Response {
var st string
switch statusCode {
case 200:
st = "200 OK"
case 400:
st = "400 Bad Request"
case 404:
st = "404 Not Found"
case 415:
st = "415 Unsupported Media Type"
case 429:
st = "429 Too Many Requests"
case 500:
st = "500 Internal Server Error"
case 501:
st = "Not Implemented"
case 504:
st = "Gateway Timeout"
default:
panic(fmt.Errorf("Unsupported mock status code: %d", statusCode))
}
return http.Response{
Status: st, StatusCode: statusCode,
Body: io.NopCloser(strings.NewReader(body)),
}
}