1
2
3
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 := New()
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 := New()
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 TestNew(t *testing.T) {
207 m := make(map[UUID]bool)
208 for x := 1; x < 32; x++ {
209 s := New()
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
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
258
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
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
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 := New()
492 uuid2 := New()
493 if uuid1 != uuid2 {
494 t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2)
495 }
496 SetRand(nil)
497 uuid1 = New()
498 uuid2 = New()
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 := New()
509 uuid2 := New()
510
511 SetRand(strings.NewReader(myString))
512 uuid3 := New()
513 uuid4 := New()
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
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
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
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
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 New()
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
824
825 func TestVersion7(t *testing.T) {
826 SetRand(nil)
827 m := make(map[string]bool)
828 for x := 1; x < 128; x++ {
829 uuid, err := 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
848
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, err := 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 := Must(NewV7()).String()
890 for i := 0; i < length; i++ {
891 u2 := Must(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
921 u1 := Must(NewV7()).String()
922 for i := 0; i < length; i++ {
923 u2 := Must(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
View as plain text