package helpers_test import ( "sync" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.yandata.net/iod/iod/trustlog-sdk/internal/helpers" ) func TestGetValidator(t *testing.T) { t.Run("返回有效的validator实例", func(t *testing.T) { v := helpers.GetValidator() require.NotNil(t, v, "Validator不应该为nil") }) t.Run("单例模式:多次调用返回同一个实例", func(t *testing.T) { v1 := helpers.GetValidator() v2 := helpers.GetValidator() v3 := helpers.GetValidator() // 使用指针比较,确保是同一个实例 assert.Same(t, v1, v2, "第一次和第二次调用应该返回同一个实例") assert.Same(t, v2, v3, "第二次和第三次调用应该返回同一个实例") assert.Same(t, v1, v3, "第一次和第三次调用应该返回同一个实例") }) t.Run("并发获取validator应该安全", func(t *testing.T) { const concurrency = 100 validators := make([]interface{}, concurrency) var wg sync.WaitGroup wg.Add(concurrency) for i := range concurrency { go func(idx int) { defer wg.Done() v := helpers.GetValidator() // 存储validator实例 validators[idx] = v }(i) } wg.Wait() // 验证所有goroutine获取的是同一个实例 firstValidator := validators[0] for i := 1; i < concurrency; i++ { assert.Same(t, firstValidator, validators[i], "并发调用第%d次获取的validator应该与第一次相同", i) } }) t.Run("validator可以正常工作", func(t *testing.T) { v := helpers.GetValidator() // 测试一个简单的结构体验证 type TestStruct struct { Name string `validate:"required,min=2,max=10"` Email string `validate:"required,email"` Age int `validate:"gte=0,lte=120"` } // 有效的结构体 validData := TestStruct{ Name: "John", Email: "john@example.com", Age: 30, } err := v.Struct(validData) require.NoError(t, err, "有效的数据不应该产生验证错误") // 无效的结构体 - 缺少必填字段 invalidData1 := TestStruct{ Name: "", Age: 30, } err = v.Struct(invalidData1) require.Error(t, err, "缺少必填字段应该产生验证错误") // 无效的结构体 - 字段值超出范围 invalidData2 := TestStruct{ Name: "John", Email: "john@example.com", Age: 150, } err = v.Struct(invalidData2) require.Error(t, err, "年龄超出范围应该产生验证错误") // 无效的结构体 - 邮箱格式错误 invalidData3 := TestStruct{ Name: "John", Email: "invalid-email", Age: 30, } err = v.Struct(invalidData3) assert.Error(t, err, "无效的邮箱格式应该产生验证错误") }) } func TestGetValidator_InitializationOnce(t *testing.T) { // 这个测试验证 sync.Once 确保初始化只执行一次 const calls = 1000 var wg sync.WaitGroup wg.Add(calls) results := make([]interface{}, calls) for i := range calls { go func(idx int) { defer wg.Done() v := helpers.GetValidator() results[idx] = v }(i) } wg.Wait() // 所有结果应该指向同一个实例 first := results[0] for i := 1; i < calls; i++ { assert.Same(t, first, results[i], "所有调用应该返回完全相同的validator实例") } } func TestGetValidator_ValidatorFunctionality(t *testing.T) { v := helpers.GetValidator() tests := []struct { name string data interface{} wantErr bool }{ { name: "结构体字段验证-成功", data: struct { Field string `validate:"required"` }{ Field: "value", }, wantErr: false, }, { name: "结构体字段验证-失败", data: struct { Field string `validate:"required"` }{ Field: "", }, wantErr: true, }, { name: "数字范围验证-成功", data: struct { Count int `validate:"min=1,max=100"` }{ Count: 50, }, wantErr: false, }, { name: "数字范围验证-失败", data: struct { Count int `validate:"min=1,max=100"` }{ Count: 200, }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := v.Struct(tt.data) if tt.wantErr { assert.Error(t, err) } else { assert.NoError(t, err) } }) } }