cloudflare/cloudflared

Public

mirrored fromhttps://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2020.6.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

dbconnect/sql_test.go

336lines · modecode

1package dbconnect
2
3import (
4 "context"
5 "database/sql"
6 "fmt"
7 "net/url"
8 "strings"
9 "testing"
10 "time"
11
12 "github.com/kshvakov/clickhouse"
13 "github.com/lib/pq"
14
15 "github.com/DATA-DOG/go-sqlmock"
16 "github.com/stretchr/testify/assert"
17)
18
19func TestNewSQLClient(t *testing.T) {
20 originURLs := []string{
21 "postgres://localhost",
22 "cockroachdb://localhost:1337",
23 "postgresql://user:pass@127.0.0.1",
24 "mysql://localhost",
25 "clickhouse://127.0.0.1:9000/?debug",
26 "sqlite3::memory:",
27 "file:test.db?cache=shared",
28 }
29
30 for _, originURL := range originURLs {
31 origin, _ := url.Parse(originURL)
32 _, err := NewSQLClient(context.Background(), origin)
33
34 assert.NoError(t, err, originURL)
35 }
36
37 originURLs = []string{
38 "",
39 "/",
40 "http://localhost",
41 "coolthing://user:pass@127.0.0.1",
42 }
43
44 for _, originURL := range originURLs {
45 origin, _ := url.Parse(originURL)
46 _, err := NewSQLClient(context.Background(), origin)
47
48 assert.Error(t, err, originURL)
49 }
50}
51
52func TestArgumentsSQL(t *testing.T) {
53 args := []Arguments{
54 Arguments{
55 Positional: []interface{}{
56 "val", 10, 3.14,
57 },
58 },
59 Arguments{
60 Named: map[string]interface{}{
61 "key": time.Unix(0, 0),
62 },
63 },
64 }
65
66 var nameType sql.NamedArg
67 for _, arg := range args {
68 arg.sql("")
69 for _, named := range arg.Positional {
70 assert.IsType(t, nameType, named)
71 }
72 }
73}
74
75func TestSQLArg(t *testing.T) {
76 tests := []struct {
77 key interface{}
78 val interface{}
79 dialect string
80 arg sql.NamedArg
81 }{
82 {"key", "val", "mssql", sql.Named("key", "val")},
83 {0, 1, "sqlite3", sql.Named("0", 1)},
84 {1, []string{"a", "b", "c"}, "postgres", sql.Named("1", pq.Array([]string{"a", "b", "c"}))},
85 {"in", []uint{0, 1}, "clickhouse", sql.Named("in", clickhouse.Array([]uint{0, 1}))},
86 {"", time.Unix(0, 0), "", sql.Named("", time.Unix(0, 0))},
87 }
88
89 for _, test := range tests {
90 arg := sqlArg(test.key, test.val, test.dialect)
91 assert.Equal(t, test.arg, arg, test.key)
92 }
93}
94
95func TestSQLIsolation(t *testing.T) {
96 tests := []struct {
97 str string
98 iso sql.IsolationLevel
99 }{
100 {"", sql.LevelDefault},
101 {"DEFAULT", sql.LevelDefault},
102 {"read_UNcommitted", sql.LevelReadUncommitted},
103 {"serializable", sql.LevelSerializable},
104 {"none", sql.IsolationLevel(-1)},
105 {"SNAP shot", -2},
106 {"blah", -2},
107 }
108
109 for _, test := range tests {
110 iso, err := sqlIsolation(test.str)
111
112 if test.iso < -1 {
113 assert.Error(t, err, test.str)
114 } else {
115 assert.NoError(t, err)
116 assert.Equal(t, test.iso, iso, test.str)
117 }
118 }
119}
120
121func TestSQLMode(t *testing.T) {
122 modes := []string{
123 "query",
124 "exec",
125 }
126
127 for _, mode := range modes {
128 actual, err := sqlMode(mode)
129
130 assert.NoError(t, err)
131 assert.Equal(t, strings.ToLower(mode), actual, mode)
132 }
133
134 modes = []string{
135 "",
136 "blah",
137 }
138
139 for _, mode := range modes {
140 _, err := sqlMode(mode)
141
142 assert.Error(t, err)
143 }
144}
145
146func helperRows(mockRows *sqlmock.Rows) *sql.Rows {
147 db, mock, _ := sqlmock.New()
148 mock.ExpectQuery("SELECT").WillReturnRows(mockRows)
149 rows, _ := db.Query("SELECT")
150 return rows
151}
152
153func TestSQLRows(t *testing.T) {
154 actual, err := sqlRows(helperRows(sqlmock.NewRows(
155 []string{"name", "age", "dept"}).
156 AddRow("alice", 19, "prod")))
157 expected := []map[string]interface{}{map[string]interface{}{
158 "name": "alice",
159 "age": int64(19),
160 "dept": "prod"}}
161
162 assert.NoError(t, err)
163 assert.ElementsMatch(t, expected, actual)
164}
165
166func TestSQLValue(t *testing.T) {
167 tests := []struct {
168 input interface{}
169 output interface{}
170 }{
171 {"hello", "hello"},
172 {1, 1},
173 {false, false},
174 {[]byte("random"), "random"},
175 {[]byte("{\"json\":true}"), map[string]interface{}{"json": true}},
176 {[]byte("[]"), []interface{}{}},
177 }
178
179 for _, test := range tests {
180 assert.Equal(t, test.output, sqlValue(test.input, nil), test.input)
181 }
182}
183
184func TestSQLResultFrom(t *testing.T) {
185 res := sqlResultFrom(sqlmock.NewResult(1, 2))
186 assert.Equal(t, sqlResult{1, 2}, res)
187
188 res = sqlResultFrom(sqlmock.NewErrorResult(fmt.Errorf("")))
189 assert.Equal(t, sqlResult{-1, -1}, res)
190}
191
192func helperSQLite3(t *testing.T) (context.Context, Client) {
193 t.Helper()
194
195 ctx := context.Background()
196 url, _ := url.Parse("file::memory:?cache=shared")
197
198 sqlite3, err := NewSQLClient(ctx, url)
199 assert.NoError(t, err)
200
201 return ctx, sqlite3
202}
203
204func TestPing(t *testing.T) {
205 ctx, sqlite3 := helperSQLite3(t)
206 err := sqlite3.Ping(ctx)
207
208 assert.NoError(t, err)
209}
210
211func TestSubmit(t *testing.T) {
212 ctx, sqlite3 := helperSQLite3(t)
213
214 res, err := sqlite3.Submit(ctx, &Command{
215 Statement: "CREATE TABLE t (a INTEGER, b FLOAT, c TEXT, d BLOB);",
216 Mode: "exec",
217 })
218 assert.NoError(t, err)
219 assert.Equal(t, sqlResult{0, 0}, res)
220
221 res, err = sqlite3.Submit(ctx, &Command{
222 Statement: "SELECT * FROM t;",
223 Mode: "query",
224 })
225 assert.NoError(t, err)
226 assert.Empty(t, res)
227
228 res, err = sqlite3.Submit(ctx, &Command{
229 Statement: "INSERT INTO t VALUES (?, ?, ?, ?);",
230 Mode: "exec",
231 Arguments: Arguments{
232 Positional: []interface{}{
233 1,
234 3.14,
235 "text",
236 "blob",
237 },
238 },
239 })
240 assert.NoError(t, err)
241 assert.Equal(t, sqlResult{1, 1}, res)
242
243 res, err = sqlite3.Submit(ctx, &Command{
244 Statement: "UPDATE t SET c = NULL;",
245 Mode: "exec",
246 })
247 assert.NoError(t, err)
248 assert.Equal(t, sqlResult{1, 1}, res)
249
250 res, err = sqlite3.Submit(ctx, &Command{
251 Statement: "SELECT * FROM t WHERE a = ?;",
252 Mode: "query",
253 Arguments: Arguments{
254 Positional: []interface{}{1},
255 },
256 })
257 assert.NoError(t, err)
258 assert.Len(t, res, 1)
259
260 resf, ok := res.([]map[string]interface{})
261 assert.True(t, ok)
262 assert.EqualValues(t, map[string]interface{}{
263 "a": int64(1),
264 "b": 3.14,
265 "c": nil,
266 "d": "blob",
267 }, resf[0])
268
269 res, err = sqlite3.Submit(ctx, &Command{
270 Statement: "DROP TABLE t;",
271 Mode: "exec",
272 })
273 assert.NoError(t, err)
274 assert.Equal(t, sqlResult{1, 1}, res)
275}
276
277func TestSubmitTransaction(t *testing.T) {
278 ctx, sqlite3 := helperSQLite3(t)
279
280 res, err := sqlite3.Submit(ctx, &Command{
281 Statement: "BEGIN;",
282 Mode: "exec",
283 })
284 assert.Error(t, err)
285 assert.Empty(t, res)
286
287 res, err = sqlite3.Submit(ctx, &Command{
288 Statement: "BEGIN; CREATE TABLE tt (a INT); COMMIT;",
289 Mode: "exec",
290 Isolation: "none",
291 })
292 assert.NoError(t, err)
293 assert.Equal(t, sqlResult{0, 0}, res)
294
295 rows, err := sqlite3.Submit(ctx, &Command{
296 Statement: "SELECT * FROM tt;",
297 Mode: "query",
298 Isolation: "repeatable_read",
299 })
300 assert.NoError(t, err)
301 assert.Empty(t, rows)
302}
303
304func TestSubmitTimeout(t *testing.T) {
305 ctx, sqlite3 := helperSQLite3(t)
306
307 res, err := sqlite3.Submit(ctx, &Command{
308 Statement: "SELECT * FROM t;",
309 Mode: "query",
310 Timeout: 1 * time.Nanosecond,
311 })
312 assert.Error(t, err)
313 assert.Empty(t, res)
314}
315
316func TestSubmitMode(t *testing.T) {
317 ctx, sqlite3 := helperSQLite3(t)
318
319 res, err := sqlite3.Submit(ctx, &Command{
320 Statement: "SELECT * FROM t;",
321 Mode: "notanoption",
322 })
323 assert.Error(t, err)
324 assert.Empty(t, res)
325}
326
327func TestSubmitEmpty(t *testing.T) {
328 ctx, sqlite3 := helperSQLite3(t)
329
330 res, err := sqlite3.Submit(ctx, &Command{
331 Statement: "; ; ; ;",
332 Mode: "query",
333 })
334 assert.Error(t, err)
335 assert.Empty(t, res)
336}
337