123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538 |
- package hbaseutil
- import (
- "encoding/binary"
- "encoding/json"
- "github.com/tsuna/gohbase/hrpc"
- "reflect"
- "testing"
- "time"
- )
- func uint64ToByte(value uint64) []byte {
- var buf = make([]byte, 8)
- binary.BigEndian.PutUint64(buf, value)
- return buf
- }
- func uint32ToByte(value uint32) []byte {
- var buf = make([]byte, 4)
- binary.BigEndian.PutUint32(buf, value)
- return buf
- }
- func uint16ToByte(value uint16) []byte {
- var buf = make([]byte, 2)
- binary.BigEndian.PutUint16(buf, value)
- return buf
- }
- type testStruct struct {
- A int64 `family:"f" qualifier:"q64"`
- B *int32 `family:"f" qualifier:"q32"`
- C int16 `family:"f" qualifier:"q16"`
- D int `qualifier:"q"`
- S *string `qualifier:"s"`
- FailField bool `family:"f" qualifier:"fail"`
- MapInt map[string]int `family:"m1"`
- MapString map[string]string `family:"m2"`
- }
- func (t *testStruct) equal(o testStruct) bool {
- return t.A == o.A &&
- *t.B == *o.B &&
- t.C == o.C &&
- t.D == o.D &&
- *t.S == *o.S &&
- t.FailField == o.FailField &&
- reflect.DeepEqual(t.MapInt, o.MapInt) &&
- reflect.DeepEqual(t.MapString, o.MapString)
- }
- var testcase = [][]*hrpc.Cell{
- {
- {Family: []byte("f"), Qualifier: []byte("q64"), Value: uint64ToByte(10000000000)},
- {Family: []byte("f"), Qualifier: []byte("q32"), Value: uint32ToByte(1000000)},
- {Family: []byte("f"), Qualifier: []byte("q16"), Value: uint16ToByte(100)},
- {Family: []byte("f"), Qualifier: []byte("q"), Value: uint64ToByte(1000000)},
- {Family: []byte("f"), Qualifier: []byte("s"), Value: []byte("just test")},
- {Family: []byte("f"), Qualifier: []byte("fail"), Value: []byte("1")},
- {Family: []byte("m1"), Qualifier: []byte("k1"), Value: uint32ToByte(1)},
- {Family: []byte("m1"), Qualifier: []byte("k2"), Value: uint16ToByte(2)},
- {Family: []byte("m2"), Qualifier: []byte("k1"), Value: []byte("1")},
- {Family: []byte("m2"), Qualifier: []byte("k2"), Value: []byte("2")},
- },
- {
- {Family: []byte("f"), Qualifier: []byte("q64"), Value: uint64ToByte(10000000000)},
- {Family: []byte("f"), Qualifier: []byte("q32"), Value: uint64ToByte(10000000000)},
- {Family: []byte("f"), Qualifier: []byte("q16"), Value: uint64ToByte(10000000000)},
- {Family: []byte("f"), Qualifier: []byte("q"), Value: uint64ToByte(10000000000)},
- {Family: []byte("f"), Qualifier: []byte("s"), Value: []byte("just test2")},
- {Family: []byte("f"), Qualifier: []byte("fail"), Value: []byte("1")},
- },
- }
- var resultb = []int32{
- 1000000,
- 10000000000 & 0xffffffff,
- }
- var results = []string{
- "just test",
- "just test2",
- }
- var resultcase = []testStruct{
- {A: 10000000000, B: &resultb[0], C: 100, D: 1000000, S: &results[0],
- MapInt: map[string]int{"k1": 1, "k2": 2},
- MapString: map[string]string{"k1": "1", "k2": "2"}},
- {A: 10000000000, B: &resultb[1], C: -7168, D: int(10000000000), S: &results[1]},
- }
- func TestParser_Parse(t *testing.T) {
- var parser = Parser{}
- for i, cells := range testcase {
- var result testStruct
- var err = parser.Parse(cells, &result)
- if err != nil {
- t.Logf("err=%v", err)
- t.Fail()
- }
- t.Logf("result=%v, expect=%v", result, resultcase[i])
- if !resultcase[i].equal(result) {
- t.Logf("fail case: index=%d", i)
- t.Fail()
- }
- }
- }
- var testcase2 = [][]*hrpc.Cell{
- {
- {Family: []byte("f"), Qualifier: []byte("q64"), Value: []byte("10000000000")},
- {Family: []byte("f"), Qualifier: []byte("q32"), Value: []byte("1000000")},
- {Family: []byte("f"), Qualifier: []byte("q16"), Value: []byte("100")},
- {Family: []byte("f"), Qualifier: []byte("q"), Value: []byte("1000000")},
- {Family: []byte("f"), Qualifier: []byte("s"), Value: []byte("just test")},
- {Family: []byte("f"), Qualifier: []byte("fail"), Value: []byte("1")},
- {Family: []byte("m1"), Qualifier: []byte("k1"), Value: []byte("1")},
- {Family: []byte("m1"), Qualifier: []byte("k2"), Value: []byte("2")},
- {Family: []byte("m2"), Qualifier: []byte("k1"), Value: []byte("1")},
- {Family: []byte("m2"), Qualifier: []byte("k2"), Value: []byte("2")},
- },
- }
- var resultcase2 = []testStruct{
- {A: 10000000000, B: &resultb[0], C: 100, D: 1000000, S: &results[0],
- MapInt: map[string]int{"k1": 1, "k2": 2},
- MapString: map[string]string{"k1": "1", "k2": "2"}},
- }
- func TestParser_ParseCustomParseInt(t *testing.T) {
- var parser = Parser{
- ParseIntFunc: StringToUint,
- }
- for i, cells := range testcase2 {
- var result testStruct
- var err = parser.Parse(cells, &result)
- if err != nil {
- t.Logf("err=%v", err)
- t.Fail()
- }
- t.Logf("result=%v, expect=%v", result, resultcase[i])
- if !resultcase2[i].equal(result) {
- t.Logf("fail case: index=%d", i)
- t.Fail()
- }
- }
- }
- func TestParser_StringInt(t *testing.T) {
- var testcase2 = [][]*hrpc.Cell{
- {
- {Family: []byte("f"), Qualifier: []byte("q64"), Value: []byte("9223372036854775807")},
- {Family: []byte("f"), Qualifier: []byte("q32"), Value: []byte("1000000")},
- {Family: []byte("f"), Qualifier: []byte("q16"), Value: []byte("10000")},
- {Family: []byte("f"), Qualifier: []byte("q"), Value: []byte("100")},
- },
- {
- {Family: []byte("f"), Qualifier: []byte("q64"), Value: []byte("-9223372036854775808")},
- {Family: []byte("f"), Qualifier: []byte("q32"), Value: []byte("-2")},
- {Family: []byte("f"), Qualifier: []byte("q16"), Value: []byte("-3")},
- {Family: []byte("f"), Qualifier: []byte("q"), Value: []byte("-4")},
- {Family: []byte("f"), Qualifier: []byte("u64"), Value: []byte("18446744073709551615")},
- {Family: []byte("f"), Qualifier: []byte("u32"), Value: []byte("2147483648")},
- {Family: []byte("f"), Qualifier: []byte("u16"), Value: []byte("32768")},
- {Family: []byte("f"), Qualifier: []byte("u8"), Value: []byte("128")},
- },
- }
- type testStruct struct {
- A int64 `family:"f" qualifier:"q64"`
- B int32 `family:"f" qualifier:"q32"`
- C int16 `family:"f" qualifier:"q16"`
- D int8 `qualifier:"q"`
- U64 uint64 `family:"f" qualifier:"u64"`
- U32 uint32 `family:"f" qualifier:"u32"`
- U16 uint16 `family:"f" qualifier:"u16"`
- U8 uint8 `family:"f" qualifier:"u8"`
- }
- var expect = []testStruct{
- {
- A: 9223372036854775807, B: 1000000, C: 10000, D: 100,
- },
- {
- A: -9223372036854775808, B: -2, C: -3, D: -4,
- U64: 18446744073709551615, U32: 2147483648, U16: 32768, U8: 128,
- },
- }
- var parser = Parser{
- ParseIntFunc: StringToUint,
- }
- for i, cells := range testcase2 {
- var result testStruct
- var err = parser.Parse(cells, &result)
- if err != nil {
- t.Logf("err=%v", err)
- t.Fail()
- }
- t.Logf("result=%+v, expect=%+v", result, expect[i])
- if !reflect.DeepEqual(expect[i], result) {
- t.Logf("fail case: index=%d", i)
- t.Fail()
- }
- }
- }
- func TestParser_InterfaceInterface(t *testing.T) {
- var parser = Parser{}
- for i, cells := range testcase {
- var st testStruct
- var result interface{} = &st
- var err = parser.Parse(cells, result)
- if err != nil {
- t.Logf("err=%v", err)
- t.Fail()
- }
- t.Logf("result=%v, expect=%v", result, resultcase[i])
- if !resultcase[i].equal(*result.(*testStruct)) {
- t.Logf("fail case: index=%d", i)
- t.Fail()
- }
- }
- }
- type testOnlyQualifier struct {
- A int64 `qualifier:"q64"`
- B *int32 `qualifier:"q32"`
- C int16 `qualifier:"q16"`
- D int `qualifier:"q"`
- S *string `qualifier:"s"`
- FailField bool `qualifier:"fail"`
- MapInt map[string]int `family:"m1"`
- MapString map[string]string `family:"m2"`
- }
- var testcase3 = [][]*hrpc.Cell{
- {
- {Family: []byte("f"), Qualifier: []byte("q64"), Value: uint64ToByte(10000000000)},
- {Family: []byte("f"), Qualifier: []byte("q32"), Value: uint32ToByte(1000000)},
- {Family: []byte("f"), Qualifier: []byte("q16"), Value: uint16ToByte(100)},
- {Family: []byte("f"), Qualifier: []byte("q"), Value: uint64ToByte(1000000)},
- {Family: []byte("f"), Qualifier: []byte("s"), Value: []byte("just test")},
- {Family: []byte("f"), Qualifier: []byte("fail"), Value: []byte("1")},
- {Family: []byte("m1"), Qualifier: []byte("k1"), Value: uint32ToByte(1)},
- {Family: []byte("m1"), Qualifier: []byte("k2"), Value: uint16ToByte(2)},
- {Family: []byte("m2"), Qualifier: []byte("k1"), Value: []byte("1")},
- {Family: []byte("m2"), Qualifier: []byte("k2"), Value: []byte("2")},
- },
- }
- var resultcase3 = []testOnlyQualifier{
- {A: 10000000000, B: &resultb[0], C: 100, D: 1000000, S: &results[0],
- MapInt: map[string]int{"k1": 1, "k2": 2},
- MapString: map[string]string{"k1": "1", "k2": "2"}},
- }
- func (t *testOnlyQualifier) equal(o testOnlyQualifier) bool {
- return t.A == o.A &&
- *t.B == *o.B &&
- t.C == o.C &&
- t.D == o.D &&
- *t.S == *o.S &&
- t.FailField == o.FailField &&
- reflect.DeepEqual(t.MapInt, o.MapInt) &&
- reflect.DeepEqual(t.MapString, o.MapString)
- }
- func TestParser_OnlyQualifier(t *testing.T) {
- var parser = Parser{}
- for i, cells := range testcase3 {
- var result testOnlyQualifier
- var err = parser.Parse(cells, &result)
- if err != nil {
- t.Logf("err=%v", err)
- t.Fail()
- }
- t.Logf("result=%v, expect=%v", result, resultcase3[i])
- if !resultcase3[i].equal(result) {
- t.Logf("fail case: index=%d", i)
- t.Fail()
- }
- }
- }
- func TestParser_PartialFamilyPartPartialQualifier(t *testing.T) {
- var testcase = [][]*hrpc.Cell{
- {
- {Family: []byte("f"), Qualifier: []byte("q64"), Value: uint64ToByte(10000000000)},
- {Family: []byte("f"), Qualifier: []byte("q32"), Value: uint32ToByte(1000000)},
- {Family: []byte("f"), Qualifier: []byte("q16"), Value: uint16ToByte(100)},
- {Family: []byte("f"), Qualifier: []byte("q"), Value: uint64ToByte(1000000)},
- {Family: []byte("f"), Qualifier: []byte("s"), Value: []byte("just test")},
- {Family: []byte("f"), Qualifier: []byte("fail"), Value: []byte("1")},
- },
- }
- type testStruct struct {
- A int `family:"f" qualifier:"q64"`
- Map map[string]int `family:"f"`
- }
- var resultcase = []testStruct{
- {A: 10000000000,
- Map: map[string]int{
- "q32": 1000000,
- "q16": 100,
- "q": 1000000,
- "fail": int('1'),
- }},
- }
- var parser = Parser{}
- for i, cells := range testcase {
- var result testStruct
- var resInterface interface{} = &result
- var start = time.Now()
- var err = parser.Parse(cells, &resInterface)
- var elapse = time.Since(start)
- if err != nil {
- t.Logf("err=%v", err)
- t.Fail()
- }
- t.Logf("result=%v, expect=%v, parse time=%v", resInterface, resultcase[i], elapse)
- if !reflect.DeepEqual(resultcase[i], result) {
- t.Logf("fail case: index=%d", i)
- t.Fail()
- }
- }
- }
- func TestParser_SetBasicValue(t *testing.T) {
- var (
- i32s int32 = -2
- i64s int64 = -3
- i16s int16 = -4
- i32d int32
- i64d int64
- i16d int16
- i64Bytes = uint64ToByte(uint64(i64s))
- i32Bytes = uint32ToByte(uint32(i32s))
- i16Bytes = uint16ToByte(uint16(i16s))
- )
- var rvi32 = reflect.ValueOf(&i32d)
- var e = setBasicValue(i32Bytes, rvi32, "rvi32", ByteBigEndianToUint64)
- if e != nil {
- t.Errorf("fail, err=%+v", e)
- t.FailNow()
- }
- if i32s != i32d {
- t.Errorf("fail,expect=%d, got=%d", i32d, i32s)
- t.FailNow()
- }
- var rvi64 = reflect.ValueOf(&i64d)
- e = setBasicValue(i64Bytes, rvi64, "rvi64", ByteBigEndianToUint64)
- if e != nil {
- t.Errorf("fail, err=%+v", e)
- t.FailNow()
- }
- if i64s != i64d {
- t.Errorf("fail,expect=%d, got=%d", i64d, i64s)
- t.FailNow()
- }
- var rvi16 = reflect.ValueOf(&i16d)
- e = setBasicValue(i16Bytes, rvi16, "rvi16", ByteBigEndianToUint64)
- if e != nil {
- t.Errorf("fail, err=%+v", e)
- t.FailNow()
- }
- if i16s != i16d {
- t.Errorf("fail,expect=%d, got=%d", i16d, i16s)
- t.FailNow()
- }
- }
- func TestParser_Minus(t *testing.T) {
- var i64 int64 = -2
- var i32 int32 = -3
- var i16 int16 = -4
- var i8 int8 = -128
- var testcase = [][]*hrpc.Cell{
- {
- {Family: []byte("f"), Qualifier: []byte("i64"), Value: uint64ToByte(uint64(i64))},
- {Family: []byte("f"), Qualifier: []byte("i32"), Value: uint32ToByte(uint32(i32))},
- {Family: []byte("f"), Qualifier: []byte("i16"), Value: uint16ToByte(uint16(i16))},
- {Family: []byte("f"), Qualifier: []byte("i8"), Value: []byte{uint8(i8)}},
- },
- }
- type testStruct struct {
- I64 int64 `family:"f" qualifier:"i64"`
- I32 int32 `family:"f" qualifier:"i32"`
- I16 int16 `family:"f" qualifier:"i16"`
- I8 int8 `family:"f" qualifier:"i8"`
- }
- var resultcase = []testStruct{
- {
- I64: i64,
- I32: i32,
- I16: i16,
- I8: i8,
- },
- }
- var parser = Parser{}
- for i, cells := range testcase {
- var result testStruct
- var resInterface interface{} = &result
- var start = time.Now()
- var err = parser.Parse(cells, &resInterface)
- var elapse = time.Since(start)
- if err != nil {
- t.Logf("err=%v", err)
- t.Fail()
- }
- t.Logf("result=%v, expect=%v, parse time=%v", resInterface, resultcase[i], elapse)
- if !reflect.DeepEqual(resultcase[i], result) {
- t.Logf("fail case: index=%d", i)
- t.Fail()
- }
- }
- }
- func TestParser_Overflow(t *testing.T) {
- var testcase = [][]*hrpc.Cell{
- {
- {Family: []byte("f"), Qualifier: []byte("i64"), Value: uint64ToByte(0xff01020304050607)},
- {Family: []byte("f"), Qualifier: []byte("i32"), Value: uint64ToByte(0xff01020304050607)},
- {Family: []byte("f"), Qualifier: []byte("i16"), Value: uint64ToByte(0xff01020304050607)},
- {Family: []byte("f"), Qualifier: []byte("i8"), Value: uint64ToByte(0xff01020304050607)},
- },
- }
- type testStruct struct {
- I64 int64 `family:"f" qualifier:"i64"`
- I32 int32 `family:"f" qualifier:"i32"`
- I16 int16 `family:"f" qualifier:"i16"`
- I8 int8 `family:"f" qualifier:"i8"`
- }
- var resultcase = []testStruct{
- {
- I64: -(0xffffffffffffffff - 0xff01020304050607 + 1),
- I32: 0xff01020304050607 & 0xffffffff,
- I16: 0xff01020304050607 & 0xffff,
- I8: 0xff01020304050607 & 0xff,
- },
- }
- var parser = Parser{}
- for i, cells := range testcase {
- var result testStruct
- var resInterface interface{} = &result
- var start = time.Now()
- var err = parser.Parse(cells, &resInterface)
- var elapse = time.Since(start)
- if err != nil {
- t.Logf("err=%v", err)
- t.Fail()
- }
- t.Logf("result=%v, expect=%v, parse time=%v", resInterface, resultcase[i], elapse)
- if !reflect.DeepEqual(resultcase[i], result) {
- t.Logf("fail case: index=%d", i)
- t.Fail()
- }
- }
- }
- func BenchmarkParser(b *testing.B) {
- var testcase = [][]*hrpc.Cell{
- {
- {Family: []byte("f"), Qualifier: []byte("q64"), Value: uint64ToByte(10000000000)},
- {Family: []byte("f"), Qualifier: []byte("q32"), Value: uint32ToByte(1000000)},
- {Family: []byte("f"), Qualifier: []byte("q16"), Value: uint16ToByte(100)},
- {Family: []byte("f"), Qualifier: []byte("q"), Value: uint64ToByte(1000000)},
- {Family: []byte("f"), Qualifier: []byte("fail"), Value: uint64ToByte(100)},
- },
- }
- type testStruct struct {
- A int `family:"f" qualifier:"q64"`
- B int32 `family:"f" qualifier:"q32"`
- C int16 `family:"f" qualifier:"q16"`
- D int `qualifier:"q"`
- S string `qualifier:"s"`
- Map map[string]int `family:"f"`
- }
- var parser Parser
- b.Logf("bench parser")
- for i := 0; i < b.N; i++ {
- var result testStruct
- parser.Parse(testcase[0], &result)
- }
- }
- func BenchmarkJson(b *testing.B) {
- var text = []byte("{\"a\": 123, \"b\": \"1234\", \"c\": \"1234\", \"d\": \"1234\", \"e\" :{\"a\": 123, \"b\": \"1234\"}}")
- var result struct {
- A int `json:"a"`
- B string `json:"b"`
- C string `json:"c"`
- D string `json:"d"`
- E struct {
- A int `json:"a"`
- B string `json:"b"`
- } `json:"e"`
- }
- b.Logf("bench json")
- for i := 0; i < b.N; i++ {
- if err := json.Unmarshal(text, &result); err != nil {
- b.FailNow()
- }
- }
- }
|