git.sr.ht/~pingoo/stdx@v0.0.0-20240218134121-094174641f6e/uuid/uuid_test.go (about)

     1  // Copyright 2016 Google Inc.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package uuid
     6  
     7  import (
     8  	"bytes"
     9  	"errors"
    10  	"fmt"
    11  	"os"
    12  	"runtime"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  	"unsafe"
    17  )
    18  
    19  type test struct {
    20  	in      string
    21  	version Version
    22  	variant Variant
    23  	isuuid  bool
    24  }
    25  
    26  var tests = []test{
    27  	{"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true},
    28  	{"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true},
    29  	{"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true},
    30  	{"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true},
    31  	{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
    32  	{"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true},
    33  	{"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true},
    34  	{"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true},
    35  	{"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true},
    36  	{"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true},
    37  	{"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true},
    38  	{"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true},
    39  	{"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true},
    40  	{"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true},
    41  	{"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true},
    42  	{"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true},
    43  
    44  	{"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
    45  	{"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
    46  	{"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
    47  	{"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true},
    48  	{"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true},
    49  	{"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true},
    50  	{"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true},
    51  	{"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true},
    52  	{"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true},
    53  	{"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true},
    54  	{"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
    55  	{"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true},
    56  	{"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true},
    57  	{"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true},
    58  	{"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true},
    59  	{"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true},
    60  	{"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true},
    61  	{"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true},
    62  
    63  	{"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false},
    64  	{"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false},
    65  	{"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false},
    66  	{"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false},
    67  	{"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false},
    68  	{"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false},
    69  
    70  	{"{f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, RFC4122, true},
    71  	{"{f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, Invalid, false},
    72  	{"f47ac10b-58cc-0372-8567-0e02b2c3d479}", 0, Invalid, false},
    73  
    74  	{"f47ac10b58cc037285670e02b2c3d479", 0, RFC4122, true},
    75  	{"f47ac10b58cc037285670e02b2c3d4790", 0, Invalid, false},
    76  	{"f47ac10b58cc037285670e02b2c3d47", 0, Invalid, false},
    77  
    78  	{"01ee836c-e7c9-619d-929a-525400475911", 6, RFC4122, true},
    79  	{"018bd12c-58b0-7683-8a5b-8752d0e86651", 7, RFC4122, true},
    80  }
    81  
    82  var constants = []struct {
    83  	c    interface{}
    84  	name string
    85  }{
    86  	{Person, "Person"},
    87  	{Group, "Group"},
    88  	{Org, "Org"},
    89  	{Invalid, "Invalid"},
    90  	{RFC4122, "RFC4122"},
    91  	{Reserved, "Reserved"},
    92  	{Microsoft, "Microsoft"},
    93  	{Future, "Future"},
    94  	{Domain(17), "Domain17"},
    95  	{Variant(42), "BadVariant42"},
    96  }
    97  
    98  func testTest(t *testing.T, in string, tt test) {
    99  	uuid, err := Parse(in)
   100  	if ok := (err == nil); ok != tt.isuuid {
   101  		t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid)
   102  	}
   103  	if err != nil {
   104  		return
   105  	}
   106  
   107  	if v := uuid.Variant(); v != tt.variant {
   108  		t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant)
   109  	}
   110  	if v := uuid.Version(); v != tt.version {
   111  		t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version)
   112  	}
   113  }
   114  
   115  func testBytes(t *testing.T, in []byte, tt test) {
   116  	uuid, err := ParseBytes(in)
   117  	if ok := (err == nil); ok != tt.isuuid {
   118  		t.Errorf("ParseBytes(%s) got %v expected %v\b", in, ok, tt.isuuid)
   119  	}
   120  	if err != nil {
   121  		return
   122  	}
   123  	suuid, _ := Parse(string(in))
   124  	if uuid != suuid {
   125  		t.Errorf("ParseBytes(%s) got %v expected %v\b", in, uuid, suuid)
   126  	}
   127  }
   128  
   129  func TestUUID(t *testing.T) {
   130  	for _, tt := range tests {
   131  		testTest(t, tt.in, tt)
   132  		testTest(t, strings.ToUpper(tt.in), tt)
   133  		testBytes(t, []byte(tt.in), tt)
   134  	}
   135  }
   136  
   137  func TestFromBytes(t *testing.T) {
   138  	b := []byte{
   139  		0x7d, 0x44, 0x48, 0x40,
   140  		0x9d, 0xc0,
   141  		0x11, 0xd1,
   142  		0xb2, 0x45,
   143  		0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
   144  	}
   145  	uuid, err := FromBytes(b)
   146  	if err != nil {
   147  		t.Fatalf("%s", err)
   148  	}
   149  	for i := 0; i < len(uuid); i++ {
   150  		if b[i] != uuid[i] {
   151  			t.Fatalf("FromBytes() got %v expected %v\b", uuid[:], b)
   152  		}
   153  	}
   154  }
   155  
   156  func TestConstants(t *testing.T) {
   157  	for x, tt := range constants {
   158  		v, ok := tt.c.(fmt.Stringer)
   159  		if !ok {
   160  			t.Errorf("%x: %v: not a stringer", x, v)
   161  		} else if s := v.String(); s != tt.name {
   162  			v, _ := tt.c.(int)
   163  			t.Errorf("%x: Constant %T:%d gives %q, expected %q", x, tt.c, v, s, tt.name)
   164  		}
   165  	}
   166  }
   167  
   168  func TestRandomUUID(t *testing.T) {
   169  	m := make(map[string]bool)
   170  	for x := 1; x < 32; x++ {
   171  		uuid := NewV4()
   172  		s := uuid.String()
   173  		if m[s] {
   174  			t.Errorf("NewRandom returned duplicated UUID %s", s)
   175  		}
   176  		m[s] = true
   177  		if v := uuid.Version(); v != 4 {
   178  			t.Errorf("Random UUID of version %s", v)
   179  		}
   180  		if uuid.Variant() != RFC4122 {
   181  			t.Errorf("Random UUID is variant %d", uuid.Variant())
   182  		}
   183  	}
   184  }
   185  
   186  func TestRandomUUID_Pooled(t *testing.T) {
   187  	defer DisableRandPool()
   188  	EnableRandPool()
   189  	m := make(map[string]bool)
   190  	for x := 1; x < 128; x++ {
   191  		uuid := NewV4()
   192  		s := uuid.String()
   193  		if m[s] {
   194  			t.Errorf("NewRandom returned duplicated UUID %s", s)
   195  		}
   196  		m[s] = true
   197  		if v := uuid.Version(); v != 4 {
   198  			t.Errorf("Random UUID of version %s", v)
   199  		}
   200  		if uuid.Variant() != RFC4122 {
   201  			t.Errorf("Random UUID is variant %d", uuid.Variant())
   202  		}
   203  	}
   204  }
   205  
   206  func TestNewV4(t *testing.T) {
   207  	m := make(map[UUID]bool)
   208  	for x := 1; x < 32; x++ {
   209  		s := NewV4()
   210  		if m[s] {
   211  			t.Errorf("New returned duplicated UUID %s", s)
   212  		}
   213  		m[s] = true
   214  		uuid, err := Parse(s.String())
   215  		if err != nil {
   216  			t.Errorf("New.String() returned %q which does not decode", s)
   217  			continue
   218  		}
   219  		if v := uuid.Version(); v != 4 {
   220  			t.Errorf("Random UUID of version %s", v)
   221  		}
   222  		if uuid.Variant() != RFC4122 {
   223  			t.Errorf("Random UUID is variant %d", uuid.Variant())
   224  		}
   225  	}
   226  }
   227  
   228  func TestClockSeq(t *testing.T) {
   229  	// Fake time.Now for this test to return a monotonically advancing time; restore it at end.
   230  	defer func(orig func() time.Time) { timeNow = orig }(timeNow)
   231  	monTime := time.Now()
   232  	timeNow = func() time.Time {
   233  		monTime = monTime.Add(1 * time.Second)
   234  		return monTime
   235  	}
   236  
   237  	SetClockSequence(-1)
   238  	uuid1, err := NewUUID()
   239  	if err != nil {
   240  		t.Fatalf("could not create UUID: %v", err)
   241  	}
   242  	uuid2, err := NewUUID()
   243  	if err != nil {
   244  		t.Fatalf("could not create UUID: %v", err)
   245  	}
   246  
   247  	if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 != s2 {
   248  		t.Errorf("clock sequence %d != %d", s1, s2)
   249  	}
   250  
   251  	SetClockSequence(-1)
   252  	uuid2, err = NewUUID()
   253  	if err != nil {
   254  		t.Fatalf("could not create UUID: %v", err)
   255  	}
   256  
   257  	// Just on the very off chance we generated the same sequence
   258  	// two times we try again.
   259  	if uuid1.ClockSequence() == uuid2.ClockSequence() {
   260  		SetClockSequence(-1)
   261  		uuid2, err = NewUUID()
   262  		if err != nil {
   263  			t.Fatalf("could not create UUID: %v", err)
   264  		}
   265  	}
   266  	if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 == s2 {
   267  		t.Errorf("Duplicate clock sequence %d", s1)
   268  	}
   269  
   270  	SetClockSequence(0x1234)
   271  	uuid1, err = NewUUID()
   272  	if err != nil {
   273  		t.Fatalf("could not create UUID: %v", err)
   274  	}
   275  	if seq := uuid1.ClockSequence(); seq != 0x1234 {
   276  		t.Errorf("%s: expected seq 0x1234 got 0x%04x", uuid1, seq)
   277  	}
   278  }
   279  
   280  func TestCoding(t *testing.T) {
   281  	text := "7d444840-9dc0-11d1-b245-5ffdce74fad2"
   282  	urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2"
   283  	data := UUID{
   284  		0x7d, 0x44, 0x48, 0x40,
   285  		0x9d, 0xc0,
   286  		0x11, 0xd1,
   287  		0xb2, 0x45,
   288  		0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
   289  	}
   290  	if v := data.String(); v != text {
   291  		t.Errorf("%x: encoded to %s, expected %s", data, v, text)
   292  	}
   293  	if v := data.URN(); v != urn {
   294  		t.Errorf("%x: urn is %s, expected %s", data, v, urn)
   295  	}
   296  
   297  	uuid, err := Parse(text)
   298  	if err != nil {
   299  		t.Errorf("Parse returned unexpected error %v", err)
   300  	}
   301  	if data != uuid {
   302  		t.Errorf("%s: decoded to %s, expected %s", text, uuid, data)
   303  	}
   304  }
   305  
   306  func TestVersion1(t *testing.T) {
   307  	uuid1, err := NewUUID()
   308  	if err != nil {
   309  		t.Fatalf("could not create UUID: %v", err)
   310  	}
   311  	uuid2, err := NewUUID()
   312  	if err != nil {
   313  		t.Fatalf("could not create UUID: %v", err)
   314  	}
   315  
   316  	if uuid1 == uuid2 {
   317  		t.Errorf("%s:duplicate uuid", uuid1)
   318  	}
   319  	if v := uuid1.Version(); v != 1 {
   320  		t.Errorf("%s: version %s expected 1", uuid1, v)
   321  	}
   322  	if v := uuid2.Version(); v != 1 {
   323  		t.Errorf("%s: version %s expected 1", uuid2, v)
   324  	}
   325  	n1 := uuid1.NodeID()
   326  	n2 := uuid2.NodeID()
   327  	if !bytes.Equal(n1, n2) {
   328  		t.Errorf("Different nodes %x != %x", n1, n2)
   329  	}
   330  	t1 := uuid1.Time()
   331  	t2 := uuid2.Time()
   332  	q1 := uuid1.ClockSequence()
   333  	q2 := uuid2.ClockSequence()
   334  
   335  	switch {
   336  	case t1 == t2 && q1 == q2:
   337  		t.Error("time stopped")
   338  	case t1 > t2 && q1 == q2:
   339  		t.Error("time reversed")
   340  	case t1 < t2 && q1 != q2:
   341  		t.Error("clock sequence changed unexpectedly")
   342  	}
   343  }
   344  
   345  func TestNode(t *testing.T) {
   346  	// This test is mostly to make sure we don't leave nodeMu locked.
   347  	ifname = ""
   348  	if ni := NodeInterface(); ni != "" {
   349  		t.Errorf("NodeInterface got %q, want %q", ni, "")
   350  	}
   351  	if SetNodeInterface("xyzzy") {
   352  		t.Error("SetNodeInterface succeeded on a bad interface name")
   353  	}
   354  	if !SetNodeInterface("") {
   355  		t.Error("SetNodeInterface failed")
   356  	}
   357  	if runtime.GOARCH != "js" {
   358  		if ni := NodeInterface(); ni == "" {
   359  			t.Error("NodeInterface returned an empty string")
   360  		}
   361  	}
   362  
   363  	ni := NodeID()
   364  	if len(ni) != 6 {
   365  		t.Errorf("ni got %d bytes, want 6", len(ni))
   366  	}
   367  	hasData := false
   368  	for _, b := range ni {
   369  		if b != 0 {
   370  			hasData = true
   371  		}
   372  	}
   373  	if !hasData {
   374  		t.Error("nodeid is all zeros")
   375  	}
   376  
   377  	id := []byte{1, 2, 3, 4, 5, 6, 7, 8}
   378  	SetNodeID(id)
   379  	ni = NodeID()
   380  	if !bytes.Equal(ni, id[:6]) {
   381  		t.Errorf("got nodeid %v, want %v", ni, id[:6])
   382  	}
   383  
   384  	if ni := NodeInterface(); ni != "user" {
   385  		t.Errorf("got interface %q, want %q", ni, "user")
   386  	}
   387  }
   388  
   389  func TestNodeAndTime(t *testing.T) {
   390  	// Time is February 5, 1998 12:30:23.136364800 AM GMT
   391  
   392  	uuid, err := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2")
   393  	if err != nil {
   394  		t.Fatalf("Parser returned unexpected error %v", err)
   395  	}
   396  	node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2}
   397  
   398  	ts := uuid.Time()
   399  	c := time.Unix(ts.UnixTime())
   400  	want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC)
   401  	if !c.Equal(want) {
   402  		t.Errorf("Got time %v, want %v", c, want)
   403  	}
   404  	if !bytes.Equal(node, uuid.NodeID()) {
   405  		t.Errorf("Expected node %v got %v", node, uuid.NodeID())
   406  	}
   407  }
   408  
   409  func TestMD5(t *testing.T) {
   410  	uuid := NewMD5(NameSpaceDNS, []byte("python.org")).String()
   411  	want := "6fa459ea-ee8a-3ca4-894e-db77e160355e"
   412  	if uuid != want {
   413  		t.Errorf("MD5: got %q expected %q", uuid, want)
   414  	}
   415  }
   416  
   417  func TestSHA1(t *testing.T) {
   418  	uuid := NewSHA1(NameSpaceDNS, []byte("python.org")).String()
   419  	want := "886313e1-3b8a-5372-9b90-0c9aee199e5d"
   420  	if uuid != want {
   421  		t.Errorf("SHA1: got %q expected %q", uuid, want)
   422  	}
   423  }
   424  
   425  func TestNodeID(t *testing.T) {
   426  	nid := []byte{1, 2, 3, 4, 5, 6}
   427  	SetNodeInterface("")
   428  	s := NodeInterface()
   429  	if runtime.GOARCH != "js" {
   430  		if s == "" || s == "user" {
   431  			t.Errorf("NodeInterface %q after SetInterface", s)
   432  		}
   433  	}
   434  	node1 := NodeID()
   435  	if node1 == nil {
   436  		t.Error("NodeID nil after SetNodeInterface", s)
   437  	}
   438  	SetNodeID(nid)
   439  	s = NodeInterface()
   440  	if s != "user" {
   441  		t.Errorf("Expected NodeInterface %q got %q", "user", s)
   442  	}
   443  	node2 := NodeID()
   444  	if node2 == nil {
   445  		t.Error("NodeID nil after SetNodeID", s)
   446  	}
   447  	if bytes.Equal(node1, node2) {
   448  		t.Error("NodeID not changed after SetNodeID", s)
   449  	} else if !bytes.Equal(nid, node2) {
   450  		t.Errorf("NodeID is %x, expected %x", node2, nid)
   451  	}
   452  }
   453  
   454  func testDCE(t *testing.T, name string, uuid UUID, err error, domain Domain, id uint32) {
   455  	if err != nil {
   456  		t.Errorf("%s failed: %v", name, err)
   457  		return
   458  	}
   459  	if v := uuid.Version(); v != 2 {
   460  		t.Errorf("%s: %s: expected version 2, got %s", name, uuid, v)
   461  		return
   462  	}
   463  	if v := uuid.Domain(); v != domain {
   464  		t.Errorf("%s: %s: expected domain %d, got %d", name, uuid, domain, v)
   465  	}
   466  	if v := uuid.ID(); v != id {
   467  		t.Errorf("%s: %s: expected id %d, got %d", name, uuid, id, v)
   468  	}
   469  }
   470  
   471  func TestDCE(t *testing.T) {
   472  	uuid, err := NewDCESecurity(42, 12345678)
   473  	testDCE(t, "NewDCESecurity", uuid, err, 42, 12345678)
   474  	uuid, err = NewDCEPerson()
   475  	testDCE(t, "NewDCEPerson", uuid, err, Person, uint32(os.Getuid()))
   476  	uuid, err = NewDCEGroup()
   477  	testDCE(t, "NewDCEGroup", uuid, err, Group, uint32(os.Getgid()))
   478  }
   479  
   480  type badRand struct{}
   481  
   482  func (r badRand) Read(buf []byte) (int, error) {
   483  	for i := range buf {
   484  		buf[i] = byte(i)
   485  	}
   486  	return len(buf), nil
   487  }
   488  
   489  func TestBadRand(t *testing.T) {
   490  	SetRand(badRand{})
   491  	uuid1 := NewV4()
   492  	uuid2 := NewV4()
   493  	if uuid1 != uuid2 {
   494  		t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2)
   495  	}
   496  	SetRand(nil)
   497  	uuid1 = NewV4()
   498  	uuid2 = NewV4()
   499  	if uuid1 == uuid2 {
   500  		t.Errorf("unexpected duplicates, got %q", uuid1)
   501  	}
   502  }
   503  
   504  func TestSetRand(t *testing.T) {
   505  	myString := "805-9dd6-1a877cb526c678e71d38-7122-44c0-9b7c-04e7001cc78783ac3e82-47a3-4cc3-9951-13f3339d88088f5d685a-11f7-4078-ada9-de44ad2daeb7"
   506  
   507  	SetRand(strings.NewReader(myString))
   508  	uuid1 := NewV4()
   509  	uuid2 := NewV4()
   510  
   511  	SetRand(strings.NewReader(myString))
   512  	uuid3 := NewV4()
   513  	uuid4 := NewV4()
   514  
   515  	if uuid1 != uuid3 {
   516  		t.Errorf("expected duplicates, got %q and %q", uuid1, uuid3)
   517  	}
   518  	if uuid2 != uuid4 {
   519  		t.Errorf("expected duplicates, got %q and %q", uuid2, uuid4)
   520  	}
   521  }
   522  
   523  func TestRandomFromReader(t *testing.T) {
   524  	myString := "8059ddhdle77cb52"
   525  	r := bytes.NewReader([]byte(myString))
   526  	r2 := bytes.NewReader([]byte(myString))
   527  	uuid1, err := NewRandomFromReader(r)
   528  	if err != nil {
   529  		t.Errorf("failed generating UUID from a reader")
   530  	}
   531  	_, err = NewRandomFromReader(r)
   532  	if err == nil {
   533  		t.Errorf("expecting an error as reader has no more bytes. Got uuid. NewRandomFromReader may not be using the provided reader")
   534  	}
   535  	uuid3, err := NewRandomFromReader(r2)
   536  	if err != nil {
   537  		t.Errorf("failed generating UUID from a reader")
   538  	}
   539  	if uuid1 != uuid3 {
   540  		t.Errorf("expected duplicates, got %q and %q", uuid1, uuid3)
   541  	}
   542  }
   543  
   544  func TestRandPool(t *testing.T) {
   545  	myString := "8059ddhdle77cb52"
   546  	EnableRandPool()
   547  	SetRand(strings.NewReader(myString))
   548  	_, err := newRandom()
   549  	if err == nil {
   550  		t.Errorf("expecting an error as reader has no more bytes")
   551  	}
   552  	DisableRandPool()
   553  	SetRand(strings.NewReader(myString))
   554  	_, err = newRandom()
   555  	if err != nil {
   556  		t.Errorf("failed generating UUID from a reader")
   557  	}
   558  }
   559  
   560  func TestWrongLength(t *testing.T) {
   561  	_, err := Parse("12345")
   562  	if err == nil {
   563  		t.Errorf("expected ‘12345’ was invalid")
   564  	} else if err.Error() != "invalid UUID length: 5" {
   565  		t.Errorf("expected a different error message for an invalid length")
   566  	}
   567  }
   568  
   569  func TestIsWrongLength(t *testing.T) {
   570  	_, err := Parse("12345")
   571  	if !IsInvalidLengthError(err) {
   572  		t.Errorf("expected error type is invalidLengthError")
   573  	}
   574  }
   575  
   576  func FuzzParse(f *testing.F) {
   577  	for _, tt := range tests {
   578  		f.Add(tt.in)
   579  		f.Add(strings.ToUpper(tt.in))
   580  	}
   581  	f.Fuzz(func(t *testing.T, in string) {
   582  		Parse(in)
   583  	})
   584  }
   585  
   586  func FuzzParseBytes(f *testing.F) {
   587  	for _, tt := range tests {
   588  		f.Add([]byte(tt.in))
   589  	}
   590  	f.Fuzz(func(t *testing.T, in []byte) {
   591  		ParseBytes(in)
   592  	})
   593  }
   594  
   595  func FuzzFromBytes(f *testing.F) {
   596  	// Copied from TestFromBytes.
   597  	f.Add([]byte{
   598  		0x7d, 0x44, 0x48, 0x40,
   599  		0x9d, 0xc0,
   600  		0x11, 0xd1,
   601  		0xb2, 0x45,
   602  		0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
   603  	})
   604  	f.Fuzz(func(t *testing.T, in []byte) {
   605  		FromBytes(in)
   606  	})
   607  }
   608  
   609  // TestValidate checks various scenarios for the Validate function
   610  func TestValidate(t *testing.T) {
   611  	testCases := []struct {
   612  		name   string
   613  		input  string
   614  		expect error
   615  	}{
   616  		{"Valid UUID", "123e4567-e89b-12d3-a456-426655440000", nil},
   617  		{"Valid UUID with URN", "urn:uuid:123e4567-e89b-12d3-a456-426655440000", nil},
   618  		{"Valid UUID with Braces", "{123e4567-e89b-12d3-a456-426655440000}", nil},
   619  		{"Valid UUID No Hyphens", "123e4567e89b12d3a456426655440000", nil},
   620  		{"Invalid UUID", "invalid-uuid", errors.New("invalid UUID length: 12")},
   621  		{"Invalid Length", "123", fmt.Errorf("invalid UUID length: %d", len("123"))},
   622  		{"Invalid URN Prefix", "urn:test:123e4567-e89b-12d3-a456-426655440000", fmt.Errorf("invalid urn prefix: %q", "urn:test:")},
   623  		{"Invalid Brackets", "[123e4567-e89b-12d3-a456-426655440000]", fmt.Errorf("invalid bracketed UUID format")},
   624  		{"Invalid UUID Format", "12345678gabc1234abcd1234abcd1234", fmt.Errorf("invalid UUID format")},
   625  	}
   626  
   627  	for _, tc := range testCases {
   628  		t.Run(tc.name, func(t *testing.T) {
   629  			err := Validate(tc.input)
   630  			if (err != nil) != (tc.expect != nil) || (err != nil && err.Error() != tc.expect.Error()) {
   631  				t.Errorf("Validate(%q) = %v, want %v", tc.input, err, tc.expect)
   632  			}
   633  		})
   634  	}
   635  }
   636  
   637  var asString = "f47ac10b-58cc-0372-8567-0e02b2c3d479"
   638  var asBytes = []byte(asString)
   639  
   640  func BenchmarkParse(b *testing.B) {
   641  	for i := 0; i < b.N; i++ {
   642  		_, err := Parse(asString)
   643  		if err != nil {
   644  			b.Fatal(err)
   645  		}
   646  	}
   647  }
   648  
   649  func BenchmarkParseBytes(b *testing.B) {
   650  	for i := 0; i < b.N; i++ {
   651  		_, err := ParseBytes(asBytes)
   652  		if err != nil {
   653  			b.Fatal(err)
   654  		}
   655  	}
   656  }
   657  
   658  // parseBytesUnsafe is to benchmark using unsafe.
   659  func parseBytesUnsafe(b []byte) (UUID, error) {
   660  	return Parse(*(*string)(unsafe.Pointer(&b)))
   661  }
   662  
   663  func BenchmarkParseBytesUnsafe(b *testing.B) {
   664  	for i := 0; i < b.N; i++ {
   665  		_, err := parseBytesUnsafe(asBytes)
   666  		if err != nil {
   667  			b.Fatal(err)
   668  		}
   669  	}
   670  }
   671  
   672  // parseBytesCopy is to benchmark not using unsafe.
   673  func parseBytesCopy(b []byte) (UUID, error) {
   674  	return Parse(string(b))
   675  }
   676  
   677  func BenchmarkParseBytesCopy(b *testing.B) {
   678  	for i := 0; i < b.N; i++ {
   679  		_, err := parseBytesCopy(asBytes)
   680  		if err != nil {
   681  			b.Fatal(err)
   682  		}
   683  	}
   684  }
   685  
   686  func BenchmarkNew(b *testing.B) {
   687  	for i := 0; i < b.N; i++ {
   688  		NewV4()
   689  	}
   690  }
   691  
   692  func BenchmarkUUID_String(b *testing.B) {
   693  	uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
   694  	if err != nil {
   695  		b.Fatal(err)
   696  	}
   697  	for i := 0; i < b.N; i++ {
   698  		if uuid.String() == "" {
   699  			b.Fatal("invalid uuid")
   700  		}
   701  	}
   702  }
   703  
   704  func BenchmarkUUID_URN(b *testing.B) {
   705  	uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
   706  	if err != nil {
   707  		b.Fatal(err)
   708  	}
   709  	for i := 0; i < b.N; i++ {
   710  		if uuid.URN() == "" {
   711  			b.Fatal("invalid uuid")
   712  		}
   713  	}
   714  }
   715  
   716  func BenchmarkParseBadLength(b *testing.B) {
   717  	short := asString[:10]
   718  	for i := 0; i < b.N; i++ {
   719  		_, err := Parse(short)
   720  		if err == nil {
   721  			b.Fatalf("expected ‘%s’ was invalid", short)
   722  		}
   723  	}
   724  }
   725  
   726  func BenchmarkParseLen32Truncated(b *testing.B) {
   727  	partial := asString[:len(asString)-4]
   728  	for i := 0; i < b.N; i++ {
   729  		_, err := Parse(partial)
   730  		if err == nil {
   731  			b.Fatalf("expected ‘%s’ was invalid", partial)
   732  		}
   733  	}
   734  }
   735  
   736  func BenchmarkParseLen36Corrupted(b *testing.B) {
   737  	wrong := asString[:len(asString)-1] + "x"
   738  	for i := 0; i < b.N; i++ {
   739  		_, err := Parse(wrong)
   740  		if err == nil {
   741  			b.Fatalf("expected ‘%s’ was invalid", wrong)
   742  		}
   743  	}
   744  }
   745  
   746  func BenchmarkUUID_New(b *testing.B) {
   747  	b.RunParallel(func(pb *testing.PB) {
   748  		for pb.Next() {
   749  			_, err := newRandom()
   750  			if err != nil {
   751  				b.Fatal(err)
   752  			}
   753  		}
   754  	})
   755  }
   756  
   757  func BenchmarkUUID_NewPooled(b *testing.B) {
   758  	EnableRandPool()
   759  	b.RunParallel(func(pb *testing.PB) {
   760  		for pb.Next() {
   761  			_, err := newRandom()
   762  			if err != nil {
   763  				b.Fatal(err)
   764  			}
   765  		}
   766  	})
   767  }
   768  
   769  func BenchmarkUUIDs_Strings(b *testing.B) {
   770  	uuid1, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
   771  	if err != nil {
   772  		b.Fatal(err)
   773  	}
   774  	uuid2, err := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2")
   775  	if err != nil {
   776  		b.Fatal(err)
   777  	}
   778  	uuids := UUIDs{uuid1, uuid2}
   779  	for i := 0; i < b.N; i++ {
   780  		uuids.Strings()
   781  	}
   782  }
   783  
   784  func TestVersion6(t *testing.T) {
   785  	uuid1, err := NewV6()
   786  	if err != nil {
   787  		t.Fatalf("could not create UUID: %v", err)
   788  	}
   789  	uuid2, err := NewV6()
   790  	if err != nil {
   791  		t.Fatalf("could not create UUID: %v", err)
   792  	}
   793  
   794  	if uuid1 == uuid2 {
   795  		t.Errorf("%s:duplicate uuid", uuid1)
   796  	}
   797  	if v := uuid1.Version(); v != 6 {
   798  		t.Errorf("%s: version %s expected 6", uuid1, v)
   799  	}
   800  	if v := uuid2.Version(); v != 6 {
   801  		t.Errorf("%s: version %s expected 6", uuid2, v)
   802  	}
   803  	n1 := uuid1.NodeID()
   804  	n2 := uuid2.NodeID()
   805  	if !bytes.Equal(n1, n2) {
   806  		t.Errorf("Different nodes %x != %x", n1, n2)
   807  	}
   808  	t1 := uuid1.Time()
   809  	t2 := uuid2.Time()
   810  	q1 := uuid1.ClockSequence()
   811  	q2 := uuid2.ClockSequence()
   812  
   813  	switch {
   814  	case t1 == t2 && q1 == q2:
   815  		t.Error("time stopped")
   816  	case t1 > t2 && q1 == q2:
   817  		t.Error("time reversed")
   818  	case t1 < t2 && q1 != q2:
   819  		t.Error("clock sequence changed unexpectedly")
   820  	}
   821  }
   822  
   823  // uuid v7 time is only unix milliseconds, so
   824  // uuid1.Time() == uuid2.Time() is right, but uuid1 must != uuid2
   825  func TestVersion7(t *testing.T) {
   826  	SetRand(nil)
   827  	m := make(map[string]bool)
   828  	for x := 1; x < 128; x++ {
   829  		uuid := NewV7()
   830  		// if err != nil {
   831  		// 	t.Fatalf("could not create UUID: %v", err)
   832  		// }
   833  		s := uuid.String()
   834  		if m[s] {
   835  			t.Errorf("NewV7 returned duplicated UUID %s", s)
   836  		}
   837  		m[s] = true
   838  		if v := uuid.Version(); v != 7 {
   839  			t.Errorf("UUID of version %s", v)
   840  		}
   841  		if uuid.Variant() != RFC4122 {
   842  			t.Errorf("UUID is variant %d", uuid.Variant())
   843  		}
   844  	}
   845  }
   846  
   847  // uuid v7 time is only unix milliseconds, so
   848  // uuid1.Time() == uuid2.Time() is right, but uuid1 must != uuid2
   849  func TestVersion7_pooled(t *testing.T) {
   850  	SetRand(nil)
   851  	EnableRandPool()
   852  	defer DisableRandPool()
   853  
   854  	m := make(map[string]bool)
   855  	for x := 1; x < 128; x++ {
   856  		uuid := NewV7()
   857  		// if err != nil {
   858  		// 	t.Fatalf("could not create UUID: %v", err)
   859  		// }
   860  		s := uuid.String()
   861  		if m[s] {
   862  			t.Errorf("NewV7 returned duplicated UUID %s", s)
   863  		}
   864  		m[s] = true
   865  		if v := uuid.Version(); v != 7 {
   866  			t.Errorf("UUID of version %s", v)
   867  		}
   868  		if uuid.Variant() != RFC4122 {
   869  			t.Errorf("UUID is variant %d", uuid.Variant())
   870  		}
   871  	}
   872  }
   873  
   874  func TestVersion7FromReader(t *testing.T) {
   875  	myString := "8059ddhdle77cb52"
   876  	r := bytes.NewReader([]byte(myString))
   877  	_, err := NewV7FromReader(r)
   878  	if err != nil {
   879  		t.Errorf("failed generating UUID from a reader")
   880  	}
   881  	_, err = NewV7FromReader(r)
   882  	if err == nil {
   883  		t.Errorf("expecting an error as reader has no more bytes. Got uuid. NewV7FromReader may not be using the provided reader")
   884  	}
   885  }
   886  
   887  func TestVersion7Monotonicity(t *testing.T) {
   888  	length := 10000
   889  	u1 := NewV7().String()
   890  	for i := 0; i < length; i++ {
   891  		u2 := NewV7().String()
   892  		if u2 <= u1 {
   893  			t.Errorf("monotonicity failed at #%d: %s(next) < %s(before)", i, u2, u1)
   894  			break
   895  		}
   896  		u1 = u2
   897  	}
   898  }
   899  
   900  type fakeRand struct{}
   901  
   902  func (g fakeRand) Read(bs []byte) (int, error) {
   903  	for i, _ := range bs {
   904  		bs[i] = 0x88
   905  	}
   906  	return len(bs), nil
   907  }
   908  
   909  func TestVersion7MonotonicityStrict(t *testing.T) {
   910  	timeNow = func() time.Time {
   911  		return time.Date(2008, 8, 8, 8, 8, 8, 8, time.UTC)
   912  	}
   913  	defer func() {
   914  		timeNow = time.Now
   915  	}()
   916  
   917  	SetRand(fakeRand{})
   918  	defer SetRand(nil)
   919  
   920  	length := 100000 // > 3906
   921  	u1 := NewV7().String()
   922  	for i := 0; i < length; i++ {
   923  		u2 := NewV7().String()
   924  		if u2 <= u1 {
   925  			t.Errorf("monotonicity failed at #%d: %s(next) < %s(before)", i, u2, u1)
   926  			break
   927  		}
   928  		u1 = u2
   929  	}
   930  }
   931  
   932  func TestEqual(t *testing.T) {
   933  	zero := Nil
   934  	someUuid := NewV4()
   935  
   936  	for range 100 {
   937  		uuid := NewV4()
   938  		if uuid.Equal(uuid) == false {
   939  			t.Fatalf("%s should be equal to %s", uuid.String(), uuid.String())
   940  		}
   941  
   942  		if uuid.Equal(zero) {
   943  			t.Fatalf("%s should be different than %s", uuid.String(), zero.String())
   944  		}
   945  
   946  		if uuid.Equal(someUuid) {
   947  			t.Fatalf("%s should be different than %s", uuid.String(), someUuid.String())
   948  		}
   949  	}
   950  
   951  }