452 lines
8.0 KiB
Go
452 lines
8.0 KiB
Go
package bind_test
|
|
|
|
import (
|
|
"code.squareroundforest.org/arpio/bind"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestTypeChecks(t *testing.T) {
|
|
t.Run("accepts scalar", func(t *testing.T) {
|
|
t.Run("bool", func(t *testing.T) {
|
|
if !bind.AcceptsScalar[bool]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("int", func(t *testing.T) {
|
|
if !bind.AcceptsScalar[int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("uint", func(t *testing.T) {
|
|
if !bind.AcceptsScalar[uint]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("float", func(t *testing.T) {
|
|
if !bind.AcceptsScalar[int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("string", func(t *testing.T) {
|
|
if !bind.AcceptsScalar[bool]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("any", func(t *testing.T) {
|
|
if !bind.AcceptsScalar[any]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("pointer", func(t *testing.T) {
|
|
type p *int
|
|
if !bind.AcceptsScalar[p]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("slice", func(t *testing.T) {
|
|
type s []int
|
|
if !bind.AcceptsScalar[s]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("pointer and slice combined", func(t *testing.T) {
|
|
type c *[]*[]int
|
|
if !bind.AcceptsScalar[c]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("struct", func(t *testing.T) {
|
|
type s struct{ Foo int }
|
|
if bind.AcceptsScalar[s]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("map", func(t *testing.T) {
|
|
if bind.AcceptsScalar[map[string]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("interface with methods", func(t *testing.T) {
|
|
type i interface{ Foo(int) }
|
|
if bind.AcceptsScalar[i]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("func", func(t *testing.T) {
|
|
if bind.AcceptsScalar[func(int)]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("chan", func(t *testing.T) {
|
|
if bind.AcceptsScalar[chan int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("accepts fields", func(t *testing.T) {
|
|
t.Run("struct", func(t *testing.T) {
|
|
type s struct{ Foo int }
|
|
if !bind.AcceptsFields[s]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("map", func(t *testing.T) {
|
|
if !bind.AcceptsFields[map[string]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("map with interface fields", func(t *testing.T) {
|
|
if !bind.AcceptsFields[map[string]any]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("map with list fields", func(t *testing.T) {
|
|
if !bind.AcceptsFields[map[string][]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("pointer", func(t *testing.T) {
|
|
type p *struct{ Foo int }
|
|
if !bind.AcceptsFields[p]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("slice", func(t *testing.T) {
|
|
type s []struct{ Foo int }
|
|
if !bind.AcceptsFields[s]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("pointer and slice combined", func(t *testing.T) {
|
|
type c *[]*[]struct{ Foo int }
|
|
if !bind.AcceptsFields[c]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("wrong map key", func(t *testing.T) {
|
|
if bind.AcceptsFields[map[int]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("wrong map value", func(t *testing.T) {
|
|
if bind.AcceptsFields[map[string]struct{ Foo int }]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("scalar", func(t *testing.T) {
|
|
if bind.AcceptsFields[int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("interface", func(t *testing.T) {
|
|
type i interface{ Foo(int) }
|
|
if bind.AcceptsFields[i]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("any type", func(t *testing.T) {
|
|
if bind.AcceptsFields[any]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("func", func(t *testing.T) {
|
|
if bind.AcceptsFields[func(int)]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("chan", func(t *testing.T) {
|
|
if bind.AcceptsFields[chan int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("accepts list", func(t *testing.T) {
|
|
t.Run("scalars", func(t *testing.T) {
|
|
if !bind.AcceptsList[[]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("structs", func(t *testing.T) {
|
|
if !bind.AcceptsList[[]struct{ Foo int }]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("maps", func(t *testing.T) {
|
|
if !bind.AcceptsList[[]map[string]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("pointer to list", func(t *testing.T) {
|
|
if !bind.AcceptsList[*[]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("scalar", func(t *testing.T) {
|
|
if bind.AcceptsList[int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("struct", func(t *testing.T) {
|
|
if bind.AcceptsList[struct{ Foo int }]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("map", func(t *testing.T) {
|
|
if bind.AcceptsList[map[string]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("map", func(t *testing.T) {
|
|
if bind.AcceptsList[map[string]int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("struct pointer", func(t *testing.T) {
|
|
if bind.AcceptsList[*struct{ Foo int }]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("wrong elem type", func(t *testing.T) {
|
|
if bind.AcceptsList[map[string]struct{ Foo int }]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("bindable", func(t *testing.T) {
|
|
t.Run("scalar", func(t *testing.T) {
|
|
if !bind.Bindable[int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("struct", func(t *testing.T) {
|
|
if !bind.Bindable[struct{ Foo int }]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("func", func(t *testing.T) {
|
|
if bind.Bindable[func()]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("chan", func(t *testing.T) {
|
|
if bind.Bindable[chan int]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("with reflection type", func(t *testing.T) {
|
|
if !bind.BindableType(reflect.TypeFor[int]()) {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("circular type", func(t *testing.T) {
|
|
t.Run("via pointer", func(t *testing.T) {
|
|
type p *p
|
|
if bind.Bindable[p]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("via slice", func(t *testing.T) {
|
|
type s []s
|
|
if bind.Bindable[s]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("pointer via struct field", func(t *testing.T) {
|
|
type s struct{ f *s }
|
|
if bind.Bindable[s]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("slice via struct field", func(t *testing.T) {
|
|
type s struct{ f []s }
|
|
if bind.Bindable[s]() {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
})
|
|
|
|
t.Run("circular reference", func(t *testing.T) {
|
|
t.Run("via pointer", func(t *testing.T) {
|
|
p := new(any)
|
|
*p = p
|
|
if bind.BindScalar(p, "42") {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("via slice", func(t *testing.T) {
|
|
s := make([]any, 1)
|
|
s[0] = s
|
|
if bind.BindScalar(s, "42") {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("via interface and pointer", func(t *testing.T) {
|
|
var v any
|
|
v = &v
|
|
if bind.BindScalar(v, "42") {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("via struct field and pointer", func(t *testing.T) {
|
|
type s struct{ F *s }
|
|
var v s
|
|
v.F = &v
|
|
if len(bind.FieldValues(v)) > 0 {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("via struct field and slice", func(t *testing.T) {
|
|
type s struct{ F []s }
|
|
var v s
|
|
v.F = []s{v}
|
|
if len(bind.FieldValues(v)) > 0 {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
|
|
t.Run("value with circular type", func(t *testing.T) {
|
|
type p *p
|
|
var v p
|
|
if len(bind.FieldValues(v)) > 0 {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
})
|
|
|
|
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("with reflection type", func(t *testing.T) {
|
|
if !bind.TypeAcceptsScalar(reflect.TypeFor[int]()) {
|
|
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("with reflection type", func(t *testing.T) {
|
|
if !bind.TypeAcceptsFields(reflect.TypeFor[struct{ Foo int }]()) {
|
|
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()
|
|
}
|
|
})
|
|
|
|
t.Run("with reflection type", func(t *testing.T) {
|
|
if !bind.TypeAcceptsList(reflect.TypeFor[[]int]()) {
|
|
t.Fatal()
|
|
}
|
|
})
|
|
})
|
|
})
|
|
}
|