marshal_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. package gocql
  2. import (
  3. "bytes"
  4. "math"
  5. "math/big"
  6. "net"
  7. "reflect"
  8. "strings"
  9. "testing"
  10. "time"
  11. "speter.net/go/exp/math/dec/inf"
  12. )
  13. var marshalTests = []struct {
  14. Info *TypeInfo
  15. Data []byte
  16. Value interface{}
  17. }{
  18. {
  19. &TypeInfo{Type: TypeVarchar},
  20. []byte("hello world"),
  21. []byte("hello world"),
  22. },
  23. {
  24. &TypeInfo{Type: TypeVarchar},
  25. []byte("hello world"),
  26. "hello world",
  27. },
  28. {
  29. &TypeInfo{Type: TypeVarchar},
  30. []byte(nil),
  31. []byte(nil),
  32. },
  33. {
  34. &TypeInfo{Type: TypeVarchar},
  35. []byte("hello world"),
  36. MyString("hello world"),
  37. },
  38. {
  39. &TypeInfo{Type: TypeVarchar},
  40. []byte("HELLO WORLD"),
  41. CustomString("hello world"),
  42. },
  43. {
  44. &TypeInfo{Type: TypeBlob},
  45. []byte("hello\x00"),
  46. []byte("hello\x00"),
  47. },
  48. {
  49. &TypeInfo{Type: TypeBlob},
  50. []byte(nil),
  51. []byte(nil),
  52. },
  53. {
  54. &TypeInfo{Type: TypeTimeUUID},
  55. []byte{0x3d, 0xcd, 0x98, 0x0, 0xf3, 0xd9, 0x11, 0xbf, 0x86, 0xd4, 0xb8, 0xe8, 0x56, 0x2c, 0xc, 0xd0},
  56. func() UUID {
  57. x, _ := UUIDFromBytes([]byte{0x3d, 0xcd, 0x98, 0x0, 0xf3, 0xd9, 0x11, 0xbf, 0x86, 0xd4, 0xb8, 0xe8, 0x56, 0x2c, 0xc, 0xd0})
  58. return x
  59. }(),
  60. },
  61. {
  62. &TypeInfo{Type: TypeInt},
  63. []byte("\x00\x00\x00\x00"),
  64. 0,
  65. },
  66. {
  67. &TypeInfo{Type: TypeInt},
  68. []byte("\x01\x02\x03\x04"),
  69. int(16909060),
  70. },
  71. {
  72. &TypeInfo{Type: TypeInt},
  73. []byte("\x80\x00\x00\x00"),
  74. int32(math.MinInt32),
  75. },
  76. {
  77. &TypeInfo{Type: TypeInt},
  78. []byte("\x7f\xff\xff\xff"),
  79. int32(math.MaxInt32),
  80. },
  81. {
  82. &TypeInfo{Type: TypeBigInt},
  83. []byte("\x00\x00\x00\x00\x00\x00\x00\x00"),
  84. 0,
  85. },
  86. {
  87. &TypeInfo{Type: TypeBigInt},
  88. []byte("\x01\x02\x03\x04\x05\x06\x07\x08"),
  89. 72623859790382856,
  90. },
  91. {
  92. &TypeInfo{Type: TypeBigInt},
  93. []byte("\x80\x00\x00\x00\x00\x00\x00\x00"),
  94. int64(math.MinInt64),
  95. },
  96. {
  97. &TypeInfo{Type: TypeBigInt},
  98. []byte("\x7f\xff\xff\xff\xff\xff\xff\xff"),
  99. int64(math.MaxInt64),
  100. },
  101. {
  102. &TypeInfo{Type: TypeBoolean},
  103. []byte("\x00"),
  104. false,
  105. },
  106. {
  107. &TypeInfo{Type: TypeBoolean},
  108. []byte("\x01"),
  109. true,
  110. },
  111. {
  112. &TypeInfo{Type: TypeFloat},
  113. []byte("\x40\x49\x0f\xdb"),
  114. float32(3.14159265),
  115. },
  116. {
  117. &TypeInfo{Type: TypeDouble},
  118. []byte("\x40\x09\x21\xfb\x53\xc8\xd4\xf1"),
  119. float64(3.14159265),
  120. },
  121. {
  122. &TypeInfo{Type: TypeDecimal},
  123. []byte("\x00\x00\x00\x00\x00"),
  124. inf.NewDec(0, 0),
  125. },
  126. {
  127. &TypeInfo{Type: TypeDecimal},
  128. []byte("\x00\x00\x00\x00\x64"),
  129. inf.NewDec(100, 0),
  130. },
  131. {
  132. &TypeInfo{Type: TypeDecimal},
  133. []byte("\x00\x00\x00\x02\x19"),
  134. decimalize("0.25"),
  135. },
  136. {
  137. &TypeInfo{Type: TypeDecimal},
  138. []byte("\x00\x00\x00\x13\xD5\a;\x20\x14\xA2\x91"),
  139. decimalize("-0.0012095473475870063"), // From the iconara/cql-rb test suite
  140. },
  141. {
  142. &TypeInfo{Type: TypeDecimal},
  143. []byte("\x00\x00\x00\x13*\xF8\xC4\xDF\xEB]o"),
  144. decimalize("0.0012095473475870063"), // From the iconara/cql-rb test suite
  145. },
  146. {
  147. &TypeInfo{Type: TypeDecimal},
  148. []byte("\x00\x00\x00\x12\xF2\xD8\x02\xB6R\x7F\x99\xEE\x98#\x99\xA9V"),
  149. decimalize("-1042342234234.123423435647768234"), // From the iconara/cql-rb test suite
  150. },
  151. {
  152. &TypeInfo{Type: TypeDecimal},
  153. []byte("\x00\x00\x00\r\nJ\x04\"^\x91\x04\x8a\xb1\x18\xfe"),
  154. decimalize("1243878957943.1234124191998"), // From the datastax/python-driver test suite
  155. },
  156. {
  157. &TypeInfo{Type: TypeDecimal},
  158. []byte("\x00\x00\x00\x06\xe5\xde]\x98Y"),
  159. decimalize("-112233.441191"), // From the datastax/python-driver test suite
  160. },
  161. {
  162. &TypeInfo{Type: TypeDecimal},
  163. []byte("\x00\x00\x00\x14\x00\xfa\xce"),
  164. decimalize("0.00000000000000064206"), // From the datastax/python-driver test suite
  165. },
  166. {
  167. &TypeInfo{Type: TypeDecimal},
  168. []byte("\x00\x00\x00\x14\xff\x052"),
  169. decimalize("-0.00000000000000064206"), // From the datastax/python-driver test suite
  170. },
  171. {
  172. &TypeInfo{Type: TypeDecimal},
  173. []byte("\xff\xff\xff\x9c\x00\xfa\xce"),
  174. inf.NewDec(64206, -100), // From the datastax/python-driver test suite
  175. },
  176. {
  177. &TypeInfo{Type: TypeTimestamp},
  178. []byte("\x00\x00\x01\x40\x77\x16\xe1\xb8"),
  179. time.Date(2013, time.August, 13, 9, 52, 3, 0, time.UTC),
  180. },
  181. {
  182. &TypeInfo{Type: TypeTimestamp},
  183. []byte("\x00\x00\x01\x40\x77\x16\xe1\xb8"),
  184. int64(1376387523000),
  185. },
  186. {
  187. &TypeInfo{Type: TypeList, Elem: &TypeInfo{Type: TypeInt}},
  188. []byte("\x00\x02\x00\x04\x00\x00\x00\x01\x00\x04\x00\x00\x00\x02"),
  189. []int{1, 2},
  190. },
  191. {
  192. &TypeInfo{Type: TypeList, Elem: &TypeInfo{Type: TypeInt}},
  193. []byte("\x00\x02\x00\x04\x00\x00\x00\x01\x00\x04\x00\x00\x00\x02"),
  194. [2]int{1, 2},
  195. },
  196. {
  197. &TypeInfo{Type: TypeSet, Elem: &TypeInfo{Type: TypeInt}},
  198. []byte("\x00\x02\x00\x04\x00\x00\x00\x01\x00\x04\x00\x00\x00\x02"),
  199. []int{1, 2},
  200. },
  201. {
  202. &TypeInfo{Type: TypeSet, Elem: &TypeInfo{Type: TypeInt}},
  203. []byte(nil),
  204. []int(nil),
  205. },
  206. {
  207. &TypeInfo{Type: TypeMap,
  208. Key: &TypeInfo{Type: TypeVarchar},
  209. Elem: &TypeInfo{Type: TypeInt},
  210. },
  211. []byte("\x00\x01\x00\x03foo\x00\x04\x00\x00\x00\x01"),
  212. map[string]int{"foo": 1},
  213. },
  214. {
  215. &TypeInfo{Type: TypeMap,
  216. Key: &TypeInfo{Type: TypeVarchar},
  217. Elem: &TypeInfo{Type: TypeInt},
  218. },
  219. []byte(nil),
  220. map[string]int(nil),
  221. },
  222. {
  223. &TypeInfo{Type: TypeList, Elem: &TypeInfo{Type: TypeVarchar}},
  224. bytes.Join([][]byte{
  225. []byte("\x00\x01\xFF\xFF"),
  226. bytes.Repeat([]byte("X"), 65535)}, []byte("")),
  227. []string{strings.Repeat("X", 65535)},
  228. },
  229. {
  230. &TypeInfo{Type: TypeMap,
  231. Key: &TypeInfo{Type: TypeVarchar},
  232. Elem: &TypeInfo{Type: TypeVarchar},
  233. },
  234. bytes.Join([][]byte{
  235. []byte("\x00\x01\xFF\xFF"),
  236. bytes.Repeat([]byte("X"), 65535),
  237. []byte("\xFF\xFF"),
  238. bytes.Repeat([]byte("Y"), 65535)}, []byte("")),
  239. map[string]string{
  240. strings.Repeat("X", 65535): strings.Repeat("Y", 65535),
  241. },
  242. },
  243. {
  244. &TypeInfo{Type: TypeVarint},
  245. []byte("\x00"),
  246. 0,
  247. },
  248. {
  249. &TypeInfo{Type: TypeVarint},
  250. []byte("\x37\xE2\x3C\xEC"),
  251. int32(937573612),
  252. },
  253. {
  254. &TypeInfo{Type: TypeVarint},
  255. []byte("\x37\xE2\x3C\xEC"),
  256. big.NewInt(937573612),
  257. },
  258. {
  259. &TypeInfo{Type: TypeVarint},
  260. []byte("\x03\x9EV \x15\f\x03\x9DK\x18\xCDI\\$?\a["),
  261. bigintize("1231312312331283012830129382342342412123"), // From the iconara/cql-rb test suite
  262. },
  263. {
  264. &TypeInfo{Type: TypeVarint},
  265. []byte("\xC9v\x8D:\x86"),
  266. big.NewInt(-234234234234), // From the iconara/cql-rb test suite
  267. },
  268. {
  269. &TypeInfo{Type: TypeVarint},
  270. []byte("f\x1e\xfd\xf2\xe3\xb1\x9f|\x04_\x15"),
  271. bigintize("123456789123456789123456789"), // From the datastax/python-driver test suite
  272. },
  273. {
  274. &TypeInfo{Type: TypeInet},
  275. []byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x7F\x00\x00\x01"),
  276. net.ParseIP("127.0.0.1"),
  277. },
  278. {
  279. &TypeInfo{Type: TypeInet},
  280. []byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"),
  281. net.ParseIP("255.255.255.255"),
  282. },
  283. {
  284. &TypeInfo{Type: TypeInet},
  285. []byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x7F\x00\x00\x01"),
  286. "127.0.0.1",
  287. },
  288. {
  289. &TypeInfo{Type: TypeInet},
  290. []byte("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF"),
  291. "255.255.255.255",
  292. },
  293. {
  294. &TypeInfo{Type: TypeInet},
  295. []byte("\x21\xDA\x00\xd3\x00\x00\x2f\x3b\x02\xaa\x00\xff\xfe\x28\x9c\x5a"),
  296. "21da:d3:0:2f3b:2aa:ff:fe28:9c5a",
  297. },
  298. {
  299. &TypeInfo{Type: TypeInet},
  300. []byte("\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x02\xb3\xff\xfe\x1e\x83\x29"),
  301. "fe80::202:b3ff:fe1e:8329",
  302. },
  303. {
  304. &TypeInfo{Type: TypeInet},
  305. []byte("\x21\xDA\x00\xd3\x00\x00\x2f\x3b\x02\xaa\x00\xff\xfe\x28\x9c\x5a"),
  306. net.ParseIP("21da:d3:0:2f3b:2aa:ff:fe28:9c5a"),
  307. },
  308. {
  309. &TypeInfo{Type: TypeInet},
  310. []byte("\xfe\x80\x00\x00\x00\x00\x00\x00\x02\x02\xb3\xff\xfe\x1e\x83\x29"),
  311. net.ParseIP("fe80::202:b3ff:fe1e:8329"),
  312. },
  313. }
  314. func decimalize(s string) *inf.Dec {
  315. i, _ := new(inf.Dec).SetString(s)
  316. return i
  317. }
  318. func bigintize(s string) *big.Int {
  319. i, _ := new(big.Int).SetString(s, 10)
  320. return i
  321. }
  322. func TestMarshal(t *testing.T) {
  323. for i, test := range marshalTests {
  324. data, err := Marshal(test.Info, test.Value)
  325. if err != nil {
  326. t.Errorf("marshalTest[%d]: %v", i, err)
  327. continue
  328. }
  329. if !bytes.Equal(data, test.Data) {
  330. t.Errorf("marshalTest[%d]: expected %q, got %q.", i, test.Data, data)
  331. }
  332. }
  333. }
  334. func TestMarshalNil(t *testing.T) {
  335. data, err := Marshal(&TypeInfo{Type: TypeInt}, nil)
  336. if err != nil {
  337. t.Errorf("failed to marshal nil with err: %v", err)
  338. }
  339. if data != nil {
  340. t.Errorf("expected nil, got %v", data)
  341. }
  342. }
  343. func TestUnmarshal(t *testing.T) {
  344. for i, test := range marshalTests {
  345. v := reflect.New(reflect.TypeOf(test.Value))
  346. err := Unmarshal(test.Info, test.Data, v.Interface())
  347. if err != nil {
  348. t.Errorf("marshalTest[%d]: %v", i, err)
  349. continue
  350. }
  351. if !reflect.DeepEqual(v.Elem().Interface(), test.Value) {
  352. t.Errorf("marshalTest[%d]: expected %#v, got %#v.", i, test.Value, v.Elem().Interface())
  353. }
  354. }
  355. }
  356. func TestMarshalVarint(t *testing.T) {
  357. varintTests := []struct {
  358. Value interface{}
  359. Marshaled []byte
  360. Unmarshaled *big.Int
  361. }{
  362. {
  363. Value: int8(0),
  364. Marshaled: []byte("\x00"),
  365. Unmarshaled: big.NewInt(0),
  366. },
  367. {
  368. Value: uint8(255),
  369. Marshaled: []byte("\x00\xFF"),
  370. Unmarshaled: big.NewInt(255),
  371. },
  372. {
  373. Value: int8(-1),
  374. Marshaled: []byte("\xFF"),
  375. Unmarshaled: big.NewInt(-1),
  376. },
  377. {
  378. Value: big.NewInt(math.MaxInt32),
  379. Marshaled: []byte("\x7F\xFF\xFF\xFF"),
  380. Unmarshaled: big.NewInt(math.MaxInt32),
  381. },
  382. {
  383. Value: big.NewInt(int64(math.MaxInt32) + 1),
  384. Marshaled: []byte("\x00\x80\x00\x00\x00"),
  385. Unmarshaled: big.NewInt(int64(math.MaxInt32) + 1),
  386. },
  387. {
  388. Value: big.NewInt(math.MinInt32),
  389. Marshaled: []byte("\x80\x00\x00\x00"),
  390. Unmarshaled: big.NewInt(math.MinInt32),
  391. },
  392. {
  393. Value: big.NewInt(int64(math.MinInt32) - 1),
  394. Marshaled: []byte("\xFF\x7F\xFF\xFF\xFF"),
  395. Unmarshaled: big.NewInt(int64(math.MinInt32) - 1),
  396. },
  397. {
  398. Value: math.MinInt64,
  399. Marshaled: []byte("\x80\x00\x00\x00\x00\x00\x00\x00"),
  400. Unmarshaled: big.NewInt(math.MinInt64),
  401. },
  402. {
  403. Value: uint64(math.MaxInt64) + 1,
  404. Marshaled: []byte("\x00\x80\x00\x00\x00\x00\x00\x00\x00"),
  405. Unmarshaled: bigintize("9223372036854775808"),
  406. },
  407. {
  408. Value: bigintize("2361183241434822606848"), // 2**71
  409. Marshaled: []byte("\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00"),
  410. Unmarshaled: bigintize("2361183241434822606848"),
  411. },
  412. {
  413. Value: bigintize("-9223372036854775809"), // -2**63 - 1
  414. Marshaled: []byte("\xFF\x7F\xFF\xFF\xFF\xFF\xFF\xFF\xFF"),
  415. Unmarshaled: bigintize("-9223372036854775809"),
  416. },
  417. }
  418. for i, test := range varintTests {
  419. data, err := Marshal(&TypeInfo{Type: TypeVarint}, test.Value)
  420. if err != nil {
  421. t.Errorf("error marshaling varint: %v (test #%d)", err, i)
  422. }
  423. if !bytes.Equal(test.Marshaled, data) {
  424. t.Errorf("marshaled varint mismatch: expected %v, got %v (test #%d)", test.Marshaled, data, i)
  425. }
  426. binder := new(big.Int)
  427. err = Unmarshal(&TypeInfo{Type: TypeVarint}, test.Marshaled, binder)
  428. if err != nil {
  429. t.Errorf("error unmarshaling varint: %v (test #%d)", err, i)
  430. }
  431. if test.Unmarshaled.Cmp(binder) != 0 {
  432. t.Errorf("unmarshaled varint mismatch: expected %v, got %v (test #%d)", test.Unmarshaled, binder, i)
  433. }
  434. }
  435. }
  436. type CustomString string
  437. func (c CustomString) MarshalCQL(info *TypeInfo) ([]byte, error) {
  438. return []byte(strings.ToUpper(string(c))), nil
  439. }
  440. func (c *CustomString) UnmarshalCQL(info *TypeInfo, data []byte) error {
  441. *c = CustomString(strings.ToLower(string(data)))
  442. return nil
  443. }
  444. type MyString string
  445. type MyInt int
  446. var typeLookupTest = []struct {
  447. TypeName string
  448. ExpectedType Type
  449. }{
  450. {"AsciiType", TypeAscii},
  451. {"LongType", TypeBigInt},
  452. {"BytesType", TypeBlob},
  453. {"BooleanType", TypeBoolean},
  454. {"CounterColumnType", TypeCounter},
  455. {"DecimalType", TypeDecimal},
  456. {"DoubleType", TypeDouble},
  457. {"FloatType", TypeFloat},
  458. {"Int32Type", TypeInt},
  459. {"DateType", TypeTimestamp},
  460. {"UUIDType", TypeUUID},
  461. {"UTF8Type", TypeVarchar},
  462. {"IntegerType", TypeVarint},
  463. {"TimeUUIDType", TypeTimeUUID},
  464. {"InetAddressType", TypeInet},
  465. {"MapType", TypeMap},
  466. {"ListType", TypeInet},
  467. {"SetType", TypeInet},
  468. {"unknown", TypeCustom},
  469. }
  470. func testType(t *testing.T, cassType string, expectedType Type) {
  471. if computedType := getApacheCassandraType(apacheCassandraTypePrefix + cassType); computedType != expectedType {
  472. t.Errorf("Cassandra custom type lookup for %s failed. Expected %s, got %s.", cassType, expectedType.String(), computedType.String())
  473. }
  474. }
  475. func TestLookupCassType(t *testing.T) {
  476. for _, lookupTest := range typeLookupTest {
  477. testType(t, lookupTest.TypeName, lookupTest.ExpectedType)
  478. }
  479. }