forked from mirror/go.uuid
Moved all generation related logic into `generator.go`.
Abstracted behind `Generator` interface for easy mocking in tests.
This commit is contained in:
parent
508dbd67f2
commit
b86a6b7dda
|
@ -0,0 +1,239 @@
|
|||
// Copyright (C) 2013-2018 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 (
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Difference in 100-nanosecond intervals between
|
||||
// UUID epoch (October 15, 1582) and Unix epoch (January 1, 1970).
|
||||
const epochStart = 122192928000000000
|
||||
|
||||
var (
|
||||
global = newDefaultGenerator()
|
||||
|
||||
epochFunc = unixTimeFunc
|
||||
posixUID = uint32(os.Getuid())
|
||||
posixGID = uint32(os.Getgid())
|
||||
)
|
||||
|
||||
// NewV1 returns UUID based on current timestamp and MAC address.
|
||||
func NewV1() UUID {
|
||||
return global.NewV1()
|
||||
}
|
||||
|
||||
// NewV2 returns DCE Security UUID based on POSIX UID/GID.
|
||||
func NewV2(domain byte) UUID {
|
||||
return global.NewV2(domain)
|
||||
}
|
||||
|
||||
// NewV3 returns UUID based on MD5 hash of namespace UUID and name.
|
||||
func NewV3(ns UUID, name string) UUID {
|
||||
return global.NewV3(ns, name)
|
||||
}
|
||||
|
||||
// NewV4 returns random generated UUID.
|
||||
func NewV4() UUID {
|
||||
return global.NewV4()
|
||||
}
|
||||
|
||||
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
|
||||
func NewV5(ns UUID, name string) UUID {
|
||||
return global.NewV5(ns, name)
|
||||
}
|
||||
|
||||
// Generator provides interface for generating UUIDs.
|
||||
type Generator interface {
|
||||
NewV1() UUID
|
||||
NewV2(domain byte) UUID
|
||||
NewV3(ns UUID, name string) UUID
|
||||
NewV4() UUID
|
||||
NewV5(ns UUID, name string) UUID
|
||||
}
|
||||
|
||||
// Default generator implementation.
|
||||
type generator struct {
|
||||
storageOnce sync.Once
|
||||
storageMutex sync.Mutex
|
||||
|
||||
lastTime uint64
|
||||
clockSequence uint16
|
||||
hardwareAddr [6]byte
|
||||
}
|
||||
|
||||
func newDefaultGenerator() Generator {
|
||||
return &generator{}
|
||||
}
|
||||
|
||||
// NewV1 returns UUID based on current timestamp and MAC address.
|
||||
func (g *generator) NewV1() UUID {
|
||||
u := UUID{}
|
||||
|
||||
timeNow, clockSeq, hardwareAddr := g.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 (g *generator) NewV2(domain byte) UUID {
|
||||
u := UUID{}
|
||||
|
||||
timeNow, clockSeq, hardwareAddr := g.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 (g *generator) 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 (g *generator) NewV4() UUID {
|
||||
u := UUID{}
|
||||
g.safeRandom(u[:])
|
||||
u.SetVersion(4)
|
||||
u.SetVariant()
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
// NewV5 returns UUID based on SHA-1 hash of namespace UUID and name.
|
||||
func (g *generator) NewV5(ns UUID, name string) UUID {
|
||||
u := newFromHash(sha1.New(), ns, name)
|
||||
u.SetVersion(5)
|
||||
u.SetVariant()
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
func (g *generator) initStorage() {
|
||||
g.initClockSequence()
|
||||
g.initHardwareAddr()
|
||||
}
|
||||
|
||||
func (g *generator) initClockSequence() {
|
||||
buf := make([]byte, 2)
|
||||
g.safeRandom(buf)
|
||||
g.clockSequence = binary.BigEndian.Uint16(buf)
|
||||
}
|
||||
|
||||
func (g *generator) initHardwareAddr() {
|
||||
interfaces, err := net.Interfaces()
|
||||
if err == nil {
|
||||
for _, iface := range interfaces {
|
||||
if len(iface.HardwareAddr) >= 6 {
|
||||
copy(g.hardwareAddr[:], iface.HardwareAddr)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize hardwareAddr randomly in case
|
||||
// of real network interfaces absence
|
||||
g.safeRandom(g.hardwareAddr[:])
|
||||
|
||||
// Set multicast bit as recommended in RFC 4122
|
||||
g.hardwareAddr[0] |= 0x01
|
||||
}
|
||||
|
||||
func (g *generator) safeRandom(dest []byte) {
|
||||
if _, err := rand.Read(dest); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Returns UUID v1/v2 storage state.
|
||||
// Returns epoch timestamp, clock sequence, and hardware address.
|
||||
func (g *generator) getStorage() (uint64, uint16, []byte) {
|
||||
g.storageOnce.Do(g.initStorage)
|
||||
|
||||
g.storageMutex.Lock()
|
||||
defer g.storageMutex.Unlock()
|
||||
|
||||
timeNow := epochFunc()
|
||||
// Clock changed backwards since last UUID generation.
|
||||
// Should increase clock sequence.
|
||||
if timeNow <= g.lastTime {
|
||||
g.clockSequence++
|
||||
}
|
||||
g.lastTime = timeNow
|
||||
|
||||
return timeNow, g.clockSequence, g.hardwareAddr[:]
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
package uuid
|
||||
|
||||
import "testing"
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
174
uuid.go
174
uuid.go
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2013-2015 by Maxim Bublis <b@codemonkey.ru>
|
||||
// Copyright (C) 2013-2018 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
|
||||
|
@ -26,18 +26,9 @@ package uuid
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"database/sql/driver"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"hash"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Size of a UUID in bytes.
|
||||
|
@ -58,74 +49,15 @@ const (
|
|||
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 [Size]byte
|
||||
|
@ -137,7 +69,7 @@ type NullUUID struct {
|
|||
Valid bool
|
||||
}
|
||||
|
||||
// The nil UUID is special form of UUID that is specified to have all
|
||||
// Nil is special form of UUID that is specified to have all
|
||||
// 128 bits set to zero.
|
||||
var Nil = UUID{}
|
||||
|
||||
|
@ -427,108 +359,6 @@ func FromStringOrNil(input string) UUID {
|
|||
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
|
||||
}
|
||||
|
||||
// Must is a helper that wraps a call to a function returning (UUID, error)
|
||||
// and panics if the error is non-nil. It is intended for use in variable
|
||||
// initializations such as
|
||||
|
|
137
uuid_test.go
137
uuid_test.go
|
@ -496,140 +496,3 @@ func TestNullUUIDScanNil(t *testing.T) {
|
|||
t.Errorf("NullUUID value should be equal to Nil: %v", 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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue