pax_global_header00006660000000000000000000000064127255566430014531gustar00rootroot0000000000000052 comment=879c5887cd475cd7864858769793b2ceb0d44feb go.uuid-1.1.0/000077500000000000000000000000001272555664300131025ustar00rootroot00000000000000go.uuid-1.1.0/.travis.yml000066400000000000000000000004151272555664300152130ustar00rootroot00000000000000language: go sudo: false go: - 1.2 - 1.3 - 1.4 - 1.5 - 1.6 before_install: - go get github.com/mattn/goveralls - go get golang.org/x/tools/cmd/cover script: - $HOME/gopath/bin/goveralls -service=travis-ci notifications: email: false go.uuid-1.1.0/LICENSE000066400000000000000000000020721272555664300141100ustar00rootroot00000000000000Copyright (C) 2013-2016 by Maxim Bublis 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.uuid-1.1.0/README.md000066400000000000000000000035351272555664300143670ustar00rootroot00000000000000# UUID package for Go language [![Build Status](https://travis-ci.org/satori/go.uuid.png?branch=master)](https://travis-ci.org/satori/go.uuid) [![Coverage Status](https://coveralls.io/repos/github/satori/go.uuid/badge.svg?branch=master)](https://coveralls.io/github/satori/go.uuid) [![GoDoc](http://godoc.org/github.com/satori/go.uuid?status.png)](http://godoc.org/github.com/satori/go.uuid) This package provides pure Go implementation of Universally Unique Identifier (UUID). Supported both creation and parsing of UUIDs. With 100% test coverage and benchmarks out of box. Supported versions: * Version 1, based on timestamp and MAC address (RFC 4122) * Version 2, based on timestamp, MAC address and POSIX UID/GID (DCE 1.1) * Version 3, based on MD5 hashing (RFC 4122) * Version 4, based on random numbers (RFC 4122) * Version 5, based on SHA-1 hashing (RFC 4122) ## Installation Use the `go` command: $ go get github.com/satori/go.uuid ## Requirements UUID package requires Go >= 1.2. ## Example ```go package main import ( "fmt" "github.com/satori/go.uuid" ) func main() { // Creating UUID Version 4 u1 := uuid.NewV4() fmt.Printf("UUIDv4: %s\n", u1) // Parsing UUID from string input u2, err := uuid.FromString("6ba7b810-9dad-11d1-80b4-00c04fd430c8") if err != nil { fmt.Printf("Something gone wrong: %s", err) } fmt.Printf("Successfully parsed: %s", u2) } ``` ## Documentation [Documentation](http://godoc.org/github.com/satori/go.uuid) is hosted at GoDoc project. ## Links * [RFC 4122](http://tools.ietf.org/html/rfc4122) * [DCE 1.1: Authentication and Security Services](http://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01) ## Copyright Copyright (C) 2013-2016 by Maxim Bublis . UUID package released under MIT License. See [LICENSE](https://github.com/satori/go.uuid/blob/master/LICENSE) for details. go.uuid-1.1.0/benchmarks_test.go000066400000000000000000000057171272555664300166170ustar00rootroot00000000000000// Copyright (C) 2013-2015 by Maxim Bublis // // 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() } } go.uuid-1.1.0/uuid.go000066400000000000000000000265511272555664300144100ustar00rootroot00000000000000// Copyright (C) 2013-2015 by Maxim Bublis // // 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 // NullUUID can be used with the standard sql package to represent a // UUID value that can be NULL in the database type NullUUID struct { UUID UUID Valid bool } // 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: UUID string too short: %s", text) return } t := text[:] braced := false if bytes.Equal(t[:9], urnPrefix) { t = t[9:] } else if t[0] == '{' { braced = true t = t[1:] } b := u[:] for i, byteGroup := range byteGroups { if i > 0 && t[0] == '-' { t = t[1:] } else if i > 0 && t[0] != '-' { err = fmt.Errorf("uuid: invalid string format") return } if i == 2 { if !bytes.Contains([]byte("012345"), []byte{t[0]}) { err = fmt.Errorf("uuid: invalid version number: %s", t[0]) return } } if len(t) < byteGroup { err = fmt.Errorf("uuid: UUID string too short: %s", text) return } if i == 4 && len(t) > byteGroup && ((braced && t[byteGroup] != '}') || len(t[byteGroup:]) > 1 || !braced) { err = fmt.Errorf("uuid: UUID string too long: %s", t) return } _, err = hex.Decode(b[:byteGroup/2], t[:byteGroup]) if err != nil { return } t = t[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) } // Value implements the driver.Valuer interface. func (u NullUUID) Value() (driver.Value, error) { if !u.Valid { return nil, nil } // Delegate to UUID Value function return u.UUID.Value() } // Scan implements the sql.Scanner interface. func (u *NullUUID) Scan(src interface{}) error { if src == nil { u.UUID, u.Valid = Nil, false return nil } // Delegate to UUID Scan function u.Valid = true return u.UUID.Scan(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 } go.uuid-1.1.0/uuid_test.go000066400000000000000000000411661272555664300154460ustar00rootroot00000000000000// Copyright (C) 2013, 2015 by Maxim Bublis // // 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 TestFromStringShort(t *testing.T) { // Invalid 35-character UUID string s1 := "6ba7b810-9dad-11d1-80b4-00c04fd430c" for i := len(s1); i >= 0; i-- { _, err := FromString(s1[:i]) if err == nil { t.Errorf("Should return error trying to parse too short string, got %s", err) } } } func TestFromStringLong(t *testing.T) { // Invalid 37+ character UUID string s := []string{ "6ba7b810-9dad-11d1-80b4-00c04fd430c8=", "6ba7b810-9dad-11d1-80b4-00c04fd430c8}", "{6ba7b810-9dad-11d1-80b4-00c04fd430c8}f", "6ba7b810-9dad-11d1-80b4-00c04fd430c800c04fd430c8", } for _, str := range s { _, err := FromString(str) if err == nil { t.Errorf("Should return error trying to parse too long string, passed %s", str) } } } func TestFromStringInvalid(t *testing.T) { // Invalid UUID string formats s := []string{ "6ba7b8109dad11d180b400c04fd430c8", "6ba7b8109dad11d180b400c04fd430c86ba7b8109dad11d180b400c04fd430c8", "urn:uuid:{6ba7b810-9dad-11d1-80b4-00c04fd430c8}", "6ba7b8109-dad-11d1-80b4-00c04fd430c8", "6ba7b810-9dad1-1d1-80b4-00c04fd430c8", "6ba7b810-9dad-11d18-0b4-00c04fd430c8", "6ba7b810-9dad-11d1-80b40-0c04fd430c8", "6ba7b810+9dad+11d1+80b4+00c04fd430c8", "6ba7b810-9dad11d180b400c04fd430c8", "6ba7b8109dad-11d180b400c04fd430c8", "6ba7b8109dad11d1-80b400c04fd430c8", "6ba7b8109dad11d180b4-00c04fd430c8", } for _, str := range s { _, err := FromString(str) if err == nil { t.Errorf("Should return error trying to parse invalid string, passed %s", str) } } } 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 TestValueNil(t *testing.T) { u := UUID{} val, err := u.Value() if err != nil { t.Errorf("Error getting UUID value: %s", err) } if val != Nil.String() { t.Errorf("Wrong value returned, should be equal to UUID.Nil: %s", val) } } func TestNullUUIDValueNil(t *testing.T) { u := NullUUID{} val, err := u.Value() if err != nil { t.Errorf("Error getting UUID value: %s", err) } if val != nil { t.Errorf("Wrong value returned, should be nil: %s", val) } } 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 TestScanNil(t *testing.T) { u := UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8} err := u.Scan(nil) if err == nil { t.Errorf("Error UUID shouldn't allow unmarshalling from nil") } } func TestNullUUIDScanValid(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 := NullUUID{} err := u1.Scan(s1) if err != nil { t.Errorf("Error unmarshaling NullUUID: %s", err) } if !u1.Valid { t.Errorf("NullUUID should be valid") } if !Equal(u, u1.UUID) { t.Errorf("UUIDs should be equal: %s and %s", u, u1.UUID) } } func TestNullUUIDScanNil(t *testing.T) { u := NullUUID{UUID{0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8}, true} err := u.Scan(nil) if err != nil { t.Errorf("Error unmarshaling NullUUID: %s", err) } if u.Valid { t.Errorf("NullUUID should not be valid") } if !Equal(u.UUID, Nil) { t.Errorf("NullUUID value should be equal to Nil: %s", u) } } 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) } }