/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

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