...

Source file src/github.com/gofrs/uuid/generator_test.go

Documentation: github.com/gofrs/uuid

     1  // Copyright (C) 2013-2018 by Maxim Bublis <b@codemonkey.ru>
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining
     4  // a copy of this software and associated documentation files (the
     5  // "Software"), to deal in the Software without restriction, including
     6  // without limitation the rights to use, copy, modify, merge, publish,
     7  // distribute, sublicense, and/or sell copies of the Software, and to
     8  // permit persons to whom the Software is furnished to do so, subject to
     9  // the following conditions:
    10  //
    11  // The above copyright notice and this permission notice shall be
    12  // included in all copies or substantial portions of the Software.
    13  //
    14  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    17  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
    18  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
    19  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
    20  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    21  
    22  package uuid
    23  
    24  import (
    25  	"bytes"
    26  	"crypto/rand"
    27  	"encoding/binary"
    28  	"errors"
    29  	"fmt"
    30  	"net"
    31  	"strings"
    32  	"testing"
    33  	"time"
    34  )
    35  
    36  func TestGenerator(t *testing.T) {
    37  	t.Run("NewV1", testNewV1)
    38  	t.Run("NewV3", testNewV3)
    39  	t.Run("NewV4", testNewV4)
    40  	t.Run("NewV5", testNewV5)
    41  	t.Run("NewV6", testNewV6)
    42  	t.Run("NewV7", testNewV7)
    43  }
    44  
    45  func testNewV1(t *testing.T) {
    46  	t.Run("Basic", testNewV1Basic)
    47  	t.Run("DifferentAcrossCalls", testNewV1DifferentAcrossCalls)
    48  	t.Run("StaleEpoch", testNewV1StaleEpoch)
    49  	t.Run("FaultyRand", testNewV1FaultyRand)
    50  	t.Run("MissingNetwork", testNewV1MissingNetwork)
    51  	t.Run("MissingNetworkFaultyRand", testNewV1MissingNetworkFaultyRand)
    52  }
    53  
    54  func TestNewGenWithHWAF(t *testing.T) {
    55  	addr := []byte{0, 1, 2, 3, 4, 42}
    56  
    57  	fn := func() (net.HardwareAddr, error) {
    58  		return addr, nil
    59  	}
    60  
    61  	var g *Gen
    62  	var err error
    63  	var uuid UUID
    64  
    65  	g = NewGenWithHWAF(fn)
    66  
    67  	if g == nil {
    68  		t.Fatal("g is unexpectedly nil")
    69  	}
    70  
    71  	uuid, err = g.NewV1()
    72  	if err != nil {
    73  		t.Fatalf("g.NewV1() err = %v, want <nil>", err)
    74  	}
    75  
    76  	node := uuid[10:]
    77  
    78  	if !bytes.Equal(addr, node) {
    79  		t.Fatalf("node = %v, want %v", node, addr)
    80  	}
    81  }
    82  
    83  func testNewV1Basic(t *testing.T) {
    84  	u, err := NewV1()
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  	if got, want := u.Version(), V1; got != want {
    89  		t.Errorf("generated UUID with version %d, want %d", got, want)
    90  	}
    91  	if got, want := u.Variant(), VariantRFC4122; got != want {
    92  		t.Errorf("generated UUID with variant %d, want %d", got, want)
    93  	}
    94  }
    95  
    96  func testNewV1DifferentAcrossCalls(t *testing.T) {
    97  	u1, err := NewV1()
    98  	if err != nil {
    99  		t.Fatal(err)
   100  	}
   101  	u2, err := NewV1()
   102  	if err != nil {
   103  		t.Fatal(err)
   104  	}
   105  	if u1 == u2 {
   106  		t.Errorf("generated identical UUIDs across calls: %v", u1)
   107  	}
   108  }
   109  
   110  func testNewV1StaleEpoch(t *testing.T) {
   111  	g := &Gen{
   112  		epochFunc: func() time.Time {
   113  			return time.Unix(0, 0)
   114  		},
   115  		hwAddrFunc: defaultHWAddrFunc,
   116  		rand:       rand.Reader,
   117  	}
   118  	u1, err := g.NewV1()
   119  	if err != nil {
   120  		t.Fatal(err)
   121  	}
   122  	u2, err := g.NewV1()
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  	if u1 == u2 {
   127  		t.Errorf("generated identical UUIDs across calls: %v", u1)
   128  	}
   129  }
   130  
   131  func testNewV1FaultyRand(t *testing.T) {
   132  	g := &Gen{
   133  		epochFunc:  time.Now,
   134  		hwAddrFunc: defaultHWAddrFunc,
   135  		rand: &faultyReader{
   136  			readToFail: 0, // fail immediately
   137  		},
   138  	}
   139  	u, err := g.NewV1()
   140  	if err == nil {
   141  		t.Fatalf("got %v, want error", u)
   142  	}
   143  	if u != Nil {
   144  		t.Fatalf("got %v on error, want Nil", u)
   145  	}
   146  }
   147  
   148  func testNewV1MissingNetwork(t *testing.T) {
   149  	g := &Gen{
   150  		epochFunc: time.Now,
   151  		hwAddrFunc: func() (net.HardwareAddr, error) {
   152  			return []byte{}, fmt.Errorf("uuid: no hw address found")
   153  		},
   154  		rand: rand.Reader,
   155  	}
   156  	_, err := g.NewV1()
   157  	if err != nil {
   158  		t.Errorf("did not handle missing network interfaces: %v", err)
   159  	}
   160  }
   161  
   162  func testNewV1MissingNetworkFaultyRand(t *testing.T) {
   163  	g := &Gen{
   164  		epochFunc: time.Now,
   165  		hwAddrFunc: func() (net.HardwareAddr, error) {
   166  			return []byte{}, fmt.Errorf("uuid: no hw address found")
   167  		},
   168  		rand: &faultyReader{
   169  			readToFail: 1,
   170  		},
   171  	}
   172  	u, err := g.NewV1()
   173  	if err == nil {
   174  		t.Errorf("did not error on faulty reader and missing network, got %v", u)
   175  	}
   176  }
   177  
   178  func testNewV3(t *testing.T) {
   179  	t.Run("Basic", testNewV3Basic)
   180  	t.Run("EqualNames", testNewV3EqualNames)
   181  	t.Run("DifferentNamespaces", testNewV3DifferentNamespaces)
   182  }
   183  
   184  func testNewV3Basic(t *testing.T) {
   185  	ns := NamespaceDNS
   186  	name := "www.example.com"
   187  	u := NewV3(ns, name)
   188  	if got, want := u.Version(), V3; got != want {
   189  		t.Errorf("NewV3(%v, %q): got version %d, want %d", ns, name, got, want)
   190  	}
   191  	if got, want := u.Variant(), VariantRFC4122; got != want {
   192  		t.Errorf("NewV3(%v, %q): got variant %d, want %d", ns, name, got, want)
   193  	}
   194  	want := "5df41881-3aed-3515-88a7-2f4a814cf09e"
   195  	if got := u.String(); got != want {
   196  		t.Errorf("NewV3(%v, %q) = %q, want %q", ns, name, got, want)
   197  	}
   198  }
   199  
   200  func testNewV3EqualNames(t *testing.T) {
   201  	ns := NamespaceDNS
   202  	name := "example.com"
   203  	u1 := NewV3(ns, name)
   204  	u2 := NewV3(ns, name)
   205  	if u1 != u2 {
   206  		t.Errorf("NewV3(%v, %q) generated %v and %v across two calls", ns, name, u1, u2)
   207  	}
   208  }
   209  
   210  func testNewV3DifferentNamespaces(t *testing.T) {
   211  	name := "example.com"
   212  	ns1 := NamespaceDNS
   213  	ns2 := NamespaceURL
   214  	u1 := NewV3(ns1, name)
   215  	u2 := NewV3(ns2, name)
   216  	if u1 == u2 {
   217  		t.Errorf("NewV3(%v, %q) == NewV3(%d, %q) (%v)", ns1, name, ns2, name, u1)
   218  	}
   219  }
   220  
   221  func testNewV4(t *testing.T) {
   222  	t.Run("Basic", testNewV4Basic)
   223  	t.Run("DifferentAcrossCalls", testNewV4DifferentAcrossCalls)
   224  	t.Run("FaultyRand", testNewV4FaultyRand)
   225  	t.Run("ShortRandomRead", testNewV4ShortRandomRead)
   226  }
   227  
   228  func testNewV4Basic(t *testing.T) {
   229  	u, err := NewV4()
   230  	if err != nil {
   231  		t.Fatal(err)
   232  	}
   233  	if got, want := u.Version(), V4; got != want {
   234  		t.Errorf("got version %d, want %d", got, want)
   235  	}
   236  	if got, want := u.Variant(), VariantRFC4122; got != want {
   237  		t.Errorf("got variant %d, want %d", got, want)
   238  	}
   239  }
   240  
   241  func testNewV4DifferentAcrossCalls(t *testing.T) {
   242  	u1, err := NewV4()
   243  	if err != nil {
   244  		t.Fatal(err)
   245  	}
   246  	u2, err := NewV4()
   247  	if err != nil {
   248  		t.Fatal(err)
   249  	}
   250  	if u1 == u2 {
   251  		t.Errorf("generated identical UUIDs across calls: %v", u1)
   252  	}
   253  }
   254  
   255  func testNewV4FaultyRand(t *testing.T) {
   256  	g := &Gen{
   257  		epochFunc:  time.Now,
   258  		hwAddrFunc: defaultHWAddrFunc,
   259  		rand: &faultyReader{
   260  			readToFail: 0, // fail immediately
   261  		},
   262  	}
   263  	u, err := g.NewV4()
   264  	if err == nil {
   265  		t.Errorf("got %v, nil error", u)
   266  	}
   267  }
   268  
   269  func testNewV4ShortRandomRead(t *testing.T) {
   270  	g := &Gen{
   271  		epochFunc: time.Now,
   272  		hwAddrFunc: func() (net.HardwareAddr, error) {
   273  			return []byte{}, fmt.Errorf("uuid: no hw address found")
   274  		},
   275  		rand: bytes.NewReader([]byte{42}),
   276  	}
   277  	u, err := g.NewV4()
   278  	if err == nil {
   279  		t.Errorf("got %v, nil error", u)
   280  	}
   281  }
   282  
   283  func testNewV5(t *testing.T) {
   284  	t.Run("Basic", testNewV5Basic)
   285  	t.Run("EqualNames", testNewV5EqualNames)
   286  	t.Run("DifferentNamespaces", testNewV5DifferentNamespaces)
   287  }
   288  
   289  func testNewV5Basic(t *testing.T) {
   290  	ns := NamespaceDNS
   291  	name := "www.example.com"
   292  	u := NewV5(ns, name)
   293  	if got, want := u.Version(), V5; got != want {
   294  		t.Errorf("NewV5(%v, %q): got version %d, want %d", ns, name, got, want)
   295  	}
   296  	if got, want := u.Variant(), VariantRFC4122; got != want {
   297  		t.Errorf("NewV5(%v, %q): got variant %d, want %d", ns, name, got, want)
   298  	}
   299  	want := "2ed6657d-e927-568b-95e1-2665a8aea6a2"
   300  	if got := u.String(); got != want {
   301  		t.Errorf("NewV5(%v, %q) = %q, want %q", ns, name, got, want)
   302  	}
   303  }
   304  
   305  func testNewV5EqualNames(t *testing.T) {
   306  	ns := NamespaceDNS
   307  	name := "example.com"
   308  	u1 := NewV5(ns, name)
   309  	u2 := NewV5(ns, name)
   310  	if u1 != u2 {
   311  		t.Errorf("NewV5(%v, %q) generated %v and %v across two calls", ns, name, u1, u2)
   312  	}
   313  }
   314  
   315  func testNewV5DifferentNamespaces(t *testing.T) {
   316  	name := "example.com"
   317  	ns1 := NamespaceDNS
   318  	ns2 := NamespaceURL
   319  	u1 := NewV5(ns1, name)
   320  	u2 := NewV5(ns2, name)
   321  	if u1 == u2 {
   322  		t.Errorf("NewV5(%v, %q) == NewV5(%v, %q) (%v)", ns1, name, ns2, name, u1)
   323  	}
   324  }
   325  
   326  func testNewV6(t *testing.T) {
   327  	t.Run("Basic", testNewV6Basic)
   328  	t.Run("DifferentAcrossCalls", testNewV6DifferentAcrossCalls)
   329  	t.Run("StaleEpoch", testNewV6StaleEpoch)
   330  	t.Run("FaultyRand", testNewV6FaultyRand)
   331  	t.Run("ShortRandomRead", testNewV6ShortRandomRead)
   332  	t.Run("KSortable", testNewV6KSortable)
   333  }
   334  
   335  func testNewV6Basic(t *testing.T) {
   336  	u, err := NewV6()
   337  	if err != nil {
   338  		t.Fatal(err)
   339  	}
   340  	if got, want := u.Version(), V6; got != want {
   341  		t.Errorf("generated UUID with version %d, want %d", got, want)
   342  	}
   343  	if got, want := u.Variant(), VariantRFC4122; got != want {
   344  		t.Errorf("generated UUID with variant %d, want %d", got, want)
   345  	}
   346  }
   347  
   348  func testNewV6DifferentAcrossCalls(t *testing.T) {
   349  	u1, err := NewV6()
   350  	if err != nil {
   351  		t.Fatal(err)
   352  	}
   353  	u2, err := NewV6()
   354  	if err != nil {
   355  		t.Fatal(err)
   356  	}
   357  	if u1 == u2 {
   358  		t.Errorf("generated identical UUIDs across calls: %v", u1)
   359  	}
   360  }
   361  
   362  func testNewV6StaleEpoch(t *testing.T) {
   363  	g := &Gen{
   364  		epochFunc: func() time.Time {
   365  			return time.Unix(0, 0)
   366  		},
   367  		hwAddrFunc: defaultHWAddrFunc,
   368  		rand:       rand.Reader,
   369  	}
   370  	u1, err := g.NewV6()
   371  	if err != nil {
   372  		t.Fatal(err)
   373  	}
   374  	u2, err := g.NewV6()
   375  	if err != nil {
   376  		t.Fatal(err)
   377  	}
   378  	if u1 == u2 {
   379  		t.Errorf("generated identical UUIDs across calls: %v", u1)
   380  	}
   381  }
   382  
   383  func testNewV6FaultyRand(t *testing.T) {
   384  	t.Run("randomData", func(t *testing.T) {
   385  		g := &Gen{
   386  			epochFunc:  time.Now,
   387  			hwAddrFunc: defaultHWAddrFunc,
   388  			rand: &faultyReader{
   389  				readToFail: 0, // fail immediately
   390  			},
   391  		}
   392  		u, err := g.NewV6()
   393  		if err == nil {
   394  			t.Fatalf("got %v, want error", u)
   395  		}
   396  		if u != Nil {
   397  			t.Fatalf("got %v on error, want Nil", u)
   398  		}
   399  	})
   400  
   401  	t.Run("clockSequence", func(t *testing.T) {
   402  		g := &Gen{
   403  			epochFunc:  time.Now,
   404  			hwAddrFunc: defaultHWAddrFunc,
   405  			rand: &faultyReader{
   406  				readToFail: 1, // fail immediately
   407  			},
   408  		}
   409  		u, err := g.NewV6()
   410  		if err == nil {
   411  			t.Fatalf("got %v, want error", u)
   412  		}
   413  		if u != Nil {
   414  			t.Fatalf("got %v on error, want Nil", u)
   415  		}
   416  	})
   417  }
   418  
   419  func testNewV6ShortRandomRead(t *testing.T) {
   420  	g := &Gen{
   421  		epochFunc: time.Now,
   422  		rand:      bytes.NewReader([]byte{42}),
   423  	}
   424  	u, err := g.NewV6()
   425  	if err == nil {
   426  		t.Errorf("got %v, nil error", u)
   427  	}
   428  }
   429  
   430  func testNewV6KSortable(t *testing.T) {
   431  	uuids := make([]UUID, 10)
   432  	for i := range uuids {
   433  		u, err := NewV6()
   434  		testErrCheck(t, "NewV6()", "", err)
   435  
   436  		uuids[i] = u
   437  
   438  		time.Sleep(time.Microsecond)
   439  	}
   440  
   441  	for i := 1; i < len(uuids); i++ {
   442  		p, n := uuids[i-1], uuids[i]
   443  		isLess := p.String() < n.String()
   444  		if !isLess {
   445  			t.Errorf("uuids[%d] (%s) not less than uuids[%d] (%s)", i-1, p, i, n)
   446  		}
   447  	}
   448  }
   449  
   450  func testNewV7(t *testing.T) {
   451  	t.Run("Basic", makeTestNewV7Basic())
   452  	t.Run("Basic10000000", makeTestNewV7Basic10000000())
   453  	t.Run("DifferentAcrossCalls", makeTestNewV7DifferentAcrossCalls())
   454  	t.Run("StaleEpoch", makeTestNewV7StaleEpoch())
   455  	t.Run("FaultyRand", makeTestNewV7FaultyRand())
   456  	t.Run("ShortRandomRead", makeTestNewV7ShortRandomRead())
   457  	t.Run("KSortable", makeTestNewV7KSortable())
   458  }
   459  
   460  func makeTestNewV7Basic() func(t *testing.T) {
   461  	return func(t *testing.T) {
   462  		u, err := NewV7()
   463  		if err != nil {
   464  			t.Fatal(err)
   465  		}
   466  		if got, want := u.Version(), V7; got != want {
   467  			t.Errorf("got version %d, want %d", got, want)
   468  		}
   469  		if got, want := u.Variant(), VariantRFC4122; got != want {
   470  			t.Errorf("got variant %d, want %d", got, want)
   471  		}
   472  	}
   473  }
   474  
   475  func makeTestNewV7Basic10000000() func(t *testing.T) {
   476  	return func(t *testing.T) {
   477  		if testing.Short() {
   478  			t.Skip("skipping test in short mode.")
   479  		}
   480  
   481  		g := NewGen()
   482  
   483  		for i := 0; i < 10000000; i++ {
   484  			u, err := g.NewV7()
   485  			if err != nil {
   486  				t.Fatal(err)
   487  			}
   488  			if got, want := u.Version(), V7; got != want {
   489  				t.Errorf("got version %d, want %d", got, want)
   490  			}
   491  			if got, want := u.Variant(), VariantRFC4122; got != want {
   492  				t.Errorf("got variant %d, want %d", got, want)
   493  			}
   494  		}
   495  	}
   496  }
   497  
   498  func makeTestNewV7DifferentAcrossCalls() func(t *testing.T) {
   499  	return func(t *testing.T) {
   500  		g := NewGen()
   501  
   502  		u1, err := g.NewV7()
   503  		if err != nil {
   504  			t.Fatal(err)
   505  		}
   506  		u2, err := g.NewV7()
   507  		if err != nil {
   508  			t.Fatal(err)
   509  		}
   510  		if u1 == u2 {
   511  			t.Errorf("generated identical UUIDs across calls: %v", u1)
   512  		}
   513  	}
   514  }
   515  
   516  func makeTestNewV7StaleEpoch() func(t *testing.T) {
   517  	return func(t *testing.T) {
   518  		g := &Gen{
   519  			epochFunc: func() time.Time {
   520  				return time.Unix(0, 0)
   521  			},
   522  			rand: rand.Reader,
   523  		}
   524  		u1, err := g.NewV7()
   525  		if err != nil {
   526  			t.Fatal(err)
   527  		}
   528  		u2, err := g.NewV7()
   529  		if err != nil {
   530  			t.Fatal(err)
   531  		}
   532  		if u1 == u2 {
   533  			t.Errorf("generated identical UUIDs across calls: %v", u1)
   534  		}
   535  	}
   536  }
   537  
   538  func makeTestNewV7FaultyRand() func(t *testing.T) {
   539  	return func(t *testing.T) {
   540  		g := &Gen{
   541  			epochFunc: time.Now,
   542  			rand: &faultyReader{
   543  				readToFail: 0, // fail immediately
   544  			},
   545  		}
   546  		u, err := g.NewV7()
   547  		if err == nil {
   548  			t.Errorf("got %v, nil error", u)
   549  		}
   550  	}
   551  }
   552  
   553  func makeTestNewV7ShortRandomRead() func(t *testing.T) {
   554  	return func(t *testing.T) {
   555  		g := &Gen{
   556  			epochFunc: time.Now,
   557  			rand:      bytes.NewReader([]byte{42}),
   558  		}
   559  		u, err := g.NewV7()
   560  		if err == nil {
   561  			t.Errorf("got %v, nil error", u)
   562  		}
   563  	}
   564  }
   565  
   566  func makeTestNewV7KSortable() func(t *testing.T) {
   567  	return func(t *testing.T) {
   568  		uuids := make([]UUID, 10)
   569  		for i := range uuids {
   570  			u, err := NewV7()
   571  			testErrCheck(t, "NewV7()", "", err)
   572  
   573  			uuids[i] = u
   574  			time.Sleep(time.Millisecond)
   575  		}
   576  
   577  		for i := 1; i < len(uuids); i++ {
   578  			p, n := uuids[i-1], uuids[i]
   579  			isLess := p.String() < n.String()
   580  			if !isLess {
   581  				t.Errorf("uuids[%d] (%s) not less than uuids[%d] (%s)", i-1, p, i, n)
   582  			}
   583  		}
   584  	}
   585  }
   586  
   587  func testNewV7ClockSequence(t *testing.T) {
   588  	if testing.Short() {
   589  		t.Skip("skipping test in short mode.")
   590  	}
   591  
   592  	g := NewGen()
   593  
   594  	// hack to try and reduce race conditions based on when the test starts
   595  	nsec := time.Now().Nanosecond()
   596  	sleepDur := int(time.Second) - nsec
   597  	time.Sleep(time.Duration(sleepDur))
   598  
   599  	u1, err := g.NewV7()
   600  	if err != nil {
   601  		t.Fatalf("failed to generate V7 UUID #1: %v", err)
   602  	}
   603  
   604  	u2, err := g.NewV7()
   605  	if err != nil {
   606  		t.Fatalf("failed to generate V7 UUID #2: %v", err)
   607  	}
   608  
   609  	time.Sleep(time.Millisecond)
   610  
   611  	u3, err := g.NewV7()
   612  	if err != nil {
   613  		t.Fatalf("failed to generate V7 UUID #3: %v", err)
   614  	}
   615  
   616  	time.Sleep(time.Second)
   617  
   618  	u4, err := g.NewV7()
   619  	if err != nil {
   620  		t.Fatalf("failed to generate V7 UUID #3: %v", err)
   621  	}
   622  
   623  	s1 := binary.BigEndian.Uint16(u1[6:8]) & 0xfff
   624  	s2 := binary.BigEndian.Uint16(u2[6:8]) & 0xfff
   625  	s3 := binary.BigEndian.Uint16(u3[6:8]) & 0xfff
   626  	s4 := binary.BigEndian.Uint16(u4[6:8]) & 0xfff
   627  
   628  	if s1 != 0 {
   629  		t.Errorf("sequence 1 should be zero, was %d", s1)
   630  	}
   631  
   632  	if s2 != s1+1 {
   633  		t.Errorf("sequence 2 expected to be one above sequence 1; seq 1: %d, seq 2: %d", s1, s2)
   634  	}
   635  
   636  	if s3 != 0 {
   637  		t.Errorf("sequence 3 should be zero, was %d", s3)
   638  	}
   639  
   640  	if s4 != 0 {
   641  		t.Errorf("sequence 4 should be zero, was %d", s4)
   642  	}
   643  }
   644  
   645  func TestDefaultHWAddrFunc(t *testing.T) {
   646  	tests := []struct {
   647  		n  string
   648  		fn func() ([]net.Interface, error)
   649  		hw net.HardwareAddr
   650  		e  string
   651  	}{
   652  		{
   653  			n: "Error",
   654  			fn: func() ([]net.Interface, error) {
   655  				return nil, errors.New("controlled failure")
   656  			},
   657  			e: "controlled failure",
   658  		},
   659  		{
   660  			n: "NoValidHWAddrReturned",
   661  			fn: func() ([]net.Interface, error) {
   662  				s := []net.Interface{
   663  					{
   664  						Index:        1,
   665  						MTU:          1500,
   666  						Name:         "test0",
   667  						HardwareAddr: net.HardwareAddr{1, 2, 3, 4},
   668  					},
   669  					{
   670  						Index:        2,
   671  						MTU:          1500,
   672  						Name:         "lo0",
   673  						HardwareAddr: net.HardwareAddr{5, 6, 7, 8},
   674  					},
   675  				}
   676  
   677  				return s, nil
   678  			},
   679  			e: "uuid: no HW address found",
   680  		},
   681  		{
   682  			n: "ValidHWAddrReturned",
   683  			fn: func() ([]net.Interface, error) {
   684  				s := []net.Interface{
   685  					{
   686  						Index:        1,
   687  						MTU:          1500,
   688  						Name:         "test0",
   689  						HardwareAddr: net.HardwareAddr{1, 2, 3, 4},
   690  					},
   691  					{
   692  						Index:        2,
   693  						MTU:          1500,
   694  						Name:         "lo0",
   695  						HardwareAddr: net.HardwareAddr{5, 6, 7, 8, 9, 0},
   696  					},
   697  				}
   698  
   699  				return s, nil
   700  			},
   701  			hw: net.HardwareAddr{5, 6, 7, 8, 9, 0},
   702  		},
   703  	}
   704  
   705  	for _, tt := range tests {
   706  		t.Run(tt.n, func(t *testing.T) {
   707  			// set the netInterfaces variable (function) for the test
   708  			// and then set it back to default in the deferred function
   709  			netInterfaces = tt.fn
   710  			defer func() {
   711  				netInterfaces = net.Interfaces
   712  			}()
   713  
   714  			var hw net.HardwareAddr
   715  			var err error
   716  
   717  			hw, err = defaultHWAddrFunc()
   718  
   719  			if len(tt.e) > 0 {
   720  				if err == nil {
   721  					t.Fatalf("defaultHWAddrFunc() error = <nil>, should contain %q", tt.e)
   722  				}
   723  
   724  				if !strings.Contains(err.Error(), tt.e) {
   725  					t.Fatalf("defaultHWAddrFunc() error = %q, should contain %q", err.Error(), tt.e)
   726  				}
   727  
   728  				return
   729  			}
   730  
   731  			if err != nil && tt.e == "" {
   732  				t.Fatalf("defaultHWAddrFunc() error = %q, want <nil>", err.Error())
   733  			}
   734  
   735  			if !bytes.Equal(hw, tt.hw) {
   736  				t.Fatalf("hw = %#v, want %#v", hw, tt.hw)
   737  			}
   738  		})
   739  	}
   740  }
   741  
   742  func BenchmarkGenerator(b *testing.B) {
   743  	b.Run("NewV1", func(b *testing.B) {
   744  		for i := 0; i < b.N; i++ {
   745  			NewV1()
   746  		}
   747  	})
   748  	b.Run("NewV3", func(b *testing.B) {
   749  		for i := 0; i < b.N; i++ {
   750  			NewV3(NamespaceDNS, "www.example.com")
   751  		}
   752  	})
   753  	b.Run("NewV4", func(b *testing.B) {
   754  		for i := 0; i < b.N; i++ {
   755  			NewV4()
   756  		}
   757  	})
   758  	b.Run("NewV5", func(b *testing.B) {
   759  		for i := 0; i < b.N; i++ {
   760  			NewV5(NamespaceDNS, "www.example.com")
   761  		}
   762  	})
   763  }
   764  
   765  type faultyReader struct {
   766  	callsNum   int
   767  	readToFail int // Read call number to fail
   768  }
   769  
   770  func (r *faultyReader) Read(dest []byte) (int, error) {
   771  	r.callsNum++
   772  	if (r.callsNum - 1) == r.readToFail {
   773  		return 0, fmt.Errorf("io: reader is faulty")
   774  	}
   775  	return rand.Read(dest)
   776  }
   777  
   778  // testErrCheck looks to see if errContains is a substring of err.Error(). If
   779  // not, this calls t.Fatal(). It also calls t.Fatal() if there was an error, but
   780  // errContains is empty. Returns true if you should continue running the test,
   781  // or false if you should stop the test.
   782  func testErrCheck(t *testing.T, name string, errContains string, err error) bool {
   783  	t.Helper()
   784  
   785  	if len(errContains) > 0 {
   786  		if err == nil {
   787  			t.Fatalf("%s error = <nil>, should contain %q", name, errContains)
   788  			return false
   789  		}
   790  
   791  		if errStr := err.Error(); !strings.Contains(errStr, errContains) {
   792  			t.Fatalf("%s error = %q, should contain %q", name, errStr, errContains)
   793  			return false
   794  		}
   795  
   796  		return false
   797  	}
   798  
   799  	if err != nil && len(errContains) == 0 {
   800  		t.Fatalf("%s unexpected error: %v", name, err)
   801  		return false
   802  	}
   803  
   804  	return true
   805  }
   806  

View as plain text