Commit d91b419e authored by Jeromy's avatar Jeromy
Browse files

WIP

parent a40ef343
// Copyright (C) 2013-2014 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package uuid
import (
"testing"
)
func BenchmarkFromBytes(b *testing.B) {
bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
for i := 0; i < b.N; i++ {
FromBytes(bytes)
}
}
func BenchmarkFromString(b *testing.B) {
s := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
for i := 0; i < b.N; i++ {
FromString(s)
}
}
func BenchmarkFromStringUrn(b *testing.B) {
s := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
for i := 0; i < b.N; i++ {
FromString(s)
}
}
func BenchmarkFromStringWithBrackets(b *testing.B) {
s := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}"
for i := 0; i < b.N; i++ {
FromString(s)
}
}
func BenchmarkNewV1(b *testing.B) {
for i := 0; i < b.N; i++ {
NewV1()
}
}
func BenchmarkNewV2(b *testing.B) {
for i := 0; i < b.N; i++ {
NewV2(DomainPerson)
}
}
func BenchmarkNewV3(b *testing.B) {
for i := 0; i < b.N; i++ {
NewV3(NamespaceDNS, "www.example.com")
}
}
func BenchmarkNewV4(b *testing.B) {
for i := 0; i < b.N; i++ {
NewV4()
}
}
func BenchmarkNewV5(b *testing.B) {
for i := 0; i < b.N; i++ {
NewV5(NamespaceDNS, "www.example.com")
}
}
func BenchmarkMarshalBinary(b *testing.B) {
u := NewV4()
for i := 0; i < b.N; i++ {
u.MarshalBinary()
}
}
func BenchmarkMarshalText(b *testing.B) {
u := NewV4()
for i := 0; i < b.N; i++ {
u.MarshalText()
}
}
func BenchmarkUnmarshalBinary(b *testing.B) {
bytes := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
u := UUID{}
for i := 0; i < b.N; i++ {
u.UnmarshalBinary(bytes)
}
}
func BenchmarkUnmarshalText(b *testing.B) {
bytes := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
u := UUID{}
for i := 0; i < b.N; i++ {
u.UnmarshalText(bytes)
}
}
func BenchmarkMarshalToString(b *testing.B) {
u := NewV4()
for i := 0; i < b.N; i++ {
u.String()
}
}
{
"name": "go.uuid",
"author": "whyrusleeping",
"version": "0.0.0",
"language": "go",
"issues_url": "",
"gx": {
"dvcsimport": "github.com/satori/go.uuid"
}
}
\ No newline at end of file
// Copyright (C) 2013-2015 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Package uuid provides implementation of Universally Unique Identifier (UUID).
// Supported versions are 1, 3, 4 and 5 (as specified in RFC 4122) and
// version 2 (as specified in DCE 1.1).
package uuid
import (
"bytes"
"crypto/md5"
"crypto/rand"
"crypto/sha1"
"database/sql/driver"
"encoding/binary"
"encoding/hex"
"fmt"
"hash"
"net"
"os"
"sync"
"time"
)
// UUID layout variants.
const (
VariantNCS = iota
VariantRFC4122
VariantMicrosoft
VariantFuture
)
// UUID DCE domains.
const (
DomainPerson = iota
DomainGroup
DomainOrg
)
// Difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
const epochStart = 122192928000000000
// Used in string method conversion
const dash byte = '-'
// UUID v1/v2 storage.
var (
storageMutex sync.Mutex
storageOnce sync.Once
epochFunc = unixTimeFunc
clockSequence uint16
lastTime uint64
hardwareAddr [6]byte
posixUID = uint32(os.Getuid())
posixGID = uint32(os.Getgid())
)
// String parse helpers.
var (
urnPrefix = []byte("urn:uuid:")
byteGroups = []int{8, 4, 4, 4, 12}
)
func initClockSequence() {
buf := make([]byte, 2)
safeRandom(buf)
clockSequence = binary.BigEndian.Uint16(buf)
}
func initHardwareAddr() {
interfaces, err := net.Interfaces()
if err == nil {
for _, iface := range interfaces {
if len(iface.HardwareAddr) >= 6 {
copy(hardwareAddr[:], iface.HardwareAddr)
return
}
}
}
// Initialize hardwareAddr randomly in case
// of real network interfaces absence
safeRandom(hardwareAddr[:])
// Set multicast bit as recommended in RFC 4122
hardwareAddr[0] |= 0x01
}
func initStorage() {
initClockSequence()
initHardwareAddr()
}
func safeRandom(dest []byte) {
if _, err := rand.Read(dest); err != nil {
panic(err)
}
}
// Returns difference in 100-nanosecond intervals between
// UUID epoch (October 15, 1582) and current time.
// This is default epoch calculation function.
func unixTimeFunc() uint64 {
return epochStart + uint64(time.Now().UnixNano()/100)
}
// UUID representation compliant with specification
// described in RFC 4122.
type UUID [16]byte
// The nil UUID is special form of UUID that is specified to have all
// 128 bits set to zero.
var Nil = UUID{}
// Predefined namespace UUIDs.
var (
NamespaceDNS, _ = FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
NamespaceURL, _ = FromString("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
NamespaceOID, _ = FromString("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
NamespaceX500, _ = FromString("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
)
// And returns result of binary AND of two UUIDs.
func And(u1 UUID, u2 UUID) UUID {
u := UUID{}
for i := 0; i < 16; i++ {
u[i] = u1[i] & u2[i]
}
return u
}
// Or returns result of binary OR of two UUIDs.
func Or(u1 UUID, u2 UUID) UUID {
u := UUID{}
for i := 0; i < 16; i++ {
u[i] = u1[i] | u2[i]
}
return u
}
// Equal returns true if u1 and u2 equals, otherwise returns false.
func Equal(u1 UUID, u2 UUID) bool {
return bytes.Equal(u1[:], u2[:])
}
// Version returns algorithm version used to generate UUID.
func (u UUID) Version() uint {
return uint(u[6] >> 4)
}
// Variant returns UUID layout variant.
func (u UUID) Variant() uint {
switch {
case (u[8] & 0x80) == 0x00:
return VariantNCS
case (u[8]&0xc0)|0x80 == 0x80:
return VariantRFC4122
case (u[8]&0xe0)|0xc0 == 0xc0:
return VariantMicrosoft
}
return VariantFuture
}
// Bytes returns bytes slice representation of UUID.
func (u UUID) Bytes() []byte {
return u[:]
}
// Returns canonical string representation of UUID:
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (u UUID) String() string {
buf := make([]byte, 36)
hex.Encode(buf[0:8], u[0:4])
buf[8] = dash
hex.Encode(buf[9:13], u[4:6])
buf[13] = dash
hex.Encode(buf[14:18], u[6:8])
buf[18] = dash
hex.Encode(buf[19:23], u[8:10])
buf[23] = dash
hex.Encode(buf[24:], u[10:])
return string(buf)
}
// SetVersion sets version bits.
func (u *UUID) SetVersion(v byte) {
u[6] = (u[6] & 0x0f) | (v << 4)
}
// SetVariant sets variant bits as described in RFC 4122.
func (u *UUID) SetVariant() {
u[8] = (u[8] & 0xbf) | 0x80
}
// MarshalText implements the encoding.TextMarshaler interface.
// The encoding is the same as returned by String.
func (u UUID) MarshalText() (text []byte, err error) {
text = []byte(u.String())
return
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// Following formats are supported:
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8",
// "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}",
// "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
func (u *UUID) UnmarshalText(text []byte) (err error) {
if len(text) < 32 {
err = fmt.Errorf("uuid: invalid UUID string: %s", text)
return
}
if bytes.Equal(text[:9], urnPrefix) {
text = text[9:]
} else if text[0] == '{' {
text = text[1:]
}
b := u[:]
for _, byteGroup := range byteGroups {
if text[0] == '-' {
text = text[1:]
}
_, err = hex.Decode(b[:byteGroup/2], text[:byteGroup])
if err != nil {
return
}
text = text[byteGroup:]
b = b[byteGroup/2:]
}
return
}
// MarshalBinary implements the encoding.BinaryMarshaler interface.
func (u UUID) MarshalBinary() (data []byte, err error) {
data = u.Bytes()
return
}
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface.
// It will return error if the slice isn't 16 bytes long.
func (u *UUID) UnmarshalBinary(data []byte) (err error) {
if len(data) != 16 {
err = fmt.Errorf("uuid: UUID must be exactly 16 bytes long, got %d bytes", len(data))
return
}
copy(u[:], data)
return
}
// Value implements the driver.Valuer interface.
func (u UUID) Value() (driver.Value, error) {
return u.String(), nil
}
// Scan implements the sql.Scanner interface.
// A 16-byte slice is handled by UnmarshalBinary, while
// a longer byte slice or a string is handled by UnmarshalText.
func (u *UUID) Scan(src interface{}) error {
switch src := src.(type) {
case []byte:
if len(src) == 16 {
return u.UnmarshalBinary(src)
}
return u.UnmarshalText(src)
case string:
return u.UnmarshalText([]byte(src))
}
return fmt.Errorf("uuid: cannot convert %T to UUID", src)
}
// FromBytes returns UUID converted from raw byte slice input.
// It will return error if the slice isn't 16 bytes long.
func FromBytes(input []byte) (u UUID, err error) {
err = u.UnmarshalBinary(input)
return
}
// FromBytesOrNil returns UUID converted from raw byte slice input.
// Same behavior as FromBytes, but returns a Nil UUID on error.
func FromBytesOrNil(input []byte) UUID {
uuid, err := FromBytes(input)
if err != nil {
return Nil
}
return uuid
}
// FromString returns UUID parsed from string input.
// Input is expected in a form accepted by UnmarshalText.
func FromString(input string) (u UUID, err error) {
err = u.UnmarshalText([]byte(input))
return
}
// FromStringOrNil returns UUID parsed from string input.
// Same behavior as FromString, but returns a Nil UUID on error.
func FromStringOrNil(input string) UUID {
uuid, err := FromString(input)
if err != nil {
return Nil
}
return uuid
}
// Returns UUID v1/v2 storage state.
// Returns epoch timestamp, clock sequence, and hardware address.
func getStorage() (uint64, uint16, []byte) {
storageOnce.Do(initStorage)
storageMutex.Lock()
defer storageMutex.Unlock()
timeNow := epochFunc()
// Clock changed backwards since last UUID generation.
// Should increase clock sequence.
if timeNow <= lastTime {
clockSequence++
}
lastTime = timeNow
return timeNow, clockSequence, hardwareAddr[:]
}
// NewV1 returns UUID based on current timestamp and MAC address.
func NewV1() UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := getStorage()
binary.BigEndian.PutUint32(u[0:], uint32(timeNow))
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
copy(u[10:], hardwareAddr)
u.SetVersion(1)
u.SetVariant()
return u
}
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
func NewV2(domain byte) UUID {
u := UUID{}
timeNow, clockSeq, hardwareAddr := getStorage()
switch domain {
case DomainPerson:
binary.BigEndian.PutUint32(u[0:], posixUID)
case DomainGroup:
binary.BigEndian.PutUint32(u[0:], posixGID)
}
binary.BigEndian.PutUint16(u[4:], uint16(timeNow>>32))
binary.BigEndian.PutUint16(u[6:], uint16(timeNow>>48))
binary.BigEndian.PutUint16(u[8:], clockSeq)
u[9] = domain
copy(u[10:], hardwareAddr)
u.SetVersion(2)
u.SetVariant()
return u
}
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
func NewV3(ns UUID, name string) UUID {
u := newFromHash(md5.New(), ns, name)
u.SetVersion(3)
u.SetVariant()
return u
}
// NewV4 returns random generated UUID.
func NewV4() UUID {
u := UUID{}
safeRandom(u[:])
u.SetVersion(4)
u.SetVariant()
return u
}
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
func NewV5(ns UUID, name string) UUID {
u := newFromHash(sha1.New(), ns, name)
u.SetVersion(5)
u.SetVariant()
return u
}
// Returns UUID based on hashing of namespace UUID and name.
func newFromHash(h hash.Hash, ns UUID, name string) UUID {
u := UUID{}
h.Write(ns[:])
h.Write([]byte(name))
copy(u[:], h.Sum(nil))
return u
}
// Copyright (C) 2013, 2015 by Maxim Bublis <b@codemonkey.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package uuid
import (
"bytes"
"testing"
)
func TestBytes(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
bytes1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
if !bytes.Equal(u.Bytes(), bytes1) {
t.Errorf("Incorrect bytes representation for UUID: %s", u)
}
}
func TestString(t *testing.T) {
if NamespaceDNS.String() != "6ba7b810-9dad-11d1-80b4-00c04fd430c8" {
t.Errorf("Incorrect string representation for UUID: %s", NamespaceDNS.String())
}
}
func TestEqual(t *testing.T) {
if !Equal(NamespaceDNS, NamespaceDNS) {
t.Errorf("Incorrect comparison of %s and %s", NamespaceDNS, NamespaceDNS)
}
if Equal(NamespaceDNS, NamespaceURL) {
t.Errorf("Incorrect comparison of %s and %s", NamespaceDNS, NamespaceURL)
}
}
func TestOr(t *testing.T) {
u1 := UUID{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff}
u2 := UUID{0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00}
u := UUID{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
if !Equal(u, Or(u1, u2)) {
t.Errorf("Incorrect bitwise OR result %s", Or(u1, u2))
}
}
func TestAnd(t *testing.T) {
u1 := UUID{0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff}
u2 := UUID{0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00}
u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
if !Equal(u, And(u1, u2)) {
t.Errorf("Incorrect bitwise AND result %s", And(u1, u2))
}
}
func TestVersion(t *testing.T) {
u := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
if u.Version() != 1 {
t.Errorf("Incorrect version for UUID: %d", u.Version())
}
}
func TestSetVersion(t *testing.T) {
u := UUID{}
u.SetVersion(4)
if u.Version() != 4 {
t.Errorf("Incorrect version for UUID after u.setVersion(4): %d", u.Version())
}
}
func TestVariant(t *testing.T) {
u1 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
if u1.Variant() != VariantNCS {
t.Errorf("Incorrect variant for UUID variant %d: %d", VariantNCS, u1.Variant())
}
u2 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
if u2.Variant() != VariantRFC4122 {
t.Errorf("Incorrect variant for UUID variant %d: %d", VariantRFC4122, u2.Variant())
}
u3 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
if u3.Variant() != VariantMicrosoft {
t.Errorf("Incorrect variant for UUID variant %d: %d", VariantMicrosoft, u3.Variant())
}
u4 := UUID{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
if u4.Variant() != VariantFuture {
t.Errorf("Incorrect variant for UUID variant %d: %d", VariantFuture, u4.Variant())
}
}
func TestSetVariant(t *testing.T) {
u := new(UUID)
u.SetVariant()
if u.Variant() != VariantRFC4122 {
t.Errorf("Incorrect variant for UUID after u.setVariant(): %d", u.Variant())
}
}
func TestFromBytes(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
u1, err := FromBytes(b1)
if err != nil {
t.Errorf("Error parsing UUID from bytes: %s", err)
}
if !Equal(u, u1) {
t.Errorf("UUIDs should be equal: %s and %s", u, u1)
}
b2 := []byte{}
_, err = FromBytes(b2)
if err == nil {
t.Errorf("Should return error parsing from empty byte slice, got %s", err)
}
}
func TestMarshalBinary(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
b2, err := u.MarshalBinary()
if err != nil {
t.Errorf("Error marshaling UUID: %s", err)
}
if !bytes.Equal(b1, b2) {
t.Errorf("Marshaled UUID should be %s, got %s", b1, b2)
}
}
func TestUnmarshalBinary(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
u1 := UUID{}
err := u1.UnmarshalBinary(b1)
if err != nil {
t.Errorf("Error unmarshaling UUID: %s", err)
}
if !Equal(u, u1) {
t.Errorf("UUIDs should be equal: %s and %s", u, u1)
}
b2 := []byte{}
u2 := UUID{}
err = u2.UnmarshalBinary(b2)
if err == nil {
t.Errorf("Should return error unmarshalling from empty byte slice, got %s", err)
}
}
func TestFromString(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
s2 := "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}"
s3 := "urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8"
_, err := FromString("")
if err == nil {
t.Errorf("Should return error trying to parse empty string, got %s", err)
}
u1, err := FromString(s1)
if err != nil {
t.Errorf("Error parsing UUID from string: %s", err)
}
if !Equal(u, u1) {
t.Errorf("UUIDs should be equal: %s and %s", u, u1)
}
u2, err := FromString(s2)
if err != nil {
t.Errorf("Error parsing UUID from string: %s", err)
}
if !Equal(u, u2) {
t.Errorf("UUIDs should be equal: %s and %s", u, u2)
}
u3, err := FromString(s3)
if err != nil {
t.Errorf("Error parsing UUID from string: %s", err)
}
if !Equal(u, u3) {
t.Errorf("UUIDs should be equal: %s and %s", u, u3)
}
}
func TestFromStringOrNil(t *testing.T) {
u := FromStringOrNil("")
if u != Nil {
t.Errorf("Should return Nil UUID on parse failure, got %s", u)
}
}
func TestFromBytesOrNil(t *testing.T) {
b := []byte{}
u := FromBytesOrNil(b)
if u != Nil {
t.Errorf("Should return Nil UUID on parse failure, got %s", u)
}
}
func TestMarshalText(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
b2, err := u.MarshalText()
if err != nil {
t.Errorf("Error marshaling UUID: %s", err)
}
if !bytes.Equal(b1, b2) {
t.Errorf("Marshaled UUID should be %s, got %s", b1, b2)
}
}
func TestUnmarshalText(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
u1 := UUID{}
err := u1.UnmarshalText(b1)
if err != nil {
t.Errorf("Error unmarshaling UUID: %s", err)
}
if !Equal(u, u1) {
t.Errorf("UUIDs should be equal: %s and %s", u, u1)
}
b2 := []byte("")
u2 := UUID{}
err = u2.UnmarshalText(b2)
if err == nil {
t.Errorf("Should return error trying to unmarshal from empty string")
}
}
func TestValue(t *testing.T) {
u, err := FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
if err != nil {
t.Errorf("Error parsing UUID from string: %s", err)
}
val, err := u.Value()
if err != nil {
t.Errorf("Error getting UUID value: %s", err)
}
if val != u.String() {
t.Errorf("Wrong value returned, should be equal: %s and %s", val, u)
}
}
func TestScanBinary(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
b1 := []byte{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
u1 := UUID{}
err := u1.Scan(b1)
if err != nil {
t.Errorf("Error unmarshaling UUID: %s", err)
}
if !Equal(u, u1) {
t.Errorf("UUIDs should be equal: %s and %s", u, u1)
}
b2 := []byte{}
u2 := UUID{}
err = u2.Scan(b2)
if err == nil {
t.Errorf("Should return error unmarshalling from empty byte slice, got %s", err)
}
}
func TestScanString(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
u1 := UUID{}
err := u1.Scan(s1)
if err != nil {
t.Errorf("Error unmarshaling UUID: %s", err)
}
if !Equal(u, u1) {
t.Errorf("UUIDs should be equal: %s and %s", u, u1)
}
s2 := ""
u2 := UUID{}
err = u2.Scan(s2)
if err == nil {
t.Errorf("Should return error trying to unmarshal from empty string")
}
}
func TestScanText(t *testing.T) {
u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}
b1 := []byte("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
u1 := UUID{}
err := u1.Scan(b1)
if err != nil {
t.Errorf("Error unmarshaling UUID: %s", err)
}
if !Equal(u, u1) {
t.Errorf("UUIDs should be equal: %s and %s", u, u1)
}
b2 := []byte("")
u2 := UUID{}
err = u2.Scan(b2)
if err == nil {
t.Errorf("Should return error trying to unmarshal from empty string")
}
}
func TestScanUnsupported(t *testing.T) {
u := UUID{}
err := u.Scan(true)
if err == nil {
t.Errorf("Should return error trying to unmarshal from bool")
}
}
func TestNewV1(t *testing.T) {
u := NewV1()
if u.Version() != 1 {
t.Errorf("UUIDv1 generated with incorrect version: %d", u.Version())
}
if u.Variant() != VariantRFC4122 {
t.Errorf("UUIDv1 generated with incorrect variant: %d", u.Variant())
}
u1 := NewV1()
u2 := NewV1()
if Equal(u1, u2) {
t.Errorf("UUIDv1 generated two equal UUIDs: %s and %s", u1, u2)
}
oldFunc := epochFunc
epochFunc = func() uint64 { return 0 }
u3 := NewV1()
u4 := NewV1()
if Equal(u3, u4) {
t.Errorf("UUIDv1 generated two equal UUIDs: %s and %s", u3, u4)
}
epochFunc = oldFunc
}
func TestNewV2(t *testing.T) {
u1 := NewV2(DomainPerson)
if u1.Version() != 2 {
t.Errorf("UUIDv2 generated with incorrect version: %d", u1.Version())
}
if u1.Variant() != VariantRFC4122 {
t.Errorf("UUIDv2 generated with incorrect variant: %d", u1.Variant())
}
u2 := NewV2(DomainGroup)
if u2.Version() != 2 {
t.Errorf("UUIDv2 generated with incorrect version: %d", u2.Version())
}
if u2.Variant() != VariantRFC4122 {
t.Errorf("UUIDv2 generated with incorrect variant: %d", u2.Variant())
}
}
func TestNewV3(t *testing.T) {
u := NewV3(NamespaceDNS, "www.example.com")
if u.Version() != 3 {
t.Errorf("UUIDv3 generated with incorrect version: %d", u.Version())
}
if u.Variant() != VariantRFC4122 {
t.Errorf("UUIDv3 generated with incorrect variant: %d", u.Variant())
}
if u.String() != "5df41881-3aed-3515-88a7-2f4a814cf09e" {
t.Errorf("UUIDv3 generated incorrectly: %s", u.String())
}
u = NewV3(NamespaceDNS, "python.org")
if u.String() != "6fa459ea-ee8a-3ca4-894e-db77e160355e" {
t.Errorf("UUIDv3 generated incorrectly: %s", u.String())
}
u1 := NewV3(NamespaceDNS, "golang.org")
u2 := NewV3(NamespaceDNS, "golang.org")
if !Equal(u1, u2) {
t.Errorf("UUIDv3 generated different UUIDs for same namespace and name: %s and %s", u1, u2)
}
u3 := NewV3(NamespaceDNS, "example.com")
if Equal(u1, u3) {
t.Errorf("UUIDv3 generated same UUIDs for different names in same namespace: %s and %s", u1, u2)
}
u4 := NewV3(NamespaceURL, "golang.org")
if Equal(u1, u4) {
t.Errorf("UUIDv3 generated same UUIDs for sane names in different namespaces: %s and %s", u1, u4)
}
}
func TestNewV4(t *testing.T) {
u := NewV4()
if u.Version() != 4 {
t.Errorf("UUIDv4 generated with incorrect version: %d", u.Version())
}
if u.Variant() != VariantRFC4122 {
t.Errorf("UUIDv4 generated with incorrect variant: %d", u.Variant())
}
}
func TestNewV5(t *testing.T) {
u := NewV5(NamespaceDNS, "www.example.com")
if u.Version() != 5 {
t.Errorf("UUIDv5 generated with incorrect version: %d", u.Version())
}
if u.Variant() != VariantRFC4122 {
t.Errorf("UUIDv5 generated with incorrect variant: %d", u.Variant())
}
u = NewV5(NamespaceDNS, "python.org")
if u.String() != "886313e1-3b8a-5372-9b90-0c9aee199e5d" {
t.Errorf("UUIDv5 generated incorrectly: %s", u.String())
}
u1 := NewV5(NamespaceDNS, "golang.org")
u2 := NewV5(NamespaceDNS, "golang.org")
if !Equal(u1, u2) {
t.Errorf("UUIDv5 generated different UUIDs for same namespace and name: %s and %s", u1, u2)
}
u3 := NewV5(NamespaceDNS, "example.com")
if Equal(u1, u3) {
t.Errorf("UUIDv5 generated same UUIDs for different names in same namespace: %s and %s", u1, u2)
}
u4 := NewV5(NamespaceURL, "golang.org")
if Equal(u1, u4) {
t.Errorf("UUIDv3 generated same UUIDs for sane names in different namespaces: %s and %s", u1, u4)
}
}
package util
import "os"
func FileExists(filename string) bool {
fi, err := os.Lstat(filename)
if fi != nil || (err != nil && !os.IsNotExist(err)) {
return true
}
return false
}
package util
import "testing"
func TestFileDoesNotExist(t *testing.T) {
t.Parallel()
if FileExists("i would be surprised to discover that this file exists") {
t.Fail()
}
}
{
"name": "go-ipfs-util",
"author": "whyrusleeping",
"version": "1.0.0",
"gxDependencies": [
{
"name": "go-base58",
"hash": "QmNsoHoCVhgXcv1Yg45jtkMgimxorTAN36fV9AQMFXHHAQ",
"version": "1.0.0"
},
{
"name": "go-multihash",
"hash": "Qma7dqy7ZVH4tkNJdC9TRrA82Uz5fQfbbwuvmNVVc17r7a",
"version": "0.0.0"
}
],
"language": "go",
"issues_url": "",
"gx": {
"dvcsimport": "github.com/ipfs/go-ipfs-util"
}
}
\ No newline at end of file
package util
import "time"
var TimeFormatIpfs = time.RFC3339Nano
func ParseRFC3339(s string) (time.Time, error) {
t, err := time.Parse(TimeFormatIpfs, s)
if err != nil {
return time.Time{}, err
}
return t.UTC(), nil
}
func FormatRFC3339(t time.Time) string {
return t.UTC().Format(TimeFormatIpfs)
}
package util
import (
"testing"
"time"
)
func TestTimeFormatParseInversion(t *testing.T) {
v, err := ParseRFC3339(FormatRFC3339(time.Now()))
if err != nil {
t.Fatal(err)
}
if v.Location() != time.UTC {
t.Fatal("Time should be UTC")
}
}
// Package util implements various utility functions used within ipfs
// that do not currently have a better place to live.
package util
import (
"errors"
"io"
"math/rand"
"os"
"path/filepath"
"runtime/debug"
"strings"
"time"
b58 "gx/QmNsoHoCVhgXcv1Yg45jtkMgimxorTAN36fV9AQMFXHHAQ/go-base58"
mh "gx/Qma7dqy7ZVH4tkNJdC9TRrA82Uz5fQfbbwuvmNVVc17r7a/go-multihash"
)
// Debug is a global flag for debugging.
var Debug bool
// ErrNotImplemented signifies a function has not been implemented yet.
var ErrNotImplemented = errors.New("Error: not implemented yet.")
// ErrTimeout implies that a timeout has been triggered
var ErrTimeout = errors.New("Error: Call timed out.")
// ErrSeErrSearchIncomplete implies that a search type operation didnt
// find the expected node, but did find 'a' node.
var ErrSearchIncomplete = errors.New("Error: Search Incomplete.")
// ErrCast is returned when a cast fails AND the program should not panic.
func ErrCast() error {
debug.PrintStack()
return errCast
}
var errCast = errors.New("cast error")
// ExpandPathnames takes a set of paths and turns them into absolute paths
func ExpandPathnames(paths []string) ([]string, error) {
var out []string
for _, p := range paths {
abspath, err := filepath.Abs(p)
if err != nil {
return nil, err
}
out = append(out, abspath)
}
return out, nil
}
type randGen struct {
rand.Rand
}
func NewTimeSeededRand() io.Reader {
src := rand.NewSource(time.Now().UnixNano())
return &randGen{
Rand: *rand.New(src),
}
}
func NewSeededRand(seed int64) io.Reader {
src := rand.NewSource(seed)
return &randGen{
Rand: *rand.New(src),
}
}
func (r *randGen) Read(p []byte) (n int, err error) {
for i := 0; i < len(p); i++ {
p[i] = byte(r.Rand.Intn(255))
}
return len(p), nil
}
// GetenvBool is the way to check an env var as a boolean
func GetenvBool(name string) bool {
v := strings.ToLower(os.Getenv(name))
return v == "true" || v == "t" || v == "1"
}
// MultiErr is a util to return multiple errors
type MultiErr []error
func (m MultiErr) Error() string {
if len(m) == 0 {
return "no errors"
}
s := "Multiple errors: "
for i, e := range m {
if i != 0 {
s += ", "
}
s += e.Error()
}
return s
}
func Partition(subject string, sep string) (string, string, string) {
if i := strings.Index(subject, sep); i != -1 {
return subject[:i], subject[i : i+len(sep)], subject[i+len(sep):]
}
return subject, "", ""
}
func RPartition(subject string, sep string) (string, string, string) {
if i := strings.LastIndex(subject, sep); i != -1 {
return subject[:i], subject[i : i+len(sep)], subject[i+len(sep):]
}
return subject, "", ""
}
// Hash is the global IPFS hash function. uses multihash SHA2_256, 256 bits
func Hash(data []byte) mh.Multihash {
h, err := mh.Sum(data, mh.SHA2_256, -1)
if err != nil {
// this error can be safely ignored (panic) because multihash only fails
// from the selection of hash function. If the fn + length are valid, it
// won't error.
panic("multihash failed to hash using SHA2_256.")
}
return h
}
// IsValidHash checks whether a given hash is valid (b58 decodable, len > 0)
func IsValidHash(s string) bool {
out := b58.Decode(s)
if out == nil || len(out) == 0 {
return false
}
_, err := mh.Cast(out)
if err != nil {
return false
}
return true
}
// XOR takes two byte slices, XORs them together, returns the resulting slice.
func XOR(a, b []byte) []byte {
c := make([]byte, len(a))
for i := 0; i < len(a); i++ {
c[i] = a[i] ^ b[i]
}
return c
}
package util
import (
"bytes"
"testing"
)
func TestXOR(t *testing.T) {
cases := [][3][]byte{
{
{0xFF, 0xFF, 0xFF},
{0xFF, 0xFF, 0xFF},
{0x00, 0x00, 0x00},
},
{
{0x00, 0xFF, 0x00},
{0xFF, 0xFF, 0xFF},
{0xFF, 0x00, 0xFF},
},
{
{0x55, 0x55, 0x55},
{0x55, 0xFF, 0xAA},
{0x00, 0xAA, 0xFF},
},
}
for _, c := range cases {
r := XOR(c[0], c[1])
if !bytes.Equal(r, c[2]) {
t.Error("XOR failed")
}
}
}
func BenchmarkHash256K(b *testing.B) {
buf := make([]byte, 256*1024)
NewTimeSeededRand().Read(buf)
b.SetBytes(int64(256 * 1024))
b.ResetTimer()
for i := 0; i < b.N; i++ {
Hash(buf)
}
}
func BenchmarkHash512K(b *testing.B) {
buf := make([]byte, 512*1024)
NewTimeSeededRand().Read(buf)
b.SetBytes(int64(512 * 1024))
b.ResetTimer()
for i := 0; i < b.N; i++ {
Hash(buf)
}
}
func BenchmarkHash1M(b *testing.B) {
buf := make([]byte, 1024*1024)
NewTimeSeededRand().Read(buf)
b.SetBytes(int64(1024 * 1024))
b.ResetTimer()
for i := 0; i < b.N; i++ {
Hash(buf)
}
}
The MIT License (MIT)
Copyright (c) 2014 Juan Batiz-Benet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
# go-detect-race
Check if the race detector is running.
I didnt find a variable to check quickly enough so I made this.
## Usage
```go
import (
detectrace "github.com/jbenet/go-detect-race"
)
func main() {
if detectrace.WithRace() {
// running with -race
} else {
// running without -race
}
}
```
## Why?
Because the race detector doesnt like massive stress tests. Example:
https://groups.google.com/forum/#!topic/golang-nuts/XDPHUt2LE70
## Why didn't you just use...
Please tell me about a better way of doing this. It wasn't
readily apparent to me, so I made this. But i would much prefer
an env var or some already existing var from the stdlib :)
{
"name": "go-detect-race",
"author": "whyrusleeping",
"version": "0.0.0",
"language": "go",
"issues_url": "",
"gx": {
"dvcsimport": "github.com/jbenet/go-detect-race"
}
}
\ No newline at end of file
package detectrace
// WithRace returns whether the binary was compiled
// with the race flag on.
func WithRace() bool {
return withRace
}
package detectrace
import (
"testing"
)
func TestWithRace(t *testing.T) {
t.Logf("WithRace() is %v\n", WithRace())
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment