github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/xid/xid_test.go (about) 1 package xid 2 3 import ( 4 "encoding/json" 5 "testing" 6 "time" 7 8 "github.com/stretchr/testify/assert" 9 ) 10 11 const strInvalidID = "xid: invalid ID" 12 13 type IDParts struct { 14 id ID 15 timestamp int64 16 machine []byte 17 pid uint16 18 counter int32 19 } 20 21 var IDs = []IDParts{ 22 IDParts{ 23 ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}, 24 1300816219, 25 []byte{0x60, 0xf4, 0x86}, 26 0xe428, 27 4271561, 28 }, 29 IDParts{ 30 ID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 31 0, 32 []byte{0x00, 0x00, 0x00}, 33 0x0000, 34 0, 35 }, 36 IDParts{ 37 ID{0x00, 0x00, 0x00, 0x00, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0x00, 0x00, 0x01}, 38 0, 39 []byte{0xaa, 0xbb, 0xcc}, 40 0xddee, 41 1, 42 }, 43 } 44 45 func TestIDPartsExtraction(t *testing.T) { 46 for i, v := range IDs { 47 assert.Equal(t, v.id.Time(), time.Unix(v.timestamp, 0), "#%d timestamp", i) 48 assert.Equal(t, v.id.Machine(), v.machine, "#%d machine", i) 49 assert.Equal(t, v.id.Pid(), v.pid, "#%d pid", i) 50 assert.Equal(t, v.id.Counter(), v.counter, "#%d counter", i) 51 } 52 } 53 54 func TestNew(t *testing.T) { 55 // Generate 10 ids 56 ids := make([]ID, 10) 57 for i := 0; i < 10; i++ { 58 ids[i] = New() 59 } 60 for i := 1; i < 10; i++ { 61 prevID := ids[i-1] 62 id := ids[i] 63 // Test for uniqueness among all other 9 generated ids 64 for j, tid := range ids { 65 if j != i { 66 assert.NotEqual(t, id, tid, "Generated ID is not unique") 67 } 68 } 69 // Check that timestamp was incremented and is within 30 seconds of the previous one 70 secs := id.Time().Sub(prevID.Time()).Seconds() 71 assert.Equal(t, (secs >= 0 && secs <= 30), true, "Wrong timestamp in generated ID") 72 // Check that machine ids are the same 73 assert.Equal(t, id.Machine(), prevID.Machine()) 74 // Check that pids are the same 75 assert.Equal(t, id.Pid(), prevID.Pid()) 76 // Test for proper increment 77 delta := int(id.Counter() - prevID.Counter()) 78 assert.Equal(t, delta, 1, "Wrong increment in generated ID") 79 } 80 } 81 82 func TestIDString(t *testing.T) { 83 id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9} 84 assert.Equal(t, "9m4e2mr0ui3e8a215n4g", id.String()) 85 } 86 87 func TestFromString(t *testing.T) { 88 id, err := FromString("9m4e2mr0ui3e8a215n4g") 89 assert.NoError(t, err) 90 assert.Equal(t, ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}, id) 91 } 92 93 func TestFromStringInvalid(t *testing.T) { 94 id, err := FromString("invalid") 95 assert.EqualError(t, err, strInvalidID) 96 assert.Equal(t, ID{}, id) 97 } 98 99 type jsonType struct { 100 ID *ID 101 Str string 102 } 103 104 func TestIDJSONMarshaling(t *testing.T) { 105 id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9} 106 v := jsonType{ID: &id, Str: "test"} 107 data, err := json.Marshal(&v) 108 assert.NoError(t, err) 109 assert.Equal(t, `{"ID":"9m4e2mr0ui3e8a215n4g","Str":"test"}`, string(data)) 110 } 111 112 func TestIDJSONUnmarshaling(t *testing.T) { 113 data := []byte(`{"ID":"9m4e2mr0ui3e8a215n4g","Str":"test"}`) 114 v := jsonType{} 115 err := json.Unmarshal(data, &v) 116 assert.NoError(t, err) 117 assert.Equal(t, ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}, *v.ID) 118 } 119 120 func TestIDJSONUnmarshalingError(t *testing.T) { 121 v := jsonType{} 122 err := json.Unmarshal([]byte(`{"ID":"9M4E2MR0UI3E8A215N4G"}`), &v) 123 assert.EqualError(t, err, strInvalidID) 124 err = json.Unmarshal([]byte(`{"ID":"TYjhW2D0huQoQS"}`), &v) 125 assert.EqualError(t, err, strInvalidID) 126 err = json.Unmarshal([]byte(`{"ID":"TYjhW2D0huQoQS3kdk"}`), &v) 127 assert.EqualError(t, err, strInvalidID) 128 } 129 130 func TestIDDriverValue(t *testing.T) { 131 id := ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9} 132 data, err := id.Value() 133 assert.NoError(t, err) 134 assert.Equal(t, "9m4e2mr0ui3e8a215n4g", data) 135 } 136 137 func TestIDDriverScan(t *testing.T) { 138 id := ID{} 139 err := id.Scan("9m4e2mr0ui3e8a215n4g") 140 assert.NoError(t, err) 141 assert.Equal(t, ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}, id) 142 } 143 144 func TestIDDriverScanError(t *testing.T) { 145 id := ID{} 146 err := id.Scan(0) 147 assert.EqualError(t, err, "xid: scanning unsupported type: int") 148 err = id.Scan("0") 149 assert.EqualError(t, err, strInvalidID) 150 } 151 152 func TestIDDriverScanByteFromDatabase(t *testing.T) { 153 id := ID{} 154 bs := []byte("9m4e2mr0ui3e8a215n4g") 155 err := id.Scan(bs) 156 assert.NoError(t, err) 157 assert.Equal(t, ID{0x4d, 0x88, 0xe1, 0x5b, 0x60, 0xf4, 0x86, 0xe4, 0x28, 0x41, 0x2d, 0xc9}, id) 158 } 159 160 func BenchmarkNew(b *testing.B) { 161 b.RunParallel(func(pb *testing.PB) { 162 for pb.Next() { 163 _ = New() 164 } 165 }) 166 } 167 168 func BenchmarkNewString(b *testing.B) { 169 b.RunParallel(func(pb *testing.PB) { 170 for pb.Next() { 171 _ = New().String() 172 } 173 }) 174 } 175 176 func BenchmarkFromString(b *testing.B) { 177 b.RunParallel(func(pb *testing.PB) { 178 for pb.Next() { 179 _, _ = FromString("9m4e2mr0ui3e8a215n4g") 180 } 181 }) 182 } 183 184 // func BenchmarkUUIDv1(b *testing.B) { 185 // b.RunParallel(func(pb *testing.PB) { 186 // for pb.Next() { 187 // _ = uuid.NewV1().String() 188 // } 189 // }) 190 // } 191 192 // func BenchmarkUUIDv4(b *testing.B) { 193 // b.RunParallel(func(pb *testing.PB) { 194 // for pb.Next() { 195 // _ = uuid.NewV4().String() 196 // } 197 // }) 198 // }