utils_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. // Go MySQL Driver - A MySQL-Driver for Go's database/sql package
  2. //
  3. // Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public
  6. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  7. // You can obtain one at http://mozilla.org/MPL/2.0/.
  8. package mysql
  9. import (
  10. "bytes"
  11. "database/sql"
  12. "database/sql/driver"
  13. "encoding/binary"
  14. "testing"
  15. "time"
  16. )
  17. func TestLengthEncodedInteger(t *testing.T) {
  18. var integerTests = []struct {
  19. num uint64
  20. encoded []byte
  21. }{
  22. {0x0000000000000000, []byte{0x00}},
  23. {0x0000000000000012, []byte{0x12}},
  24. {0x00000000000000fa, []byte{0xfa}},
  25. {0x0000000000000100, []byte{0xfc, 0x00, 0x01}},
  26. {0x0000000000001234, []byte{0xfc, 0x34, 0x12}},
  27. {0x000000000000ffff, []byte{0xfc, 0xff, 0xff}},
  28. {0x0000000000010000, []byte{0xfd, 0x00, 0x00, 0x01}},
  29. {0x0000000000123456, []byte{0xfd, 0x56, 0x34, 0x12}},
  30. {0x0000000000ffffff, []byte{0xfd, 0xff, 0xff, 0xff}},
  31. {0x0000000001000000, []byte{0xfe, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}},
  32. {0x123456789abcdef0, []byte{0xfe, 0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12}},
  33. {0xffffffffffffffff, []byte{0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}},
  34. }
  35. for _, tst := range integerTests {
  36. num, isNull, numLen := readLengthEncodedInteger(tst.encoded)
  37. if isNull {
  38. t.Errorf("%x: expected %d, got NULL", tst.encoded, tst.num)
  39. }
  40. if num != tst.num {
  41. t.Errorf("%x: expected %d, got %d", tst.encoded, tst.num, num)
  42. }
  43. if numLen != len(tst.encoded) {
  44. t.Errorf("%x: expected size %d, got %d", tst.encoded, len(tst.encoded), numLen)
  45. }
  46. encoded := appendLengthEncodedInteger(nil, num)
  47. if !bytes.Equal(encoded, tst.encoded) {
  48. t.Errorf("%v: expected %x, got %x", num, tst.encoded, encoded)
  49. }
  50. }
  51. }
  52. func TestFormatBinaryDateTime(t *testing.T) {
  53. rawDate := [11]byte{}
  54. binary.LittleEndian.PutUint16(rawDate[:2], 1978) // years
  55. rawDate[2] = 12 // months
  56. rawDate[3] = 30 // days
  57. rawDate[4] = 15 // hours
  58. rawDate[5] = 46 // minutes
  59. rawDate[6] = 23 // seconds
  60. binary.LittleEndian.PutUint32(rawDate[7:], 987654) // microseconds
  61. expect := func(expected string, inlen, outlen uint8) {
  62. actual, _ := formatBinaryDateTime(rawDate[:inlen], outlen)
  63. bytes, ok := actual.([]byte)
  64. if !ok {
  65. t.Errorf("formatBinaryDateTime must return []byte, was %T", actual)
  66. }
  67. if string(bytes) != expected {
  68. t.Errorf(
  69. "expected %q, got %q for length in %d, out %d",
  70. expected, actual, inlen, outlen,
  71. )
  72. }
  73. }
  74. expect("0000-00-00", 0, 10)
  75. expect("0000-00-00 00:00:00", 0, 19)
  76. expect("1978-12-30", 4, 10)
  77. expect("1978-12-30 15:46:23", 7, 19)
  78. expect("1978-12-30 15:46:23.987654", 11, 26)
  79. }
  80. func TestFormatBinaryTime(t *testing.T) {
  81. expect := func(expected string, src []byte, outlen uint8) {
  82. actual, _ := formatBinaryTime(src, outlen)
  83. bytes, ok := actual.([]byte)
  84. if !ok {
  85. t.Errorf("formatBinaryDateTime must return []byte, was %T", actual)
  86. }
  87. if string(bytes) != expected {
  88. t.Errorf(
  89. "expected %q, got %q for src=%q and outlen=%d",
  90. expected, actual, src, outlen)
  91. }
  92. }
  93. // binary format:
  94. // sign (0: positive, 1: negative), days(4), hours, minutes, seconds, micro(4)
  95. // Zeros
  96. expect("00:00:00", []byte{}, 8)
  97. expect("00:00:00.0", []byte{}, 10)
  98. expect("00:00:00.000000", []byte{}, 15)
  99. // Without micro(4)
  100. expect("12:34:56", []byte{0, 0, 0, 0, 0, 12, 34, 56}, 8)
  101. expect("-12:34:56", []byte{1, 0, 0, 0, 0, 12, 34, 56}, 8)
  102. expect("12:34:56.00", []byte{0, 0, 0, 0, 0, 12, 34, 56}, 11)
  103. expect("24:34:56", []byte{0, 1, 0, 0, 0, 0, 34, 56}, 8)
  104. expect("-99:34:56", []byte{1, 4, 0, 0, 0, 3, 34, 56}, 8)
  105. expect("103079215103:34:56", []byte{0, 255, 255, 255, 255, 23, 34, 56}, 8)
  106. // With micro(4)
  107. expect("12:34:56.00", []byte{0, 0, 0, 0, 0, 12, 34, 56, 99, 0, 0, 0}, 11)
  108. expect("12:34:56.000099", []byte{0, 0, 0, 0, 0, 12, 34, 56, 99, 0, 0, 0}, 15)
  109. }
  110. func TestEscapeBackslash(t *testing.T) {
  111. expect := func(expected, value string) {
  112. actual := string(escapeBytesBackslash([]byte{}, []byte(value)))
  113. if actual != expected {
  114. t.Errorf(
  115. "expected %s, got %s",
  116. expected, actual,
  117. )
  118. }
  119. actual = string(escapeStringBackslash([]byte{}, value))
  120. if actual != expected {
  121. t.Errorf(
  122. "expected %s, got %s",
  123. expected, actual,
  124. )
  125. }
  126. }
  127. expect("foo\\0bar", "foo\x00bar")
  128. expect("foo\\nbar", "foo\nbar")
  129. expect("foo\\rbar", "foo\rbar")
  130. expect("foo\\Zbar", "foo\x1abar")
  131. expect("foo\\\"bar", "foo\"bar")
  132. expect("foo\\\\bar", "foo\\bar")
  133. expect("foo\\'bar", "foo'bar")
  134. }
  135. func TestEscapeQuotes(t *testing.T) {
  136. expect := func(expected, value string) {
  137. actual := string(escapeBytesQuotes([]byte{}, []byte(value)))
  138. if actual != expected {
  139. t.Errorf(
  140. "expected %s, got %s",
  141. expected, actual,
  142. )
  143. }
  144. actual = string(escapeStringQuotes([]byte{}, value))
  145. if actual != expected {
  146. t.Errorf(
  147. "expected %s, got %s",
  148. expected, actual,
  149. )
  150. }
  151. }
  152. expect("foo\x00bar", "foo\x00bar") // not affected
  153. expect("foo\nbar", "foo\nbar") // not affected
  154. expect("foo\rbar", "foo\rbar") // not affected
  155. expect("foo\x1abar", "foo\x1abar") // not affected
  156. expect("foo''bar", "foo'bar") // affected
  157. expect("foo\"bar", "foo\"bar") // not affected
  158. }
  159. func TestAtomicBool(t *testing.T) {
  160. var ab atomicBool
  161. if ab.IsSet() {
  162. t.Fatal("Expected value to be false")
  163. }
  164. ab.Set(true)
  165. if ab.value != 1 {
  166. t.Fatal("Set(true) did not set value to 1")
  167. }
  168. if !ab.IsSet() {
  169. t.Fatal("Expected value to be true")
  170. }
  171. ab.Set(true)
  172. if !ab.IsSet() {
  173. t.Fatal("Expected value to be true")
  174. }
  175. ab.Set(false)
  176. if ab.value != 0 {
  177. t.Fatal("Set(false) did not set value to 0")
  178. }
  179. if ab.IsSet() {
  180. t.Fatal("Expected value to be false")
  181. }
  182. ab.Set(false)
  183. if ab.IsSet() {
  184. t.Fatal("Expected value to be false")
  185. }
  186. if ab.TrySet(false) {
  187. t.Fatal("Expected TrySet(false) to fail")
  188. }
  189. if !ab.TrySet(true) {
  190. t.Fatal("Expected TrySet(true) to succeed")
  191. }
  192. if !ab.IsSet() {
  193. t.Fatal("Expected value to be true")
  194. }
  195. ab.Set(true)
  196. if !ab.IsSet() {
  197. t.Fatal("Expected value to be true")
  198. }
  199. if ab.TrySet(true) {
  200. t.Fatal("Expected TrySet(true) to fail")
  201. }
  202. if !ab.TrySet(false) {
  203. t.Fatal("Expected TrySet(false) to succeed")
  204. }
  205. if ab.IsSet() {
  206. t.Fatal("Expected value to be false")
  207. }
  208. ab._noCopy.Lock() // we've "tested" it ¯\_(ツ)_/¯
  209. }
  210. func TestAtomicError(t *testing.T) {
  211. var ae atomicError
  212. if ae.Value() != nil {
  213. t.Fatal("Expected value to be nil")
  214. }
  215. ae.Set(ErrMalformPkt)
  216. if v := ae.Value(); v != ErrMalformPkt {
  217. if v == nil {
  218. t.Fatal("Value is still nil")
  219. }
  220. t.Fatal("Error did not match")
  221. }
  222. ae.Set(ErrPktSync)
  223. if ae.Value() == ErrMalformPkt {
  224. t.Fatal("Error still matches old error")
  225. }
  226. if v := ae.Value(); v != ErrPktSync {
  227. t.Fatal("Error did not match")
  228. }
  229. }
  230. func TestIsolationLevelMapping(t *testing.T) {
  231. data := []struct {
  232. level driver.IsolationLevel
  233. expected string
  234. }{
  235. {
  236. level: driver.IsolationLevel(sql.LevelReadCommitted),
  237. expected: "READ COMMITTED",
  238. },
  239. {
  240. level: driver.IsolationLevel(sql.LevelRepeatableRead),
  241. expected: "REPEATABLE READ",
  242. },
  243. {
  244. level: driver.IsolationLevel(sql.LevelReadUncommitted),
  245. expected: "READ UNCOMMITTED",
  246. },
  247. {
  248. level: driver.IsolationLevel(sql.LevelSerializable),
  249. expected: "SERIALIZABLE",
  250. },
  251. }
  252. for i, td := range data {
  253. if actual, err := mapIsolationLevel(td.level); actual != td.expected || err != nil {
  254. t.Fatal(i, td.expected, actual, err)
  255. }
  256. }
  257. // check unsupported mapping
  258. expectedErr := "mysql: unsupported isolation level: 7"
  259. actual, err := mapIsolationLevel(driver.IsolationLevel(sql.LevelLinearizable))
  260. if actual != "" || err == nil {
  261. t.Fatal("Expected error on unsupported isolation level")
  262. }
  263. if err.Error() != expectedErr {
  264. t.Fatalf("Expected error to be %q, got %q", expectedErr, err)
  265. }
  266. }
  267. func TestAppendDateTime(t *testing.T) {
  268. tests := []struct {
  269. t time.Time
  270. str string
  271. }{
  272. {
  273. t: time.Date(1234, 5, 6, 0, 0, 0, 0, time.UTC),
  274. str: "1234-05-06",
  275. },
  276. {
  277. t: time.Date(4567, 12, 31, 12, 0, 0, 0, time.UTC),
  278. str: "4567-12-31 12:00:00",
  279. },
  280. {
  281. t: time.Date(2020, 5, 30, 12, 34, 0, 0, time.UTC),
  282. str: "2020-05-30 12:34:00",
  283. },
  284. {
  285. t: time.Date(2020, 5, 30, 12, 34, 56, 0, time.UTC),
  286. str: "2020-05-30 12:34:56",
  287. },
  288. {
  289. t: time.Date(2020, 5, 30, 22, 33, 44, 123000000, time.UTC),
  290. str: "2020-05-30 22:33:44.123",
  291. },
  292. {
  293. t: time.Date(2020, 5, 30, 22, 33, 44, 123456000, time.UTC),
  294. str: "2020-05-30 22:33:44.123456",
  295. },
  296. {
  297. t: time.Date(2020, 5, 30, 22, 33, 44, 123456789, time.UTC),
  298. str: "2020-05-30 22:33:44.123456789",
  299. },
  300. {
  301. t: time.Date(9999, 12, 31, 23, 59, 59, 999999999, time.UTC),
  302. str: "9999-12-31 23:59:59.999999999",
  303. },
  304. {
  305. t: time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC),
  306. str: "0001-01-01",
  307. },
  308. }
  309. for _, v := range tests {
  310. buf := make([]byte, 0, 32)
  311. buf, _ = appendDateTime(buf, v.t)
  312. if str := string(buf); str != v.str {
  313. t.Errorf("appendDateTime(%v), have: %s, want: %s", v.t, str, v.str)
  314. }
  315. }
  316. // year out of range
  317. {
  318. v := time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC)
  319. buf := make([]byte, 0, 32)
  320. _, err := appendDateTime(buf, v)
  321. if err == nil {
  322. t.Error("want an error")
  323. return
  324. }
  325. }
  326. {
  327. v := time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC)
  328. buf := make([]byte, 0, 32)
  329. _, err := appendDateTime(buf, v)
  330. if err == nil {
  331. t.Error("want an error")
  332. return
  333. }
  334. }
  335. }
  336. func TestParseDateTime(t *testing.T) {
  337. cases := []struct {
  338. name string
  339. str string
  340. }{
  341. {
  342. name: "parse date",
  343. str: "2020-05-13",
  344. },
  345. {
  346. name: "parse null date",
  347. str: sDate0,
  348. },
  349. {
  350. name: "parse datetime",
  351. str: "2020-05-13 21:30:45",
  352. },
  353. {
  354. name: "parse null datetime",
  355. str: sDateTime0,
  356. },
  357. {
  358. name: "parse datetime nanosec 1-digit",
  359. str: "2020-05-25 23:22:01.1",
  360. },
  361. {
  362. name: "parse datetime nanosec 2-digits",
  363. str: "2020-05-25 23:22:01.15",
  364. },
  365. {
  366. name: "parse datetime nanosec 3-digits",
  367. str: "2020-05-25 23:22:01.159",
  368. },
  369. {
  370. name: "parse datetime nanosec 4-digits",
  371. str: "2020-05-25 23:22:01.1594",
  372. },
  373. {
  374. name: "parse datetime nanosec 5-digits",
  375. str: "2020-05-25 23:22:01.15949",
  376. },
  377. {
  378. name: "parse datetime nanosec 6-digits",
  379. str: "2020-05-25 23:22:01.159491",
  380. },
  381. }
  382. for _, loc := range []*time.Location{
  383. time.UTC,
  384. time.FixedZone("test", 8*60*60),
  385. } {
  386. for _, cc := range cases {
  387. t.Run(cc.name+"-"+loc.String(), func(t *testing.T) {
  388. var want time.Time
  389. if cc.str != sDate0 && cc.str != sDateTime0 {
  390. var err error
  391. want, err = time.ParseInLocation(timeFormat[:len(cc.str)], cc.str, loc)
  392. if err != nil {
  393. t.Fatal(err)
  394. }
  395. }
  396. got, err := parseDateTime([]byte(cc.str), loc)
  397. if err != nil {
  398. t.Fatal(err)
  399. }
  400. if !want.Equal(got) {
  401. t.Fatalf("want: %v, but got %v", want, got)
  402. }
  403. })
  404. }
  405. }
  406. }
  407. func TestParseDateTimeFail(t *testing.T) {
  408. cases := []struct {
  409. name string
  410. str string
  411. wantErr string
  412. }{
  413. {
  414. name: "parse invalid time",
  415. str: "hello",
  416. wantErr: "invalid time bytes: hello",
  417. },
  418. {
  419. name: "parse year",
  420. str: "000!-00-00 00:00:00.000000",
  421. wantErr: "not [0-9]",
  422. },
  423. {
  424. name: "parse month",
  425. str: "0000-!0-00 00:00:00.000000",
  426. wantErr: "not [0-9]",
  427. },
  428. {
  429. name: `parse "-" after parsed year`,
  430. str: "0000:00-00 00:00:00.000000",
  431. wantErr: "bad value for field: `:`",
  432. },
  433. {
  434. name: `parse "-" after parsed month`,
  435. str: "0000-00:00 00:00:00.000000",
  436. wantErr: "bad value for field: `:`",
  437. },
  438. {
  439. name: `parse " " after parsed date`,
  440. str: "0000-00-00+00:00:00.000000",
  441. wantErr: "bad value for field: `+`",
  442. },
  443. {
  444. name: `parse ":" after parsed date`,
  445. str: "0000-00-00 00-00:00.000000",
  446. wantErr: "bad value for field: `-`",
  447. },
  448. {
  449. name: `parse ":" after parsed hour`,
  450. str: "0000-00-00 00:00-00.000000",
  451. wantErr: "bad value for field: `-`",
  452. },
  453. {
  454. name: `parse "." after parsed sec`,
  455. str: "0000-00-00 00:00:00?000000",
  456. wantErr: "bad value for field: `?`",
  457. },
  458. }
  459. for _, cc := range cases {
  460. t.Run(cc.name, func(t *testing.T) {
  461. got, err := parseDateTime([]byte(cc.str), time.UTC)
  462. if err == nil {
  463. t.Fatal("want error")
  464. }
  465. if cc.wantErr != err.Error() {
  466. t.Fatalf("want `%s`, but got `%s`", cc.wantErr, err)
  467. }
  468. if !got.IsZero() {
  469. t.Fatal("want zero time")
  470. }
  471. })
  472. }
  473. }