id_test.go 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. package id
  2. import (
  3. "strings"
  4. "testing"
  5. "time"
  6. )
  7. // TestNewCanonicalUserID 验证 ULID 生成基本性质(26 位、Crockford、可解码)。
  8. func TestNewCanonicalUserID(t *testing.T) {
  9. uid, err := NewCanonicalUserID()
  10. if err != nil {
  11. t.Fatalf("NewCanonicalUserID 失败: %v", err)
  12. }
  13. if len(uid) != Length {
  14. t.Fatalf("ULID 长度应为 %d,得 %d(%q)", Length, len(uid), uid)
  15. }
  16. if !Validate(uid) {
  17. t.Fatalf("生成的 ULID 应通过 Validate:%q", uid)
  18. }
  19. }
  20. // TestNewCanonicalUserIDAt 验证指定时间戳 + 时间有序性(前 48bit 毫秒时间戳)。
  21. func TestNewCanonicalUserIDAt(t *testing.T) {
  22. base := time.Date(2026, 11, 7, 10, 0, 0, 0, time.UTC)
  23. uidA, err := NewCanonicalUserIDAt(base)
  24. if err != nil {
  25. t.Fatalf("NewCanonicalUserIDAt 失败: %v", err)
  26. }
  27. uidB, err := NewCanonicalUserIDAt(base.Add(2 * time.Second))
  28. if err != nil {
  29. t.Fatalf("NewCanonicalUserIDAt(+2s) 失败: %v", err)
  30. }
  31. // 时间戳后移 → ULID 字典序应更大(前 48bit 时间戳递增)
  32. if !(uidA < uidB) {
  33. t.Errorf("时间有序的 ULID 应满足 uidA(%s) < uidB(%s)", uidA, uidB)
  34. }
  35. }
  36. // TestValidate 校验合法/非法 ULID。
  37. func TestValidate(t *testing.T) {
  38. uid, _ := NewCanonicalUserID()
  39. cases := []struct {
  40. in string
  41. want bool
  42. }{
  43. {uid, true}, // 合法(新生成)
  44. {strings.ToLower(uid), false}, // 小写非法(统一大写)
  45. {"01GAQF0Z6C1V9Y3E5H7K2M8B4T", true}, // 标准样例
  46. {"abc", false}, // 长度不符
  47. {"", false}, // 空
  48. {"01GAQF0Z6C1V9Y3E5H7K2M8B4I", false}, // 含 I(Crockford 剔除)
  49. {"01GAQF0Z6C1V9Y3E5H7K2M8B4L", false}, // 含 L
  50. {"01GAQF0Z6C1V9Y3E5H7K2M8B4O", false}, // 含 O
  51. {"01GAQF0Z6C1V9Y3E5H7K2M8B4U", false}, // 含 U
  52. {"01GAQF0Z6C1V9Y3E5H7K2M8B4T0", false}, // 27 位(长度)
  53. }
  54. for i, c := range cases {
  55. if got := Validate(c.in); got != c.want {
  56. t.Errorf("case %d: Validate(%q)=%v, want %v", i, c.in, got, c.want)
  57. }
  58. }
  59. }
  60. // TestNewCanonicalUserIDUniqueness 验证并发/批量生成的唯一性(80bit 随机熵)。
  61. func TestNewCanonicalUserIDUniqueness(t *testing.T) {
  62. seen := make(map[string]struct{}, 1000)
  63. // 同一毫秒内批量生成(随机部分保证唯一)
  64. fixed := time.Date(2026, 11, 7, 8, 0, 0, 0, time.UTC)
  65. for i := 0; i < 1000; i++ {
  66. uid, err := NewCanonicalUserIDAt(fixed)
  67. if err != nil {
  68. t.Fatalf("第 %d 次生成失败: %v", i, err)
  69. }
  70. if _, dup := seen[uid]; dup {
  71. t.Fatalf("第 %d 次生成重复 ULID:%s(随机熵不足)", i, uid)
  72. }
  73. seen[uid] = struct{}{}
  74. }
  75. }