uuid_test.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // +build all unit
  2. package gocql
  3. import (
  4. "bytes"
  5. "strings"
  6. "testing"
  7. "time"
  8. )
  9. func TestUUIDNil(t *testing.T) {
  10. var uuid UUID
  11. want, got := "00000000-0000-0000-0000-000000000000", uuid.String()
  12. if want != got {
  13. t.Fatalf("TestNil: expected %q got %q", want, got)
  14. }
  15. }
  16. var testsUUID = []struct {
  17. input string
  18. variant int
  19. version int
  20. }{
  21. {"b4f00409-cef8-4822-802c-deb20704c365", VariantIETF, 4},
  22. {"B4F00409-CEF8-4822-802C-DEB20704C365", VariantIETF, 4}, //Use capital letters
  23. {"f81d4fae-7dec-11d0-a765-00a0c91e6bf6", VariantIETF, 1},
  24. {"00000000-7dec-11d0-a765-00a0c91e6bf6", VariantIETF, 1},
  25. {"3051a8d7-aea7-1801-e0bf-bc539dd60cf3", VariantFuture, 1},
  26. {"3051a8d7-aea7-2801-e0bf-bc539dd60cf3", VariantFuture, 2},
  27. {"3051a8d7-aea7-3801-e0bf-bc539dd60cf3", VariantFuture, 3},
  28. {"3051a8d7-aea7-4801-e0bf-bc539dd60cf3", VariantFuture, 4},
  29. {"3051a8d7-aea7-3801-e0bf-bc539dd60cf3", VariantFuture, 5},
  30. {"d0e817e1-e4b1-1801-3fe6-b4b60ccecf9d", VariantNCSCompat, 0},
  31. {"d0e817e1-e4b1-1801-bfe6-b4b60ccecf9d", VariantIETF, 1},
  32. {"d0e817e1-e4b1-1801-dfe6-b4b60ccecf9d", VariantMicrosoft, 0},
  33. {"d0e817e1-e4b1-1801-ffe6-b4b60ccecf9d", VariantFuture, 0},
  34. }
  35. func TestPredefinedUUID(t *testing.T) {
  36. for i := range testsUUID {
  37. uuid, err := ParseUUID(testsUUID[i].input)
  38. if err != nil {
  39. t.Errorf("ParseUUID #%d: %v", i, err)
  40. continue
  41. }
  42. if str := uuid.String(); str != strings.ToLower(testsUUID[i].input) {
  43. t.Errorf("String #%d: expected %q got %q", i, testsUUID[i].input, str)
  44. continue
  45. }
  46. if variant := uuid.Variant(); variant != testsUUID[i].variant {
  47. t.Errorf("Variant #%d: expected %d got %d", i, testsUUID[i].variant, variant)
  48. }
  49. if testsUUID[i].variant == VariantIETF {
  50. if version := uuid.Version(); version != testsUUID[i].version {
  51. t.Errorf("Version #%d: expected %d got %d", i, testsUUID[i].version, version)
  52. }
  53. }
  54. json, err := uuid.MarshalJSON()
  55. if err != nil {
  56. t.Errorf("MarshalJSON #%d: %v", i, err)
  57. }
  58. expectedJson := `"` + strings.ToLower(testsUUID[i].input) + `"`
  59. if string(json) != expectedJson {
  60. t.Errorf("MarshalJSON #%d: expected %v got %v", i, expectedJson, string(json))
  61. }
  62. var unmarshaled UUID
  63. err = unmarshaled.UnmarshalJSON(json)
  64. if err != nil {
  65. t.Errorf("UnmarshalJSON #%d: %v", i, err)
  66. }
  67. if unmarshaled != uuid {
  68. t.Errorf("UnmarshalJSON #%d: expected %v got %v", i, uuid, unmarshaled)
  69. }
  70. }
  71. }
  72. func TestInvalidUUIDCharacter(t *testing.T) {
  73. _, err := ParseUUID("z4f00409-cef8-4822-802c-deb20704c365")
  74. if err == nil || !strings.Contains(err.Error(), "invalid UUID") {
  75. t.Fatalf("expected invalid UUID error, got '%v' ", err)
  76. }
  77. }
  78. func TestInvalidUUIDLength(t *testing.T) {
  79. _, err := ParseUUID("4f00")
  80. if err == nil || !strings.Contains(err.Error(), "invalid UUID") {
  81. t.Fatalf("expected invalid UUID error, got '%v' ", err)
  82. }
  83. _, err = UUIDFromBytes(TimeUUID().Bytes()[:15])
  84. if err == nil || err.Error() != "UUIDs must be exactly 16 bytes long" {
  85. t.Fatalf("expected error '%v', got '%v'", "UUIDs must be exactly 16 bytes long", err)
  86. }
  87. }
  88. func TestRandomUUID(t *testing.T) {
  89. for i := 0; i < 20; i++ {
  90. uuid, err := RandomUUID()
  91. if err != nil {
  92. t.Errorf("RandomUUID: %v", err)
  93. }
  94. if variant := uuid.Variant(); variant != VariantIETF {
  95. t.Errorf("wrong variant. expected %d got %d", VariantIETF, variant)
  96. }
  97. if version := uuid.Version(); version != 4 {
  98. t.Errorf("wrong version. expected %d got %d", 4, version)
  99. }
  100. }
  101. }
  102. func TestRandomUUIDInvalidAPICalls(t *testing.T) {
  103. uuid, err := RandomUUID()
  104. if err != nil {
  105. t.Fatalf("unexpected error %v", err)
  106. }
  107. if node := uuid.Node(); node != nil {
  108. t.Fatalf("expected nil, got %v", node)
  109. }
  110. if stamp := uuid.Timestamp(); stamp != 0 {
  111. t.Fatalf("expceted 0, got %v", stamp)
  112. }
  113. zeroT := time.Time{}
  114. if to := uuid.Time(); to != zeroT {
  115. t.Fatalf("expected %v, got %v", zeroT, to)
  116. }
  117. }
  118. func TestUUIDFromTime(t *testing.T) {
  119. date := time.Date(1982, 5, 5, 12, 34, 56, 400, time.UTC)
  120. uuid := UUIDFromTime(date)
  121. if uuid.Time() != date {
  122. t.Errorf("embedded time incorrect. Expected %v got %v", date, uuid.Time())
  123. }
  124. }
  125. func TestTimeUUIDWith(t *testing.T) {
  126. utcTime := time.Date(1982, 5, 5, 12, 34, 56, 400, time.UTC)
  127. ts := int64(utcTime.Unix()-timeBase)*10000000 + int64(utcTime.Nanosecond()/100)
  128. clockSeq := uint32(0x3FFF) // Max number of clock sequence.
  129. node := [7]byte{0, 1, 2, 3, 4, 5, 6} // The last element should be ignored.
  130. uuid := TimeUUIDWith(ts, clockSeq, node[:])
  131. if got := uuid.Variant(); got != VariantIETF {
  132. t.Errorf("wrong variant. expected %d got %d", VariantIETF, got)
  133. }
  134. if got, want := uuid.Version(), 1; got != want {
  135. t.Errorf("wrong version. Expected %v got %v", want, got)
  136. }
  137. if got := uuid.Timestamp(); got != int64(ts) {
  138. t.Errorf("wrong timestamp. Expected %v got %v", ts, got)
  139. }
  140. if got := uuid.Clock(); uint32(got) != clockSeq {
  141. t.Errorf("wrong clock. expected %v got %v", clockSeq, got)
  142. }
  143. if got, want := uuid.Node(), node[:6]; !bytes.Equal(got, want) {
  144. t.Errorf("wrong node. expected %x, bot %x", want, got)
  145. }
  146. }
  147. func TestParseUUID(t *testing.T) {
  148. uuid, _ := ParseUUID("486f3a88-775b-11e3-ae07-d231feb1dc81")
  149. if uuid.Time() != time.Date(2014, 1, 7, 5, 19, 29, 222516000, time.UTC) {
  150. t.Errorf("Expected date of 1/7/2014 at 5:19:29.222516, got %v", uuid.Time())
  151. }
  152. }
  153. func TestTimeUUID(t *testing.T) {
  154. var node []byte
  155. timestamp := int64(0)
  156. for i := 0; i < 20; i++ {
  157. uuid := TimeUUID()
  158. if variant := uuid.Variant(); variant != VariantIETF {
  159. t.Errorf("wrong variant. expected %d got %d", VariantIETF, variant)
  160. }
  161. if version := uuid.Version(); version != 1 {
  162. t.Errorf("wrong version. expected %d got %d", 1, version)
  163. }
  164. if n := uuid.Node(); !bytes.Equal(n, node) && i > 0 {
  165. t.Errorf("wrong node. expected %x, got %x", node, n)
  166. } else if i == 0 {
  167. node = n
  168. }
  169. ts := uuid.Timestamp()
  170. if ts < timestamp {
  171. t.Errorf("timestamps must grow: timestamp=%v ts=%v", timestamp, ts)
  172. }
  173. timestamp = ts
  174. }
  175. }
  176. func TestUnmarshalJSON(t *testing.T) {
  177. var withHyphens, withoutHypens, tooLong UUID
  178. withHyphens.UnmarshalJSON([]byte(`"486f3a88-775b-11e3-ae07-d231feb1dc81"`))
  179. if withHyphens.Time().Truncate(time.Second) != time.Date(2014, 1, 7, 5, 19, 29, 0, time.UTC) {
  180. t.Errorf("Expected date of 1/7/2014 at 5:19:29, got %v", withHyphens.Time())
  181. }
  182. withoutHypens.UnmarshalJSON([]byte(`"486f3a88775b11e3ae07d231feb1dc81"`))
  183. if withoutHypens.Time().Truncate(time.Second) != time.Date(2014, 1, 7, 5, 19, 29, 0, time.UTC) {
  184. t.Errorf("Expected date of 1/7/2014 at 5:19:29, got %v", withoutHypens.Time())
  185. }
  186. err := tooLong.UnmarshalJSON([]byte(`"486f3a88-775b-11e3-ae07-d231feb1dc81486f3a88"`))
  187. if err == nil {
  188. t.Errorf("no error for invalid JSON UUID")
  189. }
  190. }
  191. func TestMarshalText(t *testing.T) {
  192. u, err := ParseUUID("486f3a88-775b-11e3-ae07-d231feb1dc81")
  193. if err != nil {
  194. t.Fatal(err)
  195. }
  196. text, err := u.MarshalText()
  197. if err != nil {
  198. t.Fatal(err)
  199. }
  200. var u2 UUID
  201. if err := u2.UnmarshalText(text); err != nil {
  202. t.Fatal(err)
  203. }
  204. if u != u2 {
  205. t.Fatalf("uuids not equal after marshalling: before=%s after=%s", u, u2)
  206. }
  207. }
  208. func TestMinTimeUUID(t *testing.T) {
  209. aTime := time.Now()
  210. minTimeUUID := MinTimeUUID(aTime)
  211. ts := aTime.Unix()
  212. tsFromUUID := minTimeUUID.Time().Unix()
  213. if ts != tsFromUUID {
  214. t.Errorf("timestamps are not equal: expected %d, got %d", ts, tsFromUUID)
  215. }
  216. clockFromUUID := minTimeUUID.Clock()
  217. // clear two most significant bits, as they are used for IETF variant
  218. if minClock&0x3FFF != clockFromUUID {
  219. t.Errorf("clocks are not equal: expected %08b, got %08b", minClock&0x3FFF, clockFromUUID)
  220. }
  221. nodeFromUUID := minTimeUUID.Node()
  222. if !bytes.Equal(minNode, nodeFromUUID) {
  223. t.Errorf("nodes are not equal: expected %08b, got %08b", minNode, nodeFromUUID)
  224. }
  225. }
  226. func TestMaxTimeUUID(t *testing.T) {
  227. aTime := time.Now()
  228. maxTimeUUID := MaxTimeUUID(aTime)
  229. ts := aTime.Unix()
  230. tsFromUUID := maxTimeUUID.Time().Unix()
  231. if ts != tsFromUUID {
  232. t.Errorf("timestamps are not equal: expected %d, got %d", ts, tsFromUUID)
  233. }
  234. clockFromUUID := maxTimeUUID.Clock()
  235. if maxClock&0x3FFF != clockFromUUID {
  236. t.Errorf("clocks are not equal: expected %08b, got %08b", maxClock&0x3FFF, clockFromUUID)
  237. }
  238. nodeFromUUID := maxTimeUUID.Node()
  239. if !bytes.Equal(maxNode, nodeFromUUID) {
  240. t.Errorf("nodes are not equal: expected %08b, got %08b", maxNode, nodeFromUUID)
  241. }
  242. }