refactor: 重构trustlog-sdk目录结构到trustlog/go-trustlog

- 将所有trustlog-sdk文件移动到trustlog/go-trustlog/目录
- 更新README中所有import路径从trustlog-sdk改为go-trustlog
- 更新cookiecutter配置文件中的项目名称
- 更新根目录.lefthook.yml以引用新位置的配置
- 添加go.sum文件到版本控制
- 删除过时的示例文件

这次重构与trustlog-server保持一致的目录结构,
为未来支持多语言SDK(Python、Java等)预留空间。
This commit is contained in:
ryan
2025-12-22 13:37:57 +08:00
commit d313449c5c
87 changed files with 20622 additions and 0 deletions

View File

@@ -0,0 +1,186 @@
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)
}
})
}
}