2025-08-27 21:03:25 +02:00
|
|
|
package bind_test
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"code.squareroundforest.org/arpio/bind"
|
2025-09-05 23:33:19 +02:00
|
|
|
"fmt"
|
2025-08-28 05:04:06 +02:00
|
|
|
"testing"
|
2025-08-31 01:23:21 +02:00
|
|
|
"time"
|
2025-08-27 21:03:25 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func TestScan(t *testing.T) {
|
|
|
|
|
t.Run("conversion", func(t *testing.T) {
|
|
|
|
|
var i64 int64
|
|
|
|
|
i := 42
|
|
|
|
|
bind.BindScalar(&i64, i)
|
|
|
|
|
if i64 != 42 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("unscannable", func(t *testing.T) {
|
|
|
|
|
var s string
|
|
|
|
|
if bind.BindScalar(&s, func() string { return "" }) {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("bool", func(t *testing.T) {
|
|
|
|
|
var b bool
|
|
|
|
|
if !bind.BindScalar(&b, "true") || !b {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("int", func(t *testing.T) {
|
|
|
|
|
var i int
|
|
|
|
|
if !bind.BindScalar(&i, "42") || i != 42 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("int sized", func(t *testing.T) {
|
|
|
|
|
var i int8
|
|
|
|
|
if !bind.BindScalar(&i, "42") || i != 42 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("uint", func(t *testing.T) {
|
|
|
|
|
var i uint
|
|
|
|
|
if !bind.BindScalar(&i, "42") || i != 42 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("uint sized", func(t *testing.T) {
|
|
|
|
|
var i uint8
|
|
|
|
|
if !bind.BindScalar(&i, "42") || i != 42 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("binary", func(t *testing.T) {
|
|
|
|
|
var i int
|
|
|
|
|
if !bind.BindScalar(&i, "0b101010") || i != 42 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("octal", func(t *testing.T) {
|
|
|
|
|
var i int
|
|
|
|
|
if !bind.BindScalar(&i, "052") || i != 42 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("hexa", func(t *testing.T) {
|
|
|
|
|
var i int
|
|
|
|
|
if !bind.BindScalar(&i, "0x2a") || i != 42 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("num parse failing", func(t *testing.T) {
|
|
|
|
|
i := 21
|
|
|
|
|
if bind.BindScalar(&i, "foo") || i != 21 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("float", func(t *testing.T) {
|
|
|
|
|
var f float64
|
|
|
|
|
if !bind.BindScalar(&f, "2.41") || f != 2.41 {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("string", func(t *testing.T) {
|
|
|
|
|
var s string
|
|
|
|
|
if !bind.BindScalar(&s, "foo bar baz") || s != "foo bar baz" {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("interface", func(t *testing.T) {
|
|
|
|
|
var i any
|
|
|
|
|
if !bind.BindScalar(&i, "foo bar baz") || i != "foo bar baz" {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
2025-08-31 01:23:21 +02:00
|
|
|
|
|
|
|
|
t.Run("duration", func(t *testing.T) {
|
|
|
|
|
var d time.Duration
|
|
|
|
|
if !bind.BindScalar(&d, "9s") || d != 9*time.Second {
|
|
|
|
|
t.Fatal(d)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("duration convert", func(t *testing.T) {
|
2025-09-03 22:12:13 +02:00
|
|
|
// not supported, otherwise any integer field would become convertible:
|
2025-08-31 01:23:21 +02:00
|
|
|
type dur time.Duration
|
|
|
|
|
var d dur
|
2025-09-03 22:12:13 +02:00
|
|
|
if bind.BindScalar(&d, "9s") {
|
2025-08-31 01:23:21 +02:00
|
|
|
t.Fatal(d)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("time rfc", func(t *testing.T) {
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if !bind.BindScalar(&tim, "2025-08-31T01:14:55+02:00") || tim.Year() != 2025 {
|
|
|
|
|
t.Fatal(tim)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("time only", func(t *testing.T) {
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if !bind.BindScalar(&tim, "01:14:55") || tim.Second() != 55 {
|
|
|
|
|
t.Fatal(tim)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("time convert", func(t *testing.T) {
|
|
|
|
|
type timey time.Time
|
|
|
|
|
var tim timey
|
|
|
|
|
if !bind.BindScalar(&tim, "2025-08-31T01:14:55+02:00") || time.Time(tim).Year() != 2025 {
|
|
|
|
|
t.Fatal(tim)
|
|
|
|
|
}
|
|
|
|
|
})
|
2025-09-03 23:52:33 +02:00
|
|
|
|
2025-09-05 23:33:19 +02:00
|
|
|
t.Run("time from int", func(t *testing.T) {
|
|
|
|
|
const timestamp = 1757097011
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if !bind.BindScalar(&tim, timestamp) || !tim.Equal(time.Unix(timestamp, 0)) {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("time from float", func(t *testing.T) {
|
|
|
|
|
const (
|
|
|
|
|
seconds = 1757097011
|
|
|
|
|
nanoseconds = 33000
|
|
|
|
|
timestamp = float64(1757097011.000033)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if !bind.BindScalar(&tim, timestamp) || tim.Unix() != seconds {
|
|
|
|
|
t.Fatal(tim, tim.Unix(), tim.UnixNano())
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("time from int string", func(t *testing.T) {
|
|
|
|
|
const seconds = 1757097011
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if !bind.BindScalar(&tim, fmt.Sprint(seconds)) || tim.Unix() != seconds {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("time from float string", func(t *testing.T) {
|
|
|
|
|
const (
|
|
|
|
|
seconds = 1757097011
|
|
|
|
|
nanoseconds = 33000
|
|
|
|
|
s = "1757097011.000033"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if !bind.BindScalar(&tim, s) || tim.Unix() != seconds || tim.Nanosecond() != nanoseconds {
|
|
|
|
|
t.Fatal(tim.Unix(), tim.Nanosecond())
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("time from invalid float string", func(t *testing.T) {
|
|
|
|
|
t.Run("multiple decimal points", func(t *testing.T) {
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if bind.BindScalar(&tim, "24.235.23") {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("invalid round part", func(t *testing.T) {
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if bind.BindScalar(&tim, "89s.01") {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("invalid fractional part", func(t *testing.T) {
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if bind.BindScalar(&tim, "89.01s") {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
2025-09-03 23:52:33 +02:00
|
|
|
t.Run("time invalid", func(t *testing.T) {
|
|
|
|
|
var tim time.Time
|
|
|
|
|
if bind.BindScalar(&tim, "foo") {
|
|
|
|
|
t.Fatal()
|
|
|
|
|
}
|
|
|
|
|
})
|
2025-08-27 21:03:25 +02:00
|
|
|
}
|