add builtin.bool test + make other types that allow 'string' allow '[]byte' as well
This commit is contained in:
parent
9affef4cd7
commit
60a1849cf8
|
@ -17,7 +17,28 @@ func (Bool) Checker(typeName string) typecheck.CheckerFunc {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return func(value interface{}) bool {
|
return func(value interface{}) bool {
|
||||||
_, isBool := value.(bool)
|
_, isBool := readBool(value)
|
||||||
return isBool
|
return isBool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readBool tries to read a serialized boolean and returns whether it succeeded.
|
||||||
|
func readBool(value interface{}) (bool, bool) {
|
||||||
|
switch cast := value.(type) {
|
||||||
|
case bool:
|
||||||
|
return cast, true
|
||||||
|
|
||||||
|
case string:
|
||||||
|
strVal := string(cast)
|
||||||
|
return strVal == "true", strVal == "true" || strVal == "false"
|
||||||
|
|
||||||
|
case []byte:
|
||||||
|
strVal := string(cast)
|
||||||
|
return strVal == "true", strVal == "true" || strVal == "false"
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, false
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
package builtin_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.xdrm.io/go/aicra/typecheck/builtin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBool_New(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
inst := interface{}(builtin.NewBool())
|
||||||
|
|
||||||
|
switch cast := inst.(type) {
|
||||||
|
case *builtin.Bool:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
t.Errorf("expect %T ; got %T", &builtin.Bool{}, cast)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBool_AvailableTypes(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
inst := builtin.NewBool()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
Type string
|
||||||
|
Handled bool
|
||||||
|
}{
|
||||||
|
{"bool", true},
|
||||||
|
{"Bool", false},
|
||||||
|
{"boolean", false},
|
||||||
|
{" bool", false},
|
||||||
|
{"bool ", false},
|
||||||
|
{" bool ", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.Type, func(t *testing.T) {
|
||||||
|
checker := inst.Checker(test.Type)
|
||||||
|
if checker == nil {
|
||||||
|
if test.Handled {
|
||||||
|
t.Errorf("expect %q to be handled", test.Type)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !test.Handled {
|
||||||
|
t.Errorf("expect %q NOT to be handled", test.Type)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBool_Values(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
const typeName = "bool"
|
||||||
|
|
||||||
|
checker := builtin.NewBool().Checker(typeName)
|
||||||
|
if checker == nil {
|
||||||
|
t.Errorf("expect %q to be handled", typeName)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
Value interface{}
|
||||||
|
Valid bool
|
||||||
|
}{
|
||||||
|
{true, true},
|
||||||
|
{false, true},
|
||||||
|
{1, false},
|
||||||
|
{0, false},
|
||||||
|
{-1, false},
|
||||||
|
|
||||||
|
// json number
|
||||||
|
{"-1", false},
|
||||||
|
{"0", false},
|
||||||
|
{"1", false},
|
||||||
|
|
||||||
|
// json string
|
||||||
|
{"true", true},
|
||||||
|
{"false", true},
|
||||||
|
{[]byte("true"), true},
|
||||||
|
{[]byte("false"), true},
|
||||||
|
|
||||||
|
{"string", false},
|
||||||
|
{[]byte("bytes"), false},
|
||||||
|
{-0.1, false},
|
||||||
|
{0.1, false},
|
||||||
|
{nil, false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range tests {
|
||||||
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
||||||
|
if checker(test.Value) {
|
||||||
|
if !test.Valid {
|
||||||
|
t.Errorf("expect value to be invalid")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if test.Valid {
|
||||||
|
t.Errorf("expect value to be valid")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -45,6 +45,11 @@ func readFloat(value interface{}) (float64, bool) {
|
||||||
floatVal, err := num.Float64()
|
floatVal, err := num.Float64()
|
||||||
return floatVal, err == nil
|
return floatVal, err == nil
|
||||||
|
|
||||||
|
case []byte:
|
||||||
|
num := json.Number(cast)
|
||||||
|
floatVal, err := num.Float64()
|
||||||
|
return floatVal, err == nil
|
||||||
|
|
||||||
// unknown type
|
// unknown type
|
||||||
default:
|
default:
|
||||||
return 0, false
|
return 0, false
|
||||||
|
|
|
@ -49,6 +49,12 @@ func readInt(value interface{}) (int, bool) {
|
||||||
num := json.Number(cast)
|
num := json.Number(cast)
|
||||||
intVal, err := num.Int64()
|
intVal, err := num.Int64()
|
||||||
return int(intVal), err == nil
|
return int(intVal), err == nil
|
||||||
|
// serialized string -> try to convert to float
|
||||||
|
|
||||||
|
case []byte:
|
||||||
|
num := json.Number(cast)
|
||||||
|
intVal, err := num.Int64()
|
||||||
|
return int(intVal), err == nil
|
||||||
|
|
||||||
// unknown type
|
// unknown type
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -61,6 +61,12 @@ func (s String) Checker(typeName string) typecheck.CheckerFunc {
|
||||||
|
|
||||||
// check type
|
// check type
|
||||||
strValue, isString := value.(string)
|
strValue, isString := value.(string)
|
||||||
|
byteSliceValue, isByteSlice := value.([]byte)
|
||||||
|
if !isString && isByteSlice {
|
||||||
|
strValue = string(byteSliceValue)
|
||||||
|
isString = true
|
||||||
|
}
|
||||||
|
|
||||||
if !isString {
|
if !isString {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,7 @@ func TestString_AnyLength(t *testing.T) {
|
||||||
Valid bool
|
Valid bool
|
||||||
}{
|
}{
|
||||||
{"string", true},
|
{"string", true},
|
||||||
{[]byte("bytes"), false},
|
{[]byte("bytes"), true},
|
||||||
{1, false},
|
{1, false},
|
||||||
{0.1, false},
|
{0.1, false},
|
||||||
{nil, false},
|
{nil, false},
|
||||||
|
|
|
@ -53,6 +53,15 @@ func readUint(value interface{}) (uint, bool) {
|
||||||
overflows := floatVal < 0 || floatVal > math.MaxUint64
|
overflows := floatVal < 0 || floatVal > math.MaxUint64
|
||||||
return uint(floatVal), !overflows
|
return uint(floatVal), !overflows
|
||||||
|
|
||||||
|
case []byte:
|
||||||
|
num := json.Number(cast)
|
||||||
|
floatVal, err := num.Float64()
|
||||||
|
if err != nil {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
overflows := floatVal < 0 || floatVal > math.MaxUint64
|
||||||
|
return uint(floatVal), !overflows
|
||||||
|
|
||||||
// unknown type
|
// unknown type
|
||||||
default:
|
default:
|
||||||
return 0, false
|
return 0, false
|
||||||
|
|
Loading…
Reference in New Issue