add builtin.bool test + make other types that allow 'string' allow '[]byte' as well

This commit is contained in:
Adrien Marquès 2019-11-18 16:17:02 +01:00
parent 9affef4cd7
commit 60a1849cf8
7 changed files with 164 additions and 2 deletions

View File

@ -17,7 +17,28 @@ func (Bool) Checker(typeName string) typecheck.CheckerFunc {
return nil
}
return func(value interface{}) bool {
_, isBool := value.(bool)
_, isBool := readBool(value)
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
}

View File

@ -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()
}
})
}
}

View File

@ -45,6 +45,11 @@ func readFloat(value interface{}) (float64, bool) {
floatVal, err := num.Float64()
return floatVal, err == nil
case []byte:
num := json.Number(cast)
floatVal, err := num.Float64()
return floatVal, err == nil
// unknown type
default:
return 0, false

View File

@ -49,6 +49,12 @@ func readInt(value interface{}) (int, bool) {
num := json.Number(cast)
intVal, err := num.Int64()
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
default:

View File

@ -61,6 +61,12 @@ func (s String) Checker(typeName string) typecheck.CheckerFunc {
// check type
strValue, isString := value.(string)
byteSliceValue, isByteSlice := value.([]byte)
if !isString && isByteSlice {
strValue = string(byteSliceValue)
isString = true
}
if !isString {
return false
}

View File

@ -87,7 +87,7 @@ func TestString_AnyLength(t *testing.T) {
Valid bool
}{
{"string", true},
{[]byte("bytes"), false},
{[]byte("bytes"), true},
{1, false},
{0.1, false},
{nil, false},

View File

@ -53,6 +53,15 @@ func readUint(value interface{}) (uint, bool) {
overflows := floatVal < 0 || floatVal > math.MaxUint64
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
default:
return 0, false