PageRenderTime 75ms CodeModel.GetById 11ms app.highlight 59ms RepoModel.GetById 1ms app.codeStats 1ms

/Godeps/_workspace/src/github.com/ziutek/mymysql/native/bind_test.go

https://gitlab.com/voxxit/gogeoip2
Go | 403 lines | 348 code | 53 blank | 2 comment | 23 complexity | 6222ae77be007b344996574056ed104c MD5 | raw file
  1package native
  2
  3import (
  4	"bufio"
  5	"bytes"
  6	"github.com/ziutek/mymysql/mysql"
  7	"math"
  8	"reflect"
  9	"strconv"
 10	"testing"
 11	"time"
 12)
 13
 14var (
 15	Bytes  = []byte("Ala ma Kota!")
 16	String = "ssss" //"A kot ma AlÄ™!"
 17	blob   = mysql.Blob{1, 2, 3}
 18	dateT  = time.Date(2010, 12, 30, 17, 21, 01, 0, time.Local)
 19	tstamp = mysql.Timestamp{dateT.Add(1e9)}
 20	date   = mysql.Date{Year: 2011, Month: 2, Day: 3}
 21	tim    = -time.Duration((5*24*3600+4*3600+3*60+2)*1e9 + 1)
 22	bol    = true
 23
 24	pBytes  *[]byte
 25	pString *string
 26	pBlob   *mysql.Blob
 27	pDateT  *time.Time
 28	pTstamp *mysql.Timestamp
 29	pDate   *mysql.Date
 30	pTim    *time.Duration
 31	pBol    *bool
 32
 33	raw = mysql.Raw{MYSQL_TYPE_INT24, &[]byte{3, 2, 1, 0}}
 34
 35	Int8   = int8(1)
 36	Uint8  = uint8(2)
 37	Int16  = int16(3)
 38	Uint16 = uint16(4)
 39	Int32  = int32(5)
 40	Uint32 = uint32(6)
 41	Int64  = int64(0x7000100020003001)
 42	Uint64 = uint64(0xffff0000ffff0000)
 43	Int    = int(7)
 44	Uint   = uint(8)
 45
 46	Float32 = float32(1e10)
 47	Float64 = 256e256
 48
 49	pInt8    *int8
 50	pUint8   *uint8
 51	pInt16   *int16
 52	pUint16  *uint16
 53	pInt32   *int32
 54	pUint32  *uint32
 55	pInt64   *int64
 56	pUint64  *uint64
 57	pInt     *int
 58	pUint    *uint
 59	pFloat32 *float32
 60	pFloat64 *float64
 61)
 62
 63type BindTest struct {
 64	val    interface{}
 65	typ    uint16
 66	length int
 67}
 68
 69func intSize() int {
 70	switch strconv.IntSize {
 71	case 32:
 72		return 4
 73	case 64:
 74		return 8
 75	}
 76	panic("bad int size")
 77}
 78
 79func intType() uint16 {
 80	switch strconv.IntSize {
 81	case 32:
 82		return MYSQL_TYPE_LONG
 83	case 64:
 84		return MYSQL_TYPE_LONGLONG
 85	}
 86	panic("bad int size")
 87
 88}
 89
 90var bindTests = []BindTest{
 91	BindTest{nil, MYSQL_TYPE_NULL, 0},
 92
 93	BindTest{Bytes, MYSQL_TYPE_VAR_STRING, -1},
 94	BindTest{String, MYSQL_TYPE_STRING, -1},
 95	BindTest{blob, MYSQL_TYPE_BLOB, -1},
 96	BindTest{dateT, MYSQL_TYPE_DATETIME, -1},
 97	BindTest{tstamp, MYSQL_TYPE_TIMESTAMP, -1},
 98	BindTest{date, MYSQL_TYPE_DATE, -1},
 99	BindTest{tim, MYSQL_TYPE_TIME, -1},
100	BindTest{bol, MYSQL_TYPE_TINY, -1},
101
102	BindTest{&Bytes, MYSQL_TYPE_VAR_STRING, -1},
103	BindTest{&String, MYSQL_TYPE_STRING, -1},
104	BindTest{&blob, MYSQL_TYPE_BLOB, -1},
105	BindTest{&dateT, MYSQL_TYPE_DATETIME, -1},
106	BindTest{&tstamp, MYSQL_TYPE_TIMESTAMP, -1},
107	BindTest{&date, MYSQL_TYPE_DATE, -1},
108	BindTest{&tim, MYSQL_TYPE_TIME, -1},
109
110	BindTest{pBytes, MYSQL_TYPE_VAR_STRING, -1},
111	BindTest{pString, MYSQL_TYPE_STRING, -1},
112	BindTest{pBlob, MYSQL_TYPE_BLOB, -1},
113	BindTest{pDateT, MYSQL_TYPE_DATETIME, -1},
114	BindTest{pTstamp, MYSQL_TYPE_TIMESTAMP, -1},
115	BindTest{pDate, MYSQL_TYPE_DATE, -1},
116	BindTest{pTim, MYSQL_TYPE_TIME, -1},
117	BindTest{pBol, MYSQL_TYPE_TINY, -1},
118
119	BindTest{raw, MYSQL_TYPE_INT24, -1},
120
121	BindTest{Int8, MYSQL_TYPE_TINY, 1},
122	BindTest{Int16, MYSQL_TYPE_SHORT, 2},
123	BindTest{Int32, MYSQL_TYPE_LONG, 4},
124	BindTest{Int64, MYSQL_TYPE_LONGLONG, 8},
125	BindTest{Int, intType(), intSize()},
126
127	BindTest{&Int8, MYSQL_TYPE_TINY, 1},
128	BindTest{&Int16, MYSQL_TYPE_SHORT, 2},
129	BindTest{&Int32, MYSQL_TYPE_LONG, 4},
130	BindTest{&Int64, MYSQL_TYPE_LONGLONG, 8},
131	BindTest{&Int, intType(), intSize()},
132
133	BindTest{pInt8, MYSQL_TYPE_TINY, 1},
134	BindTest{pInt16, MYSQL_TYPE_SHORT, 2},
135	BindTest{pInt32, MYSQL_TYPE_LONG, 4},
136	BindTest{pInt64, MYSQL_TYPE_LONGLONG, 8},
137	BindTest{pInt, intType(), intSize()},
138
139	BindTest{Uint8, MYSQL_TYPE_TINY | MYSQL_UNSIGNED_MASK, 1},
140	BindTest{Uint16, MYSQL_TYPE_SHORT | MYSQL_UNSIGNED_MASK, 2},
141	BindTest{Uint32, MYSQL_TYPE_LONG | MYSQL_UNSIGNED_MASK, 4},
142	BindTest{Uint64, MYSQL_TYPE_LONGLONG | MYSQL_UNSIGNED_MASK, 8},
143	BindTest{Uint, intType() | MYSQL_UNSIGNED_MASK, intSize()},
144
145	BindTest{&Uint8, MYSQL_TYPE_TINY | MYSQL_UNSIGNED_MASK, 1},
146	BindTest{&Uint16, MYSQL_TYPE_SHORT | MYSQL_UNSIGNED_MASK, 2},
147	BindTest{&Uint32, MYSQL_TYPE_LONG | MYSQL_UNSIGNED_MASK, 4},
148	BindTest{&Uint64, MYSQL_TYPE_LONGLONG | MYSQL_UNSIGNED_MASK, 8},
149	BindTest{&Uint, intType() | MYSQL_UNSIGNED_MASK, intSize()},
150
151	BindTest{pUint8, MYSQL_TYPE_TINY | MYSQL_UNSIGNED_MASK, 1},
152	BindTest{pUint16, MYSQL_TYPE_SHORT | MYSQL_UNSIGNED_MASK, 2},
153	BindTest{pUint32, MYSQL_TYPE_LONG | MYSQL_UNSIGNED_MASK, 4},
154	BindTest{pUint64, MYSQL_TYPE_LONGLONG | MYSQL_UNSIGNED_MASK, 8},
155	BindTest{pUint, intType() | MYSQL_UNSIGNED_MASK, intSize()},
156
157	BindTest{Float32, MYSQL_TYPE_FLOAT, 4},
158	BindTest{Float64, MYSQL_TYPE_DOUBLE, 8},
159
160	BindTest{&Float32, MYSQL_TYPE_FLOAT, 4},
161	BindTest{&Float64, MYSQL_TYPE_DOUBLE, 8},
162}
163
164func makeAddressable(v reflect.Value) reflect.Value {
165	if v.IsValid() {
166		// Make an addresable value
167		av := reflect.New(v.Type()).Elem()
168		av.Set(v)
169		v = av
170	}
171	return v
172}
173
174func TestBind(t *testing.T) {
175	for _, test := range bindTests {
176		v := makeAddressable(reflect.ValueOf(test.val))
177		val := bindValue(v)
178		if val.typ != test.typ || val.length != test.length {
179			t.Errorf(
180				"Type: %s exp=0x%x res=0x%x Len: exp=%d res=%d",
181				reflect.TypeOf(test.val), test.typ, val.typ, test.length,
182				val.length,
183			)
184		}
185	}
186}
187
188type WriteTest struct {
189	val interface{}
190	exp []byte
191}
192
193var writeTest []WriteTest
194
195func encodeU16(v uint16) []byte {
196	buf := make([]byte, 2)
197	EncodeU16(buf, v)
198	return buf
199}
200
201func encodeU24(v uint32) []byte {
202	buf := make([]byte, 3)
203	EncodeU24(buf, v)
204	return buf
205}
206
207func encodeU32(v uint32) []byte {
208	buf := make([]byte, 4)
209	EncodeU32(buf, v)
210	return buf
211}
212
213func encodeU64(v uint64) []byte {
214	buf := make([]byte, 8)
215	EncodeU64(buf, v)
216	return buf
217}
218
219func encodeDuration(d time.Duration) []byte {
220	buf := make([]byte, 13)
221	n := EncodeDuration(buf, d)
222	return buf[:n]
223}
224
225func encodeTime(t time.Time) []byte {
226	buf := make([]byte, 12)
227	n := EncodeTime(buf, t)
228	return buf[:n]
229}
230
231func encodeDate(d mysql.Date) []byte {
232	buf := make([]byte, 5)
233	n := EncodeDate(buf, d)
234	return buf[:n]
235}
236
237func encodeUint(u uint) []byte {
238	switch strconv.IntSize {
239	case 32:
240		return encodeU32(uint32(u))
241	case 64:
242		return encodeU64(uint64(u))
243	}
244	panic("bad int size")
245
246}
247
248func init() {
249	b := make([]byte, 64*1024)
250	for ii := range b {
251		b[ii] = byte(ii)
252	}
253	blob = mysql.Blob(b)
254
255	writeTest = []WriteTest{
256		WriteTest{Bytes, append([]byte{byte(len(Bytes))}, Bytes...)},
257		WriteTest{String, append([]byte{byte(len(String))}, []byte(String)...)},
258		WriteTest{pBytes, nil},
259		WriteTest{pString, nil},
260		WriteTest{
261			blob,
262			append(
263				append([]byte{253}, byte(len(blob)), byte(len(blob)>>8), byte(len(blob)>>16)),
264				[]byte(blob)...),
265		},
266		WriteTest{
267			dateT,
268			[]byte{
269				7, byte(dateT.Year()), byte(dateT.Year() >> 8),
270				byte(dateT.Month()),
271				byte(dateT.Day()), byte(dateT.Hour()), byte(dateT.Minute()),
272				byte(dateT.Second()),
273			},
274		},
275		WriteTest{
276			&dateT,
277			[]byte{
278				7, byte(dateT.Year()), byte(dateT.Year() >> 8),
279				byte(dateT.Month()),
280				byte(dateT.Day()), byte(dateT.Hour()), byte(dateT.Minute()),
281				byte(dateT.Second()),
282			},
283		},
284		WriteTest{
285			date,
286			[]byte{
287				4, byte(date.Year), byte(date.Year >> 8), byte(date.Month),
288				byte(date.Day),
289			},
290		},
291		WriteTest{
292			&date,
293			[]byte{
294				4, byte(date.Year), byte(date.Year >> 8), byte(date.Month),
295				byte(date.Day),
296			},
297		},
298		WriteTest{
299			tim,
300			[]byte{12, 1, 5, 0, 0, 0, 4, 3, 2, 1, 0, 0, 0},
301		},
302		WriteTest{
303			&tim,
304			[]byte{12, 1, 5, 0, 0, 0, 4, 3, 2, 1, 0, 0, 0},
305		},
306		WriteTest{bol, []byte{1}},
307		WriteTest{&bol, []byte{1}},
308		WriteTest{pBol, nil},
309
310		WriteTest{dateT, encodeTime(dateT)},
311		WriteTest{&dateT, encodeTime(dateT)},
312		WriteTest{pDateT, nil},
313
314		WriteTest{tstamp, encodeTime(tstamp.Time)},
315		WriteTest{&tstamp, encodeTime(tstamp.Time)},
316		WriteTest{pTstamp, nil},
317
318		WriteTest{date, encodeDate(date)},
319		WriteTest{&date, encodeDate(date)},
320		WriteTest{pDate, nil},
321
322		WriteTest{tim, encodeDuration(tim)},
323		WriteTest{&tim, encodeDuration(tim)},
324		WriteTest{pTim, nil},
325
326		WriteTest{Int, encodeUint(uint(Int))},
327		WriteTest{Int16, encodeU16(uint16(Int16))},
328		WriteTest{Int32, encodeU32(uint32(Int32))},
329		WriteTest{Int64, encodeU64(uint64(Int64))},
330
331		WriteTest{Uint, encodeUint(Uint)},
332		WriteTest{Uint16, encodeU16(Uint16)},
333		WriteTest{Uint32, encodeU32(Uint32)},
334		WriteTest{Uint64, encodeU64(Uint64)},
335
336		WriteTest{&Int, encodeUint(uint(Int))},
337		WriteTest{&Int16, encodeU16(uint16(Int16))},
338		WriteTest{&Int32, encodeU32(uint32(Int32))},
339		WriteTest{&Int64, encodeU64(uint64(Int64))},
340
341		WriteTest{&Uint, encodeUint(Uint)},
342		WriteTest{&Uint16, encodeU16(Uint16)},
343		WriteTest{&Uint32, encodeU32(Uint32)},
344		WriteTest{&Uint64, encodeU64(Uint64)},
345
346		WriteTest{pInt, nil},
347		WriteTest{pInt16, nil},
348		WriteTest{pInt32, nil},
349		WriteTest{pInt64, nil},
350
351		WriteTest{Float32, encodeU32(math.Float32bits(Float32))},
352		WriteTest{Float64, encodeU64(math.Float64bits(Float64))},
353
354		WriteTest{&Float32, encodeU32(math.Float32bits(Float32))},
355		WriteTest{&Float64, encodeU64(math.Float64bits(Float64))},
356
357		WriteTest{pFloat32, nil},
358		WriteTest{pFloat64, nil},
359	}
360}
361
362func TestWrite(t *testing.T) {
363	buf := new(bytes.Buffer)
364	for _, test := range writeTest {
365		buf.Reset()
366		var seq byte
367		pw := &pktWriter{
368			wr:       bufio.NewWriter(buf),
369			seq:      &seq,
370			to_write: len(test.exp),
371		}
372		v := makeAddressable(reflect.ValueOf(test.val))
373		val := bindValue(v)
374		pw.writeValue(&val)
375		if !reflect.Indirect(v).IsValid() && len(buf.Bytes()) == 0 {
376			// writeValue writes nothing for nil
377			continue
378		}
379		if len(buf.Bytes()) != len(test.exp)+4 || !bytes.Equal(buf.Bytes()[4:], test.exp) || val.Len() != len(test.exp) {
380			t.Fatalf("%s - exp_len=%d res_len=%d exp: %v res: %v",
381				reflect.TypeOf(test.val), len(test.exp), val.Len(),
382				test.exp, buf.Bytes(),
383			)
384		}
385	}
386}
387
388func TestEscapeString(t *testing.T) {
389	txt := " \000 \n \r \\ ' \" \032 "
390	exp := ` \0 \n \r \\ \' \" \Z `
391	out := escapeString(txt)
392	if out != exp {
393		t.Fatalf("escapeString: ret='%s' exp='%s'", out, exp)
394	}
395}
396func TestEscapeQuotes(t *testing.T) {
397	txt := " '' '' ' ' ' "
398	exp := ` '''' '''' '' '' '' `
399	out := escapeQuotes(txt)
400	if out != exp {
401		t.Fatalf("escapeString: ret='%s' exp='%s'", out, exp)
402	}
403}