1
0
This commit is contained in:
Arpad Ryszka 2025-09-03 23:52:33 +02:00
parent 78886422e8
commit c27b9c2daa
6 changed files with 223 additions and 0 deletions

View File

@ -7,6 +7,8 @@ import (
"sort" "sort"
"strings" "strings"
"testing" "testing"
"time"
"fmt"
) )
func TestField(t *testing.T) { func TestField(t *testing.T) {
@ -136,6 +138,41 @@ func TestField(t *testing.T) {
t.Fatal() t.Fatal()
} }
}) })
t.Run("field types", func(t *testing.T) {
type s struct {
B bool
I int
U uint
F float64
S string
D time.Duration
T time.Time
A any
}
f := bind.Fields[s]()
if len(f) != 8 {
t.Fatal(notation.Sprint(f))
}
check := map[string]bind.FieldType {
"b": bind.Bool,
"i": bind.Int,
"u": bind.Uint,
"f": bind.Float64,
"s": bind.String,
"d": bind.Duration,
"t": bind.Time,
"a": bind.Any,
}
for _, fi := range f {
if fi.Type() != check[fi.Name()] {
t.Fatal()
}
}
})
}) })
t.Run("field values", func(t *testing.T) { t.Run("field values", func(t *testing.T) {
@ -868,6 +905,17 @@ func TestField(t *testing.T) {
t.Fatal() t.Fatal()
} }
}) })
t.Run("unpack interfaces", func(t *testing.T) {
type s struct{Foo time.Duration}
var v s
var str fmt.Stringer
str = time.Second
u := bind.BindFields(&v, bind.NamedValue("foo", &str))
if len(u) != 0 || v.Foo != time.Second {
t.Fatal()
}
})
}) })
t.Run("bind fields create", func(t *testing.T) { t.Run("bind fields create", func(t *testing.T) {

1
lib.go
View File

@ -21,6 +21,7 @@ const (
Uintptr FieldType = reflect.Uintptr Uintptr FieldType = reflect.Uintptr
Float32 FieldType = reflect.Float32 Float32 FieldType = reflect.Float32
Float64 FieldType = reflect.Float64 Float64 FieldType = reflect.Float64
String FieldType = reflect.String
Any FieldType = reflect.Interface Any FieldType = reflect.Interface
Struct FieldType = reflect.Struct Struct FieldType = reflect.Struct
Duration FieldType = 0xfffe Duration FieldType = 0xfffe

94
lib_test.go Normal file
View File

@ -0,0 +1,94 @@
package bind_test
import (
"testing"
"code.squareroundforest.org/arpio/bind"
)
func TestLib(t *testing.T) {
t.Run("field", func(t *testing.T) {
t.Run("type", func(t *testing.T) {
t.Run("not from input", func(t *testing.T) {
v := struct{Foo int}{42}
f := bind.FieldValues(v)
if len(f) != 1 || f[0].Type() != bind.Int {
t.Fatal()
}
})
t.Run("nil", func(t *testing.T) {
f := bind.NamedValue("foo", nil)
if f.Type() != bind.Any {
t.Fatal()
}
})
t.Run("circular type", func(t *testing.T) {
type p *p
var v p
v = &v
f := bind.NamedValue("foo", v)
if f.Type() != bind.Any {
t.Fatal()
}
})
t.Run("direct", func(t *testing.T) {
f := bind.NamedValue("foo", 42)
if f.Type() != bind.Int {
t.Fatal()
}
})
t.Run("unpacked", func(t *testing.T) {
var v int
f := bind.NamedValue("foo", &v)
if f.Type() != bind.Int {
t.Fatal()
}
})
})
t.Run("name and path", func(t *testing.T) {
t.Run("returns path", func(t *testing.T) {
f := bind.ValueByPath([]string{"Foo", "Bar"}, 42)
p := f.Path()
if len(p) != 2 || p[0] != "Foo" || p[1] != "Bar" {
t.Fatal()
}
})
t.Run("cannot change path", func(t *testing.T) {
f := bind.ValueByPath([]string{"Foo", "Bar"}, 42)
p := f.Path()
p[1] = "Baz"
p = f.Path()
if p[1] != "Bar" {
t.Fatal()
}
})
t.Run("has name", func(t *testing.T) {
f := bind.NamedValue("foo-bar", 42)
if f.Name() != "foo-bar" {
t.Fatal()
}
})
t.Run("has path", func(t *testing.T) {
f := bind.ValueByPath([]string{"Foo", "Bar"}, 42)
if f.Name() != "foo-bar" {
t.Fatal()
}
})
t.Run("no name and no path", func(t *testing.T) {
f := bind.ValueByPath(nil, 42)
if f.Name() != "" {
t.Fatal()
}
})
})
})
}

View File

@ -165,6 +165,13 @@ func TestScalar(t *testing.T) {
} }
}) })
t.Run("nil value and non-nillable receiver", func(t *testing.T) {
var v int
if bind.BindScalar(&v, nil) {
t.Fatal()
}
})
t.Run("nil receiver", func(t *testing.T) { t.Run("nil receiver", func(t *testing.T) {
if bind.BindScalar(nil, 42) { if bind.BindScalar(nil, 42) {
t.Fatal() t.Fatal()

View File

@ -144,4 +144,11 @@ func TestScan(t *testing.T) {
t.Fatal(tim) t.Fatal(tim)
} }
}) })
t.Run("time invalid", func(t *testing.T) {
var tim time.Time
if bind.BindScalar(&tim, "foo") {
t.Fatal()
}
})
} }

View File

@ -357,4 +357,70 @@ func TestTypeChecks(t *testing.T) {
} }
}) })
}) })
t.Run("accept", func(t *testing.T) {
t.Run("scalar", func(t *testing.T) {
t.Run("yes", func(t *testing.T) {
if !bind.AcceptsScalar[int]() {
t.Fatal()
}
})
t.Run("no", func(t *testing.T) {
if bind.AcceptsScalar[chan int]() {
t.Fatal()
}
})
t.Run("circular", func(t *testing.T) {
type p *p
if bind.AcceptsScalar[p]() {
t.Fatal()
}
})
})
t.Run("fields", func(t *testing.T) {
t.Run("yes", func(t *testing.T) {
type s struct{Foo int}
if !bind.AcceptsFields[s]() {
t.Fatal()
}
})
t.Run("no", func(t *testing.T) {
if bind.AcceptsFields[chan int]() {
t.Fatal()
}
})
t.Run("circular", func(t *testing.T) {
type p *p
if bind.AcceptsFields[p]() {
t.Fatal()
}
})
})
t.Run("list", func(t *testing.T) {
t.Run("yes", func(t *testing.T) {
if !bind.AcceptsList[[]int]() {
t.Fatal()
}
})
t.Run("no", func(t *testing.T) {
if bind.AcceptsList[int]() {
t.Fatal()
}
})
t.Run("circular", func(t *testing.T) {
type p *p
if bind.AcceptsList[p]() {
t.Fatal()
}
})
})
})
} }