cloudflare/cloudflared

Public

mirrored from https://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2020.7.4

Branches

Tags

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

Clone

HTTPS

Download ZIP

dbconnect/sql_test.go

336lines · modeblame

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