Files
go-utils/id/uuid_test.go
2025-06-14 21:44:33 +08:00

268 lines
6.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package id
import (
"strings"
"sync"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewGUIDv4(t *testing.T) {
// 测试带有连字符的 GUID
withHyphen := NewGUIDv4(true)
assert.NotEmpty(t, withHyphen)
assert.Equal(t, 4, strings.Count(withHyphen, "-"), "GUID 应包含 4 个连字符")
// 测试不带连字符的 GUID
withoutHyphen := NewGUIDv4(false)
assert.NotEmpty(t, withoutHyphen)
assert.Equal(t, 0, strings.Count(withoutHyphen, "-"), "GUID 不应包含连字符")
// 验证 GUID 的长度
assert.Equal(t, 36, len(withHyphen), "带连字符的 GUID 长度应为 36")
assert.Equal(t, 32, len(withoutHyphen), "不带连字符的 GUID 长度应为 32")
}
func TestNewGUIDv4CollisionRate(t *testing.T) {
const (
testCount = 100000 // 测试生成的GUID数量
withHyphen = true // 是否带连字符
)
ids := make(map[string]struct{})
for i := 0; i < testCount; i++ {
id := NewGUIDv4(withHyphen)
if _, exists := ids[id]; exists {
t.Errorf("碰撞发生: %s 已存在", id)
}
ids[id] = struct{}{}
}
t.Logf("生成了 %d 个GUID无碰撞。", testCount)
}
func TestNewShortUUID(t *testing.T) {
// 测试生成的 ShortUUID 是否非空
id := NewShortUUID()
assert.NotEmpty(t, id, "生成的 ShortUUID 应该非空")
// 测试生成的 ShortUUID 的长度是否符合预期
assert.True(t, len(id) > 0, "生成的 ShortUUID 长度应该大于 0")
}
func TestNewShortUUIDCollisionRate(t *testing.T) {
const testCount = 100000 // 测试生成的ShortUUID数量
ids := make(map[string]struct{})
for i := 0; i < testCount; i++ {
id := NewShortUUID()
if _, exists := ids[id]; exists {
t.Errorf("碰撞发生: %s 已存在", id)
}
ids[id] = struct{}{}
}
t.Logf("生成了 %d 个ShortUUID无碰撞。", testCount)
}
func TestNewKSUID(t *testing.T) {
// 测试生成的 KSUID 是否非空
id := NewKSUID()
assert.NotEmpty(t, id, "生成的 KSUID 应该非空")
// 测试生成的 KSUID 的长度是否符合预期
assert.Equal(t, 27, len(id), "生成的 KSUID 长度应该为 27")
}
func TestNewKSUIDCollisionRate(t *testing.T) {
const testCount = 100000 // 测试生成的KSUID数量
ids := make(map[string]struct{})
for i := 0; i < testCount; i++ {
id := NewKSUID()
if _, exists := ids[id]; exists {
t.Errorf("碰撞发生: %s 已存在", id)
}
ids[id] = struct{}{}
}
t.Logf("生成了 %d 个KSUID无碰撞。", testCount)
}
func TestNewXID(t *testing.T) {
// 测试生成的 XID 是否非空
id := NewXID()
assert.NotEmpty(t, id, "生成的 XID 应该非空")
t.Logf("xid: %s", id)
// 测试生成的 XID 的长度是否符合预期
assert.Equal(t, 20, len(id), "生成的 XID 长度应该为 20")
}
func TestNewXIDCollisionRate(t *testing.T) {
const testCount = 100000 // 测试生成的XID数量
ids := make(map[string]struct{})
for i := 0; i < testCount; i++ {
id := NewXID()
if _, exists := ids[id]; exists {
t.Errorf("碰撞发生: %s 已存在", id)
}
ids[id] = struct{}{}
}
t.Logf("生成了 %d 个XID无碰撞。", testCount)
}
func TestNewSnowflakeID(t *testing.T) {
tests := []struct {
workerId int64
expectErr bool
}{
{0, false}, // 有效的 workerId
{31, false}, // 有效的 workerId
{32, false}, // 有效的 workerId
{-1, true}, // 无效的 workerId
}
for _, tt := range tests {
id, err := NewSnowflakeID(tt.workerId)
if (err != nil) != tt.expectErr {
t.Errorf("NewSnowflakeID(%d) 错误状态不符合预期: %v", tt.workerId, err)
}
if err == nil && id <= 0 {
t.Errorf("NewSnowflakeID(%d) 生成的ID无效: %d", tt.workerId, id)
}
t.Logf("NewSnowflakeID(%d) ID: %d", tt.workerId, id)
}
}
func TestNewSnowflakeIDCollisionRate(t *testing.T) {
const (
workerId = 0
testCount = 100000 // 测试生成的ID数量
)
ids := make(map[int64]struct{})
for i := 0; i < testCount; i++ {
id, err := NewSnowflakeID(workerId)
if err != nil {
t.Errorf("生成ID时出现错误: %v", err)
continue
}
if _, exists := ids[id]; exists {
t.Errorf("碰撞发生: %d 已存在", id)
}
ids[id] = struct{}{}
}
t.Logf("生成了 %d 个Snowflake ID无碰撞。", testCount)
}
func TestConcurrentNewSnowflakeIDCollisionRate(t *testing.T) {
const (
workerId = 0 // Snowflake 工作节点 ID
testCount = 100000 // 测试生成的 ID 数量
workerCount = 10 // 并发工作线程数
)
var mu sync.Mutex
ids := make(map[int64]struct{})
var wg sync.WaitGroup
for w := 0; w < workerCount; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < testCount/workerCount; i++ {
id, err := NewSnowflakeID(workerId)
if err != nil {
t.Errorf("生成 Snowflake ID 时出现错误: %v", err)
continue
}
mu.Lock()
if _, exists := ids[id]; exists {
t.Errorf("碰撞发生: %d 已存在", id)
}
ids[id] = struct{}{}
mu.Unlock()
}
}()
}
wg.Wait()
t.Logf("生成了 %d 个 Snowflake ID无碰撞。", testCount)
}
func TestNewSonyflakeID(t *testing.T) {
// 测试生成的 Sonyflake ID 是否有效
id, err := NewSonyflakeID()
t.Logf("sonyflake id: %v", id)
assert.NoError(t, err, "生成 Sonyflake ID 时不应出现错误")
assert.True(t, id > 0, "生成的 Sonyflake ID 应该是正数")
}
func TestNewSonyflakeIDCollisionRate(t *testing.T) {
const testCount = 100000 // 测试生成的 Sonyflake ID 数量
ids := make(map[uint64]struct{})
for i := 0; i < testCount; i++ {
id, err := NewSonyflakeID()
if err != nil {
t.Errorf("生成 Sonyflake ID 时出现错误: %v", err)
continue
}
if _, exists := ids[id]; exists {
t.Errorf("碰撞发生: %d 已存在", id)
}
ids[id] = struct{}{}
}
t.Logf("生成了 %d 个 Sonyflake ID无碰撞。", testCount)
}
func TestConcurrentNewSonyflakeIDCollisionRate(t *testing.T) {
const (
testCount = 100000 // 测试生成的 Sonyflake ID 数量
workerCount = 10 // 并发工作线程数
)
var mu sync.Mutex
ids := make(map[uint64]struct{})
var wg sync.WaitGroup
for w := 0; w < workerCount; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < testCount/workerCount; i++ {
id, err := NewSonyflakeID()
if err != nil {
t.Errorf("生成 Sonyflake ID 时出现错误: %v", err)
continue
}
mu.Lock()
if _, exists := ids[id]; exists {
t.Errorf("碰撞发生: %d 已存在", id)
}
ids[id] = struct{}{}
mu.Unlock()
}
}()
}
wg.Wait()
t.Logf("生成了 %d 个 Sonyflake ID无碰撞。", testCount)
}
func TestNewMongoObjectID(t *testing.T) {
// 测试生成的 ObjectID 是否非空
id := NewMongoObjectID()
assert.NotEmpty(t, id, "生成的 Mongo ObjectID 应该非空")
// 测试生成的 ObjectID 的长度是否符合预期
assert.Equal(t, 36, len(id), "生成的 Mongo ObjectID 长度应该为 36")
}