cast/bench_test.go
2026-05-09 16:30:01 +08:00

183 lines
3.6 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 cast_test
import (
"math"
"testing"
"apigo.cc/go/cast"
)
// --- 黑盒测试 (Black-box / Edge Cases) ---
func TestEdgeCases(t *testing.T) {
// 1. 极端数值
if cast.Int64(math.MaxInt64) != math.MaxInt64 {
t.Error("MaxInt64 failed")
}
if cast.Float64("1.7976931348623157e+308") == 0 {
t.Error("MaxFloat64 string failed")
}
// 2. 各种非法格式字符串
if cast.Int("abc") != 0 {
t.Error("Invalid string to int should be 0")
}
if cast.Float("1.2.3.4") != 0 {
t.Error("Invalid float string should be 0")
}
if cast.Bool("not_a_bool") != false {
t.Error("Invalid bool string should be false")
}
// 3. 深度嵌套与空指针
var p ***int
if cast.Int(p) != 0 {
t.Error("Deep nil pointer to int failed")
}
// 4. JSON 异常输入
if err := cast.UnmarshalJSON("{invalid_json}", nil); err == nil {
t.Log("UnmarshalJSON handled invalid input")
}
}
// --- 性能测试 (Performance / Benchmarks) ---
func BenchmarkInt(b *testing.B) {
val := "123456"
for i := 0; i < b.N; i++ {
_ = cast.Int(val)
}
}
func BenchmarkIntFromInterface(b *testing.B) {
var val interface{} = 123456
for i := 0; i < b.N; i++ {
_ = cast.Int(val)
}
}
func BenchmarkString(b *testing.B) {
val := 123456.789
for i := 0; i < b.N; i++ {
_ = cast.String(val)
}
}
func BenchmarkJSON(b *testing.B) {
type User struct {
ID int
Name string
}
u := User{ID: 1, Name: "Benchmark User"}
for i := 0; i < b.N; i++ {
_ = cast.To[string](u)
}
}
func BenchmarkIf(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = cast.If(i%2 == 0, "A", "B")
}
}
func BenchmarkSplit(b *testing.B) {
s := " a, b, c, d, e, f, g "
for i := 0; i < b.N; i++ {
_ = cast.Split(s, ",")
}
}
func BenchmarkToMap(b *testing.B) {
m := make(map[string]int)
kv := []any{"a", 1, "b", 2, "c", 3, "d", 4, "e", 5}
b.ResetTimer()
for i := 0; i < b.N; i++ {
cast.FillMap(m, kv)
}
}
func BenchmarkToSlice(b *testing.B) {
m := map[string]int{"a": 1, "b": 2, "c": 3, "d": 4, "e": 5}
var s []any
b.ResetTimer()
for i := 0; i < b.N; i++ {
s = s[:0]
cast.FillSlice(&s, m)
}
}
// 1. 测试 Int 转换的快速路径 (命中 switch case)
func BenchmarkInt_FastPath(b *testing.B) {
val := "123456"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = cast.Int(val)
}
}
// 2. 测试 Int 转换的慢速路径 (退化为反射)
type customInt int
func BenchmarkInt_SlowPath(b *testing.B) {
var val customInt = 123456
b.ResetTimer()
for i := 0; i < b.N; i++ {
// 自定义类型无法命中 switch 的基础类型,会走 reflect.ValueOf
_ = cast.Int(val)
}
}
// 3. 测试 String 转换的快速路径
func BenchmarkString_FastPath(b *testing.B) {
val := 123456.789
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = cast.String(val) // 命中 strconv.FormatFloat极快
}
}
// 4. 测试 ToJSON 性能 (对比自定义逻辑与标准库)
func BenchmarkToJSON_SimpleStruct(b *testing.B) {
type User struct {
ID int
Name string
}
u := User{ID: 1, Name: "Benchmark User"}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = cast.To[string](u)
}
}
// 5. 测试 Goja Map 的清洗性能
func BenchmarkToJSON_DirtyMap(b *testing.B) {
// 模拟恶劣数据:包含 any key 的 map
val := map[any]any{
0: "A",
1: map[any]any{"key": "B"},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = cast.To[string](val)
}
}
func BenchmarkTo_StructToStruct(b *testing.B) {
type Source struct {
ID int
Name string
Age string
}
type Target struct {
ID int64
Name string
Age int
}
src := Source{ID: 1, Name: "Tom", Age: "18"}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = cast.To[Target](src)
}
}