Added Parsers and Tests fixes #6
This commit is contained in:
		| @@ -1,6 +1,6 @@ | ||||
| snowflake | ||||
| ==== | ||||
| [](https://godoc.org/github.com/bwmarrin/snowflake) [](http://goreportcard.com/report/bwmarrin/snowflake) [](https://travis-ci.org/bwmarrin/snowflake) [](https://discord.gg/0f1SbxBZjYq9jLBk) | ||||
| [](https://godoc.org/github.com/bwmarrin/snowflake) [](http://goreportcard.com/report/bwmarrin/snowflake) [](https://gocover.io/github.com/bwmarrin/snowflake) [](https://travis-ci.org/bwmarrin/snowflake) [](https://discord.gg/0f1SbxBZjYq9jLBk) | ||||
|  | ||||
| snowflake is a [Go](https://golang.org/) package that provides | ||||
| * A very simple Twitter snowflake generator. | ||||
|   | ||||
							
								
								
									
										56
									
								
								snowflake.go
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								snowflake.go
									
									
									
									
									
								
							| @@ -166,25 +166,38 @@ func (f ID) Int64() int64 { | ||||
| 	return int64(f) | ||||
| } | ||||
|  | ||||
| // ParseInt64 converts an int64 into a snowflake ID | ||||
| func ParseInt64(id int64) ID { | ||||
| 	return ID(id) | ||||
| } | ||||
|  | ||||
| // String returns a string of the snowflake ID | ||||
| func (f ID) String() string { | ||||
| 	return strconv.FormatInt(int64(f), 10) | ||||
| } | ||||
|  | ||||
| // ParseString converts a string into a snowflake ID | ||||
| func ParseString(id string) (ID, error) { | ||||
| 	i, err := strconv.ParseInt(id, 10, 64) | ||||
| 	return ID(i), err | ||||
|  | ||||
| } | ||||
|  | ||||
| // Base2 returns a string base2 of the snowflake ID | ||||
| func (f ID) Base2() string { | ||||
| 	return strconv.FormatInt(int64(f), 2) | ||||
| } | ||||
|  | ||||
| // Base36 returns a base36 string of the snowflake ID | ||||
| func (f ID) Base36() string { | ||||
| 	return strconv.FormatInt(int64(f), 36) | ||||
| // ParseBase2 converts a Base2 string into a snowflake ID | ||||
| func ParseBase2(id string) (ID, error) { | ||||
| 	i, err := strconv.ParseInt(id, 2, 64) | ||||
| 	return ID(i), err | ||||
| } | ||||
|  | ||||
| // Base32 uses the z-base-32 character set but encodes and decodes similar | ||||
| // to base58, allowing it to create an even smaller result string. | ||||
| // NOTE: There are many different base32 implementations so becareful when | ||||
| // doing any interoperation interop with other packages. | ||||
| // doing any interoperation. | ||||
| func (f ID) Base32() string { | ||||
|  | ||||
| 	if f < 32 { | ||||
| @@ -207,7 +220,7 @@ func (f ID) Base32() string { | ||||
|  | ||||
| // ParseBase32 parses a base32 []byte into a snowflake ID | ||||
| // NOTE: There are many different base32 implementations so becareful when | ||||
| // doing any interoperation interop with other packages. | ||||
| // doing any interoperation. | ||||
| func ParseBase32(b []byte) (ID, error) { | ||||
|  | ||||
| 	var id int64 | ||||
| @@ -222,6 +235,17 @@ func ParseBase32(b []byte) (ID, error) { | ||||
| 	return ID(id), nil | ||||
| } | ||||
|  | ||||
| // Base36 returns a base36 string of the snowflake ID | ||||
| func (f ID) Base36() string { | ||||
| 	return strconv.FormatInt(int64(f), 36) | ||||
| } | ||||
|  | ||||
| // ParseBase36 converts a Base36 string into a snowflake ID | ||||
| func ParseBase36(id string) (ID, error) { | ||||
| 	i, err := strconv.ParseInt(id, 36, 64) | ||||
| 	return ID(i), err | ||||
| } | ||||
|  | ||||
| // Base58 returns a base58 string of the snowflake ID | ||||
| func (f ID) Base58() string { | ||||
|  | ||||
| @@ -263,11 +287,27 @@ func (f ID) Base64() string { | ||||
| 	return base64.StdEncoding.EncodeToString(f.Bytes()) | ||||
| } | ||||
|  | ||||
| // ParseBase64 converts a base64 string into a snowflake ID | ||||
| func ParseBase64(id string) (ID, error) { | ||||
| 	b, err := base64.StdEncoding.DecodeString(id) | ||||
| 	if err != nil { | ||||
| 		return -1, err | ||||
| 	} | ||||
| 	return ParseBytes(b) | ||||
|  | ||||
| } | ||||
|  | ||||
| // Bytes returns a byte slice of the snowflake ID | ||||
| func (f ID) Bytes() []byte { | ||||
| 	return []byte(f.String()) | ||||
| } | ||||
|  | ||||
| // ParseBytes converts a byte slice into a snowflake ID | ||||
| func ParseBytes(id []byte) (ID, error) { | ||||
| 	i, err := strconv.ParseInt(string(id), 10, 64) | ||||
| 	return ID(i), err | ||||
| } | ||||
|  | ||||
| // IntBytes returns an array of bytes of the snowflake ID, encoded as a | ||||
| // big endian integer. | ||||
| func (f ID) IntBytes() [8]byte { | ||||
| @@ -276,6 +316,12 @@ func (f ID) IntBytes() [8]byte { | ||||
| 	return b | ||||
| } | ||||
|  | ||||
| // ParseIntBytes converts an array of bytes encoded as big endian integer as | ||||
| // a snowflake ID | ||||
| func ParseIntBytes(id [8]byte) ID { | ||||
| 	return ID(int64(binary.BigEndian.Uint64(id[:]))) | ||||
| } | ||||
|  | ||||
| // Time returns an int64 unix timestamp in milliseconds of the snowflake ID time | ||||
| // DEPRECATED: the below function will be removed in a future release. | ||||
| func (f ID) Time() int64 { | ||||
|   | ||||
| @@ -6,13 +6,17 @@ import ( | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| // check if Generate will create duplicate IDs | ||||
| //****************************************************************************** | ||||
| // General Test funcs | ||||
|  | ||||
| // lazy check if Generate will create duplicate IDs | ||||
| // would be good to later enhance this with more smarts | ||||
| func TestGenerateDuplicateID(t *testing.T) { | ||||
|  | ||||
| 	node, _ := NewNode(1) | ||||
|  | ||||
| 	var x, y ID | ||||
| 	for i := 0; i < 100000000; i++ { | ||||
| 	for i := 0; i < 1000000; i++ { | ||||
| 		y = node.Generate() | ||||
| 		if x == y { | ||||
| 			t.Errorf("x(%d) & y(%d) are the same", x, y) | ||||
| @@ -40,17 +44,282 @@ func TestRace(t *testing.T) { | ||||
|  | ||||
| } | ||||
|  | ||||
| //****************************************************************************** | ||||
| // Converters/Parsers Test funcs | ||||
| // We should have funcs here to test conversion both ways for everything | ||||
|  | ||||
| func TestPrintAll(t *testing.T) { | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	id := node.Generate() | ||||
|  | ||||
| 	t.Logf("Int64    : %#v", id.Int64()) | ||||
| 	t.Logf("String   : %#v", id.String()) | ||||
| 	t.Logf("Base2    : %#v", id.Base2()) | ||||
| 	t.Logf("Base32   : %#v", id.Base32()) | ||||
| 	t.Logf("Base36   : %#v", id.Base36()) | ||||
| 	t.Logf("Base58   : %#v", id.Base58()) | ||||
| 	t.Logf("Base64   : %#v", id.Base64()) | ||||
| 	t.Logf("Bytes    : %#v", id.Bytes()) | ||||
| 	t.Logf("IntBytes : %#v", id.IntBytes()) | ||||
|  | ||||
| } | ||||
|  | ||||
| func TestInt64(t *testing.T) { | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	oID := node.Generate() | ||||
| 	i := oID.Int64() | ||||
|  | ||||
| 	pID := ParseInt64(i) | ||||
| 	if pID != oID { | ||||
| 		t.Fatalf("pID %v != oID %v", pID, oID) | ||||
| 	} | ||||
|  | ||||
| 	mi := int64(1116766490855473152) | ||||
| 	pID = ParseInt64(mi) | ||||
| 	if pID.Int64() != mi { | ||||
| 		t.Fatalf("pID %v != mi %v", pID.Int64(), mi) | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| func TestString(t *testing.T) { | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	oID := node.Generate() | ||||
| 	si := oID.String() | ||||
|  | ||||
| 	pID, err := ParseString(si) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	if pID != oID { | ||||
| 		t.Fatalf("pID %v != oID %v", pID, oID) | ||||
| 	} | ||||
|  | ||||
| 	ms := `1116766490855473152` | ||||
| 	_, err = ParseString(ms) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	ms = `1112316766490855473152` | ||||
| 	_, err = ParseString(ms) | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("no error parsing %s", ms) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestBase2(t *testing.T) { | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	oID := node.Generate() | ||||
| 	i := oID.Base2() | ||||
|  | ||||
| 	pID, err := ParseBase2(i) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
| 	if pID != oID { | ||||
| 		t.Fatalf("pID %v != oID %v", pID, oID) | ||||
| 	} | ||||
|  | ||||
| 	ms := `111101111111101110110101100101001000000000000000000000000000` | ||||
| 	_, err = ParseBase2(ms) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	ms = `1112316766490855473152` | ||||
| 	_, err = ParseBase2(ms) | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("no error parsing %s", ms) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestBase32(t *testing.T) { | ||||
|  | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < 100; i++ { | ||||
|  | ||||
| 		sf := node.Generate() | ||||
| 		b32i := sf.Base32() | ||||
| 		psf, err := ParseBase32([]byte(b32i)) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if sf != psf { | ||||
| 			t.Fatal("Parsed does not match String.") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestBase36(t *testing.T) { | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	oID := node.Generate() | ||||
| 	i := oID.Base36() | ||||
|  | ||||
| 	pID, err := ParseBase36(i) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
| 	if pID != oID { | ||||
| 		t.Fatalf("pID %v != oID %v", pID, oID) | ||||
| 	} | ||||
|  | ||||
| 	ms := `8hgmw4blvlkw` | ||||
| 	_, err = ParseBase36(ms) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	ms = `68h5gmw443blv2lk1w` | ||||
| 	_, err = ParseBase36(ms) | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("no error parsing, %s", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestBase58(t *testing.T) { | ||||
|  | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < 10; i++ { | ||||
|  | ||||
| 		sf := node.Generate() | ||||
| 		b58 := sf.Base58() | ||||
| 		psf, err := ParseBase58([]byte(b58)) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if sf != psf { | ||||
| 			t.Fatal("Parsed does not match String.") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestBase64(t *testing.T) { | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	oID := node.Generate() | ||||
| 	i := oID.Base64() | ||||
|  | ||||
| 	pID, err := ParseBase64(i) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
| 	if pID != oID { | ||||
| 		t.Fatalf("pID %v != oID %v", pID, oID) | ||||
| 	} | ||||
|  | ||||
| 	ms := `MTExNjgxOTQ5NDY2MDk5NzEyMA==` | ||||
| 	_, err = ParseBase64(ms) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	ms = `MTExNjgxOTQ5NDY2MDk5NzEyMA` | ||||
| 	_, err = ParseBase64(ms) | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("no error parsing, %s", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestBytes(t *testing.T) { | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	oID := node.Generate() | ||||
| 	i := oID.Bytes() | ||||
|  | ||||
| 	pID, err := ParseBytes(i) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %s", err) | ||||
| 	} | ||||
| 	if pID != oID { | ||||
| 		t.Fatalf("pID %v != oID %v", pID, oID) | ||||
| 	} | ||||
|  | ||||
| 	ms := []byte{0x31, 0x31, 0x31, 0x36, 0x38, 0x32, 0x31, 0x36, 0x37, 0x39, 0x35, 0x37, 0x30, 0x34, 0x31, 0x39, 0x37, 0x31, 0x32} | ||||
| 	_, err = ParseBytes(ms) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error parsing, %#v", err) | ||||
| 	} | ||||
|  | ||||
| 	ms = []byte{0xFF, 0xFF, 0xFF, 0x31, 0x31, 0x31, 0x36, 0x38, 0x32, 0x31, 0x36, 0x37, 0x39, 0x35, 0x37, 0x30, 0x34, 0x31, 0x39, 0x37, 0x31, 0x32} | ||||
| 	_, err = ParseBytes(ms) | ||||
| 	if err == nil { | ||||
| 		t.Fatalf("no error parsing, %#v", err) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestIntBytes(t *testing.T) { | ||||
| 	node, err := NewNode(0) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("error creating NewNode, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	oID := node.Generate() | ||||
| 	i := oID.IntBytes() | ||||
|  | ||||
| 	pID := ParseIntBytes(i) | ||||
| 	if pID != oID { | ||||
| 		t.Fatalf("pID %v != oID %v", pID, oID) | ||||
| 	} | ||||
|  | ||||
| 	ms := [8]uint8{0xf, 0x7f, 0xc0, 0xfc, 0x2f, 0x80, 0x0, 0x0} | ||||
| 	mi := int64(1116823421972381696) | ||||
| 	pID = ParseIntBytes(ms) | ||||
| 	if pID.Int64() != mi { | ||||
| 		t.Fatalf("pID %v != mi %v", pID.Int64(), mi) | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| //****************************************************************************** | ||||
| // Marshall Test Methods | ||||
|  | ||||
| func TestMarshalJSON(t *testing.T) { | ||||
| 	id := ID(13587) | ||||
| 	expected := "\"13587\"" | ||||
|  | ||||
| 	bytes, err := id.MarshalJSON() | ||||
| 	if err != nil { | ||||
| 		t.Error("Unexpected error during MarshalJSON") | ||||
| 		t.Fatalf("Unexpected error during MarshalJSON") | ||||
| 	} | ||||
|  | ||||
| 	if string(bytes) != expected { | ||||
| 		t.Errorf("Got %s, expected %s", string(bytes), expected) | ||||
| 		t.Fatalf("Got %s, expected %s", string(bytes), expected) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -58,7 +327,7 @@ func TestMarshalsIntBytes(t *testing.T) { | ||||
| 	id := ID(13587).IntBytes() | ||||
| 	expected := []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x35, 0x13} | ||||
| 	if !bytes.Equal(id[:], expected) { | ||||
| 		t.Errorf("Expected ID to be encoded as %v, got %v", expected, id) | ||||
| 		t.Fatalf("Expected ID to be encoded as %v, got %v", expected, id) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -77,32 +346,17 @@ func TestUnmarshalJSON(t *testing.T) { | ||||
| 		var id ID | ||||
| 		err := id.UnmarshalJSON([]byte(tc.json)) | ||||
| 		if !reflect.DeepEqual(err, tc.expectedErr) { | ||||
| 			t.Errorf("Expected to get error '%s' decoding JSON, but got '%s'", tc.expectedErr, err) | ||||
| 			t.Fatalf("Expected to get error '%s' decoding JSON, but got '%s'", tc.expectedErr, err) | ||||
| 		} | ||||
|  | ||||
| 		if id != tc.expectedID { | ||||
| 			t.Errorf("Expected to get ID '%s' decoding JSON, but got '%s'", tc.expectedID, id) | ||||
| 			t.Fatalf("Expected to get ID '%s' decoding JSON, but got '%s'", tc.expectedID, id) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func TestBase32(t *testing.T) { | ||||
|  | ||||
| 	node, _ := NewNode(1) | ||||
|  | ||||
| 	for i := 0; i < 100; i++ { | ||||
|  | ||||
| 		sf := node.Generate() | ||||
| 		b32i := sf.Base32() | ||||
| 		psf, err := ParseBase32([]byte(b32i)) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if sf != psf { | ||||
| 			t.Fatal("Parsed does not match String.") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| // **************************************************************************** | ||||
| // Benchmark Methods | ||||
|  | ||||
| func BenchmarkParseBase32(b *testing.B) { | ||||
|  | ||||
| @@ -129,24 +383,6 @@ func BenchmarkBase32(b *testing.B) { | ||||
| 		sf.Base32() | ||||
| 	} | ||||
| } | ||||
| func TestBase58(t *testing.T) { | ||||
|  | ||||
| 	node, _ := NewNode(1) | ||||
|  | ||||
| 	for i := 0; i < 10; i++ { | ||||
|  | ||||
| 		sf := node.Generate() | ||||
| 		b58 := sf.Base58() | ||||
| 		psf, err := ParseBase58([]byte(b58)) | ||||
| 		if err != nil { | ||||
| 			t.Fatal(err) | ||||
| 		} | ||||
| 		if sf != psf { | ||||
| 			t.Fatal("Parsed does not match String.") | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func BenchmarkParseBase58(b *testing.B) { | ||||
|  | ||||
| 	node, _ := NewNode(1) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user