uuid_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  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. package uuid
  5. import (
  6. "bytes"
  7. "fmt"
  8. "os"
  9. "runtime"
  10. "strings"
  11. "testing"
  12. "time"
  13. "unsafe"
  14. )
  15. type test struct {
  16. in string
  17. version Version
  18. variant Variant
  19. isuuid bool
  20. }
  21. var tests = []test{
  22. {"f47ac10b-58cc-0372-8567-0e02b2c3d479", 0, RFC4122, true},
  23. {"f47ac10b-58cc-1372-8567-0e02b2c3d479", 1, RFC4122, true},
  24. {"f47ac10b-58cc-2372-8567-0e02b2c3d479", 2, RFC4122, true},
  25. {"f47ac10b-58cc-3372-8567-0e02b2c3d479", 3, RFC4122, true},
  26. {"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
  27. {"f47ac10b-58cc-5372-8567-0e02b2c3d479", 5, RFC4122, true},
  28. {"f47ac10b-58cc-6372-8567-0e02b2c3d479", 6, RFC4122, true},
  29. {"f47ac10b-58cc-7372-8567-0e02b2c3d479", 7, RFC4122, true},
  30. {"f47ac10b-58cc-8372-8567-0e02b2c3d479", 8, RFC4122, true},
  31. {"f47ac10b-58cc-9372-8567-0e02b2c3d479", 9, RFC4122, true},
  32. {"f47ac10b-58cc-a372-8567-0e02b2c3d479", 10, RFC4122, true},
  33. {"f47ac10b-58cc-b372-8567-0e02b2c3d479", 11, RFC4122, true},
  34. {"f47ac10b-58cc-c372-8567-0e02b2c3d479", 12, RFC4122, true},
  35. {"f47ac10b-58cc-d372-8567-0e02b2c3d479", 13, RFC4122, true},
  36. {"f47ac10b-58cc-e372-8567-0e02b2c3d479", 14, RFC4122, true},
  37. {"f47ac10b-58cc-f372-8567-0e02b2c3d479", 15, RFC4122, true},
  38. {"urn:uuid:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
  39. {"URN:UUID:f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
  40. {"f47ac10b-58cc-4372-0567-0e02b2c3d479", 4, Reserved, true},
  41. {"f47ac10b-58cc-4372-1567-0e02b2c3d479", 4, Reserved, true},
  42. {"f47ac10b-58cc-4372-2567-0e02b2c3d479", 4, Reserved, true},
  43. {"f47ac10b-58cc-4372-3567-0e02b2c3d479", 4, Reserved, true},
  44. {"f47ac10b-58cc-4372-4567-0e02b2c3d479", 4, Reserved, true},
  45. {"f47ac10b-58cc-4372-5567-0e02b2c3d479", 4, Reserved, true},
  46. {"f47ac10b-58cc-4372-6567-0e02b2c3d479", 4, Reserved, true},
  47. {"f47ac10b-58cc-4372-7567-0e02b2c3d479", 4, Reserved, true},
  48. {"f47ac10b-58cc-4372-8567-0e02b2c3d479", 4, RFC4122, true},
  49. {"f47ac10b-58cc-4372-9567-0e02b2c3d479", 4, RFC4122, true},
  50. {"f47ac10b-58cc-4372-a567-0e02b2c3d479", 4, RFC4122, true},
  51. {"f47ac10b-58cc-4372-b567-0e02b2c3d479", 4, RFC4122, true},
  52. {"f47ac10b-58cc-4372-c567-0e02b2c3d479", 4, Microsoft, true},
  53. {"f47ac10b-58cc-4372-d567-0e02b2c3d479", 4, Microsoft, true},
  54. {"f47ac10b-58cc-4372-e567-0e02b2c3d479", 4, Future, true},
  55. {"f47ac10b-58cc-4372-f567-0e02b2c3d479", 4, Future, true},
  56. {"f47ac10b158cc-5372-a567-0e02b2c3d479", 0, Invalid, false},
  57. {"f47ac10b-58cc25372-a567-0e02b2c3d479", 0, Invalid, false},
  58. {"f47ac10b-58cc-53723a567-0e02b2c3d479", 0, Invalid, false},
  59. {"f47ac10b-58cc-5372-a56740e02b2c3d479", 0, Invalid, false},
  60. {"f47ac10b-58cc-5372-a567-0e02-2c3d479", 0, Invalid, false},
  61. {"g47ac10b-58cc-4372-a567-0e02b2c3d479", 0, Invalid, false},
  62. }
  63. var constants = []struct {
  64. c interface{}
  65. name string
  66. }{
  67. {Person, "Person"},
  68. {Group, "Group"},
  69. {Org, "Org"},
  70. {Invalid, "Invalid"},
  71. {RFC4122, "RFC4122"},
  72. {Reserved, "Reserved"},
  73. {Microsoft, "Microsoft"},
  74. {Future, "Future"},
  75. {Domain(17), "Domain17"},
  76. {Variant(42), "BadVariant42"},
  77. }
  78. func testTest(t *testing.T, in string, tt test) {
  79. uuid, err := Parse(in)
  80. if ok := (err == nil); ok != tt.isuuid {
  81. t.Errorf("Parse(%s) got %v expected %v\b", in, ok, tt.isuuid)
  82. }
  83. if err != nil {
  84. return
  85. }
  86. if v := uuid.Variant(); v != tt.variant {
  87. t.Errorf("Variant(%s) got %d expected %d\b", in, v, tt.variant)
  88. }
  89. if v := uuid.Version(); v != tt.version {
  90. t.Errorf("Version(%s) got %d expected %d\b", in, v, tt.version)
  91. }
  92. }
  93. func testBytes(t *testing.T, in []byte, tt test) {
  94. uuid, err := ParseBytes(in)
  95. if ok := (err == nil); ok != tt.isuuid {
  96. t.Errorf("ParseBytes(%s) got %v expected %v\b", in, ok, tt.isuuid)
  97. }
  98. if err != nil {
  99. return
  100. }
  101. suuid, _ := Parse(string(in))
  102. if uuid != suuid {
  103. t.Errorf("ParseBytes(%s) got %v expected %v\b", in, uuid, suuid)
  104. }
  105. }
  106. func TestUUID(t *testing.T) {
  107. for _, tt := range tests {
  108. testTest(t, tt.in, tt)
  109. testTest(t, strings.ToUpper(tt.in), tt)
  110. testBytes(t, []byte(tt.in), tt)
  111. }
  112. }
  113. func TestFromBytes(t *testing.T) {
  114. b := []byte{
  115. 0x7d, 0x44, 0x48, 0x40,
  116. 0x9d, 0xc0,
  117. 0x11, 0xd1,
  118. 0xb2, 0x45,
  119. 0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
  120. }
  121. uuid, err := FromBytes(b)
  122. if err != nil {
  123. t.Fatalf("%s", err)
  124. }
  125. for i := 0; i < len(uuid); i++ {
  126. if b[i] != uuid[i] {
  127. t.Fatalf("FromBytes() got %v expected %v\b", uuid[:], b)
  128. }
  129. }
  130. }
  131. func TestConstants(t *testing.T) {
  132. for x, tt := range constants {
  133. v, ok := tt.c.(fmt.Stringer)
  134. if !ok {
  135. t.Errorf("%x: %v: not a stringer", x, v)
  136. } else if s := v.String(); s != tt.name {
  137. v, _ := tt.c.(int)
  138. t.Errorf("%x: Constant %T:%d gives %q, expected %q", x, tt.c, v, s, tt.name)
  139. }
  140. }
  141. }
  142. func TestRandomUUID(t *testing.T) {
  143. m := make(map[string]bool)
  144. for x := 1; x < 32; x++ {
  145. uuid := New()
  146. s := uuid.String()
  147. if m[s] {
  148. t.Errorf("NewRandom returned duplicated UUID %s", s)
  149. }
  150. m[s] = true
  151. if v := uuid.Version(); v != 4 {
  152. t.Errorf("Random UUID of version %s", v)
  153. }
  154. if uuid.Variant() != RFC4122 {
  155. t.Errorf("Random UUID is variant %d", uuid.Variant())
  156. }
  157. }
  158. }
  159. func TestNew(t *testing.T) {
  160. m := make(map[UUID]bool)
  161. for x := 1; x < 32; x++ {
  162. s := New()
  163. if m[s] {
  164. t.Errorf("New returned duplicated UUID %s", s)
  165. }
  166. m[s] = true
  167. uuid, err := Parse(s.String())
  168. if err != nil {
  169. t.Errorf("New.String() returned %q which does not decode", s)
  170. continue
  171. }
  172. if v := uuid.Version(); v != 4 {
  173. t.Errorf("Random UUID of version %s", v)
  174. }
  175. if uuid.Variant() != RFC4122 {
  176. t.Errorf("Random UUID is variant %d", uuid.Variant())
  177. }
  178. }
  179. }
  180. func TestClockSeq(t *testing.T) {
  181. // Fake time.Now for this test to return a monotonically advancing time; restore it at end.
  182. defer func(orig func() time.Time) { timeNow = orig }(timeNow)
  183. monTime := time.Now()
  184. timeNow = func() time.Time {
  185. monTime = monTime.Add(1 * time.Second)
  186. return monTime
  187. }
  188. SetClockSequence(-1)
  189. uuid1, err := NewUUID()
  190. if err != nil {
  191. t.Fatalf("could not create UUID: %v", err)
  192. }
  193. uuid2, err := NewUUID()
  194. if err != nil {
  195. t.Fatalf("could not create UUID: %v", err)
  196. }
  197. if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 != s2 {
  198. t.Errorf("clock sequence %d != %d", s1, s2)
  199. }
  200. SetClockSequence(-1)
  201. uuid2, err = NewUUID()
  202. if err != nil {
  203. t.Fatalf("could not create UUID: %v", err)
  204. }
  205. // Just on the very off chance we generated the same sequence
  206. // two times we try again.
  207. if uuid1.ClockSequence() == uuid2.ClockSequence() {
  208. SetClockSequence(-1)
  209. uuid2, err = NewUUID()
  210. if err != nil {
  211. t.Fatalf("could not create UUID: %v", err)
  212. }
  213. }
  214. if s1, s2 := uuid1.ClockSequence(), uuid2.ClockSequence(); s1 == s2 {
  215. t.Errorf("Duplicate clock sequence %d", s1)
  216. }
  217. SetClockSequence(0x1234)
  218. uuid1, err = NewUUID()
  219. if err != nil {
  220. t.Fatalf("could not create UUID: %v", err)
  221. }
  222. if seq := uuid1.ClockSequence(); seq != 0x1234 {
  223. t.Errorf("%s: expected seq 0x1234 got 0x%04x", uuid1, seq)
  224. }
  225. }
  226. func TestCoding(t *testing.T) {
  227. text := "7d444840-9dc0-11d1-b245-5ffdce74fad2"
  228. urn := "urn:uuid:7d444840-9dc0-11d1-b245-5ffdce74fad2"
  229. data := UUID{
  230. 0x7d, 0x44, 0x48, 0x40,
  231. 0x9d, 0xc0,
  232. 0x11, 0xd1,
  233. 0xb2, 0x45,
  234. 0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2,
  235. }
  236. if v := data.String(); v != text {
  237. t.Errorf("%x: encoded to %s, expected %s", data, v, text)
  238. }
  239. if v := data.URN(); v != urn {
  240. t.Errorf("%x: urn is %s, expected %s", data, v, urn)
  241. }
  242. uuid, err := Parse(text)
  243. if err != nil {
  244. t.Errorf("Parse returned unexpected error %v", err)
  245. }
  246. if data != uuid {
  247. t.Errorf("%s: decoded to %s, expected %s", text, uuid, data)
  248. }
  249. }
  250. func TestVersion1(t *testing.T) {
  251. uuid1, err := NewUUID()
  252. if err != nil {
  253. t.Fatalf("could not create UUID: %v", err)
  254. }
  255. uuid2, err := NewUUID()
  256. if err != nil {
  257. t.Fatalf("could not create UUID: %v", err)
  258. }
  259. if uuid1 == uuid2 {
  260. t.Errorf("%s:duplicate uuid", uuid1)
  261. }
  262. if v := uuid1.Version(); v != 1 {
  263. t.Errorf("%s: version %s expected 1", uuid1, v)
  264. }
  265. if v := uuid2.Version(); v != 1 {
  266. t.Errorf("%s: version %s expected 1", uuid2, v)
  267. }
  268. n1 := uuid1.NodeID()
  269. n2 := uuid2.NodeID()
  270. if !bytes.Equal(n1, n2) {
  271. t.Errorf("Different nodes %x != %x", n1, n2)
  272. }
  273. t1 := uuid1.Time()
  274. t2 := uuid2.Time()
  275. q1 := uuid1.ClockSequence()
  276. q2 := uuid2.ClockSequence()
  277. switch {
  278. case t1 == t2 && q1 == q2:
  279. t.Error("time stopped")
  280. case t1 > t2 && q1 == q2:
  281. t.Error("time reversed")
  282. case t1 < t2 && q1 != q2:
  283. t.Error("clock sequence changed unexpectedly")
  284. }
  285. }
  286. func TestNode(t *testing.T) {
  287. // This test is mostly to make sure we don't leave nodeMu locked.
  288. ifname = ""
  289. if ni := NodeInterface(); ni != "" {
  290. t.Errorf("NodeInterface got %q, want %q", ni, "")
  291. }
  292. if SetNodeInterface("xyzzy") {
  293. t.Error("SetNodeInterface succeeded on a bad interface name")
  294. }
  295. if !SetNodeInterface("") {
  296. t.Error("SetNodeInterface failed")
  297. }
  298. if runtime.GOARCH != "js" {
  299. if ni := NodeInterface(); ni == "" {
  300. t.Error("NodeInterface returned an empty string")
  301. }
  302. }
  303. ni := NodeID()
  304. if len(ni) != 6 {
  305. t.Errorf("ni got %d bytes, want 6", len(ni))
  306. }
  307. hasData := false
  308. for _, b := range ni {
  309. if b != 0 {
  310. hasData = true
  311. }
  312. }
  313. if !hasData {
  314. t.Error("nodeid is all zeros")
  315. }
  316. id := []byte{1, 2, 3, 4, 5, 6, 7, 8}
  317. SetNodeID(id)
  318. ni = NodeID()
  319. if !bytes.Equal(ni, id[:6]) {
  320. t.Errorf("got nodeid %v, want %v", ni, id[:6])
  321. }
  322. if ni := NodeInterface(); ni != "user" {
  323. t.Errorf("got interface %q, want %q", ni, "user")
  324. }
  325. }
  326. func TestNodeAndTime(t *testing.T) {
  327. // Time is February 5, 1998 12:30:23.136364800 AM GMT
  328. uuid, err := Parse("7d444840-9dc0-11d1-b245-5ffdce74fad2")
  329. if err != nil {
  330. t.Fatalf("Parser returned unexpected error %v", err)
  331. }
  332. node := []byte{0x5f, 0xfd, 0xce, 0x74, 0xfa, 0xd2}
  333. ts := uuid.Time()
  334. c := time.Unix(ts.UnixTime())
  335. want := time.Date(1998, 2, 5, 0, 30, 23, 136364800, time.UTC)
  336. if !c.Equal(want) {
  337. t.Errorf("Got time %v, want %v", c, want)
  338. }
  339. if !bytes.Equal(node, uuid.NodeID()) {
  340. t.Errorf("Expected node %v got %v", node, uuid.NodeID())
  341. }
  342. }
  343. func TestMD5(t *testing.T) {
  344. uuid := NewMD5(NameSpaceDNS, []byte("python.org")).String()
  345. want := "6fa459ea-ee8a-3ca4-894e-db77e160355e"
  346. if uuid != want {
  347. t.Errorf("MD5: got %q expected %q", uuid, want)
  348. }
  349. }
  350. func TestSHA1(t *testing.T) {
  351. uuid := NewSHA1(NameSpaceDNS, []byte("python.org")).String()
  352. want := "886313e1-3b8a-5372-9b90-0c9aee199e5d"
  353. if uuid != want {
  354. t.Errorf("SHA1: got %q expected %q", uuid, want)
  355. }
  356. }
  357. func TestNodeID(t *testing.T) {
  358. nid := []byte{1, 2, 3, 4, 5, 6}
  359. SetNodeInterface("")
  360. s := NodeInterface()
  361. if runtime.GOARCH != "js" {
  362. if s == "" || s == "user" {
  363. t.Errorf("NodeInterface %q after SetInterface", s)
  364. }
  365. }
  366. node1 := NodeID()
  367. if node1 == nil {
  368. t.Error("NodeID nil after SetNodeInterface", s)
  369. }
  370. SetNodeID(nid)
  371. s = NodeInterface()
  372. if s != "user" {
  373. t.Errorf("Expected NodeInterface %q got %q", "user", s)
  374. }
  375. node2 := NodeID()
  376. if node2 == nil {
  377. t.Error("NodeID nil after SetNodeID", s)
  378. }
  379. if bytes.Equal(node1, node2) {
  380. t.Error("NodeID not changed after SetNodeID", s)
  381. } else if !bytes.Equal(nid, node2) {
  382. t.Errorf("NodeID is %x, expected %x", node2, nid)
  383. }
  384. }
  385. func testDCE(t *testing.T, name string, uuid UUID, err error, domain Domain, id uint32) {
  386. if err != nil {
  387. t.Errorf("%s failed: %v", name, err)
  388. return
  389. }
  390. if v := uuid.Version(); v != 2 {
  391. t.Errorf("%s: %s: expected version 2, got %s", name, uuid, v)
  392. return
  393. }
  394. if v := uuid.Domain(); v != domain {
  395. t.Errorf("%s: %s: expected domain %d, got %d", name, uuid, domain, v)
  396. }
  397. if v := uuid.ID(); v != id {
  398. t.Errorf("%s: %s: expected id %d, got %d", name, uuid, id, v)
  399. }
  400. }
  401. func TestDCE(t *testing.T) {
  402. uuid, err := NewDCESecurity(42, 12345678)
  403. testDCE(t, "NewDCESecurity", uuid, err, 42, 12345678)
  404. uuid, err = NewDCEPerson()
  405. testDCE(t, "NewDCEPerson", uuid, err, Person, uint32(os.Getuid()))
  406. uuid, err = NewDCEGroup()
  407. testDCE(t, "NewDCEGroup", uuid, err, Group, uint32(os.Getgid()))
  408. }
  409. type badRand struct{}
  410. func (r badRand) Read(buf []byte) (int, error) {
  411. for i := range buf {
  412. buf[i] = byte(i)
  413. }
  414. return len(buf), nil
  415. }
  416. func TestBadRand(t *testing.T) {
  417. SetRand(badRand{})
  418. uuid1 := New()
  419. uuid2 := New()
  420. if uuid1 != uuid2 {
  421. t.Errorf("expected duplicates, got %q and %q", uuid1, uuid2)
  422. }
  423. SetRand(nil)
  424. uuid1 = New()
  425. uuid2 = New()
  426. if uuid1 == uuid2 {
  427. t.Errorf("unexpected duplicates, got %q", uuid1)
  428. }
  429. }
  430. var asString = "f47ac10b-58cc-0372-8567-0e02b2c3d479"
  431. var asBytes = []byte(asString)
  432. func BenchmarkParse(b *testing.B) {
  433. for i := 0; i < b.N; i++ {
  434. _, err := Parse(asString)
  435. if err != nil {
  436. b.Fatal(err)
  437. }
  438. }
  439. }
  440. func BenchmarkParseBytes(b *testing.B) {
  441. for i := 0; i < b.N; i++ {
  442. _, err := ParseBytes(asBytes)
  443. if err != nil {
  444. b.Fatal(err)
  445. }
  446. }
  447. }
  448. // parseBytesUnsafe is to benchmark using unsafe.
  449. func parseBytesUnsafe(b []byte) (UUID, error) {
  450. return Parse(*(*string)(unsafe.Pointer(&b)))
  451. }
  452. func BenchmarkParseBytesUnsafe(b *testing.B) {
  453. for i := 0; i < b.N; i++ {
  454. _, err := parseBytesUnsafe(asBytes)
  455. if err != nil {
  456. b.Fatal(err)
  457. }
  458. }
  459. }
  460. // parseBytesCopy is to benchmark not using unsafe.
  461. func parseBytesCopy(b []byte) (UUID, error) {
  462. return Parse(string(b))
  463. }
  464. func BenchmarkParseBytesCopy(b *testing.B) {
  465. for i := 0; i < b.N; i++ {
  466. _, err := parseBytesCopy(asBytes)
  467. if err != nil {
  468. b.Fatal(err)
  469. }
  470. }
  471. }
  472. func BenchmarkNew(b *testing.B) {
  473. for i := 0; i < b.N; i++ {
  474. New()
  475. }
  476. }
  477. func BenchmarkUUID_String(b *testing.B) {
  478. uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
  479. if err != nil {
  480. b.Fatal(err)
  481. }
  482. for i := 0; i < b.N; i++ {
  483. if uuid.String() == "" {
  484. b.Fatal("invalid uuid")
  485. }
  486. }
  487. }
  488. func BenchmarkUUID_URN(b *testing.B) {
  489. uuid, err := Parse("f47ac10b-58cc-0372-8567-0e02b2c3d479")
  490. if err != nil {
  491. b.Fatal(err)
  492. }
  493. for i := 0; i < b.N; i++ {
  494. if uuid.URN() == "" {
  495. b.Fatal("invalid uuid")
  496. }
  497. }
  498. }