github.com/andersfylling/snowflake/v5@v5.0.1/snowflake_test.go (about) 1 package snowflake 2 3 import ( 4 "encoding" 5 "encoding/json" 6 "testing" 7 "time" 8 ) 9 10 func TestSnowflake_Date(t *testing.T) { 11 s := Snowflake(0) 12 a := s.Date() 13 if diff := a.Sub(time.Unix(int64(EpochDiscord)/1000, 0)); diff != 0 { 14 t.Error("expected Date subtracted the epoch to be 0. Got ", diff) 15 } 16 17 s = NewSnowflake(228846961774559232) 18 if s.Date().Unix() != 1474631767 { 19 t.Error("date is incorrect") 20 } 21 } 22 23 func TestASCIITrick(t *testing.T) { 24 if int('n'+'u'+'l')*2 < 4*'9' { 25 t.Error("unable to sum ascii chars") 26 } 27 } 28 29 func TestString(t *testing.T) { 30 var b []byte 31 var err error 32 id := NewSnowflake(uint64(435834986943)) 33 if id.String() != "435834986943" { 34 t.Errorf("String conversion failed. Got %s, wants %s", id.String(), "435834986943") 35 } 36 37 if id.HexString() != "6579ca21bf" { 38 t.Errorf("String conversion for Hex failed. Got %s, wants %s", id.HexString(), "6579ca21bf") 39 } 40 41 if id.HexPrettyString() != "0x6579ca21bf" { 42 t.Errorf("String conversion for Pretty Hex failed. Got %s, wants %s", id.HexPrettyString(), "0x6579ca21bf") 43 } 44 45 b, err = id.MarshalBinary() 46 if err != nil { 47 t.Error(err) 48 } 49 if string(b) != "110010101111001110010100010000110111111" { 50 t.Errorf("String conversion for binary failed. Got %s, wants %s", string(b), "110010101111001110010100010000110111111") 51 } 52 } 53 54 func TestSnowflake_IsZero(t *testing.T) { 55 id := Snowflake(0) 56 if !id.IsZero() { 57 t.Errorf("snowflake should be considered empty when value is 0") 58 } 59 id = Snowflake(1) 60 if id.IsZero() { 61 t.Errorf("snowflake should contain data") 62 } 63 } 64 65 func TestBinaryMarshalling(t *testing.T) { 66 if _, ok := interface{}((*Snowflake)(nil)).(encoding.BinaryMarshaler); !ok { 67 t.Error("does not implement encoding.BinaryMarshaler") 68 } 69 70 id := NewSnowflake(4598345) 71 b, err := id.MarshalBinary() 72 if err != nil { 73 t.Error(err) 74 } 75 76 id2 := NewSnowflake(4534) 77 err = id2.UnmarshalBinary(b) 78 if err != nil { 79 t.Error(err) 80 } 81 82 if id2 != id { 83 t.Errorf("Value differs. Got %d, wants %d", id2, id) 84 } 85 } 86 87 func TestTextMarshalling(t *testing.T) { 88 if _, ok := interface{}((*Snowflake)(nil)).(encoding.TextMarshaler); !ok { 89 t.Error("does not implement encoding.TextMarshaler") 90 } 91 92 target := "80351110224678912" 93 94 id := NewSnowflake(4534) 95 err := id.UnmarshalText([]byte(target)) 96 if err != nil { 97 t.Error(err) 98 } 99 100 b, err := id.MarshalText() 101 if err != nil { 102 t.Error(err) 103 } 104 105 if string(b) != target { 106 t.Errorf("Value differs. Got %s, wants %s", string(b), target) 107 } 108 } 109 110 func TestJSONMarshalling(t *testing.T) { 111 if _, ok := interface{}((*Snowflake)(nil)).(json.Marshaler); !ok { 112 t.Error("does not implement json.Marshaler") 113 } 114 115 target := `"80351110224678912"` 116 117 id := NewSnowflake(0) 118 err := json.Unmarshal([]byte(target), &id) 119 if err != nil { 120 t.Error(err) 121 } 122 123 b, err := json.Marshal(id) 124 if err != nil { 125 t.Error(err) 126 } 127 128 if string(b) != target { 129 t.Errorf("Incorrect snowflake value. Got %s, wants %s", string(b), target) 130 } 131 132 id = NewSnowflake(0) 133 b, err = json.Marshal(&id) 134 if err != nil { 135 t.Error(err) 136 } 137 if string(b) != `null` { 138 t.Error("expected 0 Snowflake to display as null, got " + string(b)) 139 } 140 141 if err = json.Unmarshal([]byte("1"), &id); err != nil { 142 t.Fatal(err) 143 } 144 } 145 146 type testSet struct { 147 result uint64 148 data []byte 149 } 150 151 func TestSnowflake_UnmarshalJSON(t *testing.T) { 152 data := []testSet{ 153 {8994537984753, []byte(`{"id":"8994537984753"}`)}, 154 {4573485, []byte(`{"id":"4573485"}`)}, 155 {2349872349, []byte(`{"id":"00002349872349"}`)}, 156 {435453, []byte(`{"id":"435453"}`)}, 157 {4987598525434463, []byte(`{"id":"4987598525434463"}`)}, 158 {69696969, []byte(`{"id":69696969}`)}, 159 {59823042, []byte(`{"id":"059823042"}`)}, 160 {698734534634, []byte(`{"id":"698734534634"}`)}, 161 {24795873495, []byte(`{"id":"024795873495"}`)}, 162 {598360703000, []byte(`{"id":"0598360703000"}`)}, 163 {0, []byte(`{"id":null}`)}, 164 {0, []byte(`{"id":0}`)}, 165 {1, []byte(`{"id":1}`)}, 166 {(1 << 63) | 1, []byte(`{"id":-1}`)}, 167 {0, []byte(`{"id":"0"}`)}, 168 {10, []byte(`{"id":10}`)}, 169 } 170 171 type Foo struct { 172 Bar Snowflake `json:"id,omitempty"` 173 } 174 175 foo := &Foo{} 176 for i := range data { 177 wants := data[i].result 178 input := data[i].data 179 err := json.Unmarshal(input, foo) 180 if err != nil { 181 t.Error(err.Error() + " | " + "given input of: " + string(input)) 182 } 183 184 if uint64(foo.Bar) != wants { 185 t.Errorf("incorrect snowflake ID. Got %d, wants %d", foo.Bar, wants) 186 } 187 } 188 189 // fail on letters in snowflake ID's 190 evilJSON := []byte("{\"id\":\"89945379a84753\"}") 191 err := json.Unmarshal(evilJSON, foo) 192 if err == nil { 193 t.Error("expected to fail, but continued to parse string as uint64") 194 } 195 signedIntJSON := []byte("{\"id\":\"-234234\"}") 196 if err := json.Unmarshal(signedIntJSON, foo); err != nil { 197 t.Error(err) 198 } 199 } 200 201 func BenchmarkUnmarshalJSON(b *testing.B) { 202 dataSets := [][]byte{ 203 []byte("\"8994537984753\""), 204 []byte("\"4573485\""), 205 []byte("\"00002349872349\""), 206 []byte("\"435453\""), 207 []byte("\"4987598525434463\""), 208 []byte("\"059823042\""), 209 []byte("\"698734534634\""), 210 []byte("\"024795873495\""), 211 []byte("\"0598360703000\""), 212 } 213 b.Run("string", func(b *testing.B) { 214 var result string 215 var i int 216 length := len(dataSets) 217 for n := 0; n < b.N; n++ { 218 result = string(dataSets[i]) 219 i++ 220 if i == length { 221 i = 0 222 } 223 } 224 if result == "" { 225 } 226 }) 227 b.Run("snowflake", func(b *testing.B) { 228 var s Snowflake 229 var i int 230 length := len(dataSets) 231 for n := 0; n < b.N; n++ { 232 if err := s.UnmarshalJSON(dataSets[i]); err != nil { 233 b.Error(err) 234 } 235 i++ 236 if i == length { 237 i = 0 238 } 239 } 240 }) 241 type fooOld struct { 242 Foo string `json:"id"` 243 } 244 type fooNew struct { 245 Foo Snowflake `json:"id"` 246 } 247 dataSetsJSON := [][]byte{ 248 []byte("{\"id\":\"8994537984753\"}"), 249 []byte("{\"id\":\"4573485\"}"), 250 []byte("{\"id\":\"00002349872349\"}"), 251 []byte("{\"id\":\"435453\"}"), 252 []byte("{\"id\":\"4987598525434463\"}"), 253 []byte("{\"id\":\"059823042\"}"), 254 []byte("{\"id\":\"698734534634\"}"), 255 []byte("{\"id\":\"024795873495\"}"), 256 []byte("{\"id\":\"0598360703000\"}"), 257 []byte("{\"id\":null}"), 258 } 259 b.Run("string-struct", func(b *testing.B) { 260 foo := &fooOld{} 261 var i int 262 length := len(dataSetsJSON) 263 for n := 0; n < b.N; n++ { 264 _ = json.Unmarshal(dataSetsJSON[i], foo) 265 i++ 266 if i == length { 267 i = 0 268 } 269 } 270 }) 271 b.Run("snowflake-struct", func(b *testing.B) { 272 foo := &fooNew{} 273 var i int 274 length := len(dataSetsJSON) 275 for n := 0; n < b.N; n++ { 276 _ = json.Unmarshal(dataSetsJSON[i], foo) 277 i++ 278 if i == length { 279 i = 0 280 } 281 } 282 }) 283 } 284 285 var sink_nullcheck bool 286 var sink_nullcheck2 bool 287 var sink_nullcheck3 bool 288 289 func BenchmarkNullCheck(b *testing.B) { 290 // this trick isn't needed any longer, as we assume none string values starting with n, with a length of 4 is null 291 b.Run("asci-sum", func(b *testing.B) { 292 data := []byte(`null`) 293 length := len(data) 294 start := 0 295 for n := 0; n < b.N; n++ { 296 sink_nullcheck = length < 6 && int(data[start])+int(data[start+1])+int(data[start+2])+int(data[start+3]) == int('n'+'u'+'l'+'l') 297 } 298 }) 299 b.Run("branched", func(b *testing.B) { 300 data := []byte(`null`) 301 length := len(data) 302 start := 0 303 for n := 0; n < b.N; n++ { 304 sink_nullcheck2 = length < 6 && data[start] == 'n' && data[start+1] == 'u' && data[start+2] == 'l' && data[start+3] == 'l' 305 } 306 }) 307 b.Run("string", func(b *testing.B) { 308 data := []byte(`null`) 309 length := len(data) 310 for n := 0; n < b.N; n++ { 311 sink_nullcheck3 = length == 4 && string(data) == "null" 312 } 313 }) 314 b.Run("assuming", func(b *testing.B) { 315 data := []byte(`null`) 316 length := len(data) 317 start := 0 318 for n := 0; n < b.N; n++ { 319 sink_nullcheck3 = length == 4 && data[start] == 'n' 320 } 321 }) 322 }