reflect: Add Value.IsZero() method

Add Value.IsZero() with tests, largely copied from the Go source code.

The tests were altered to remove the parts calling `Zero()` as that is
still unimplemented in tinygo, and to remove a test that tries to catch
a panic which is not supported on wasi.

A new case for `UnsafePointer` in `Value.IsNil()` was required for
unsafe.Pointer tests to pass.

Link: https://cs.opensource.google/go/go/+/refs/tags/go1.19.3:src/reflect/value.go;l=1568
Link: https://cs.opensource.google/go/go/+/refs/tags/go1.19.3:src/reflect/all_test.go;l=1322
Co-authored-by: Cam Hutchison <camh@xdna.net>
This commit is contained in:
Julia Ogris
2022-11-20 20:03:41 +11:00
committed by Ron Evans
parent a329f56ec2
commit c759e6fc2d
2 changed files with 148 additions and 1 deletions
+106
View File
@@ -5,9 +5,13 @@
package reflect_test
import (
"io"
"math"
. "reflect"
"strings"
"testing"
"time"
"unsafe"
)
type Basic struct {
@@ -184,5 +188,107 @@ func TestDeepEqualComplexStructInequality(t *testing.T) {
}
}
type T struct {
a int
b float64
c string
d *int
}
var _i = 7
func TestIsZero(t *testing.T) {
for i, tt := range []struct {
x interface{}
want bool
}{
// Booleans
{true, false},
{false, true},
// Numeric types
{int(0), true},
{int(1), false},
{int8(0), true},
{int8(1), false},
{int16(0), true},
{int16(1), false},
{int32(0), true},
{int32(1), false},
{int64(0), true},
{int64(1), false},
{uint(0), true},
{uint(1), false},
{uint8(0), true},
{uint8(1), false},
{uint16(0), true},
{uint16(1), false},
{uint32(0), true},
{uint32(1), false},
{uint64(0), true},
{uint64(1), false},
{float32(0), true},
{float32(1.2), false},
{float64(0), true},
{float64(1.2), false},
{math.Copysign(0, -1), false},
{complex64(0), true},
{complex64(1.2), false},
{complex128(0), true},
{complex128(1.2), false},
{complex(math.Copysign(0, -1), 0), false},
{complex(0, math.Copysign(0, -1)), false},
{complex(math.Copysign(0, -1), math.Copysign(0, -1)), false},
{uintptr(0), true},
{uintptr(128), false},
// Array
{[5]string{"", "", "", "", ""}, true},
{[5]string{}, true},
{[5]string{"", "", "", "a", ""}, false},
// Chan
{(chan string)(nil), true},
{make(chan string), false},
{time.After(1), false},
// Func
{(func())(nil), true},
{New, false},
// Interface
{New(TypeOf(new(error)).Elem()).Elem(), true},
{(io.Reader)(strings.NewReader("")), false},
// Map
{(map[string]string)(nil), true},
{map[string]string{}, false},
{make(map[string]string), false},
// Pointer
{(*func())(nil), true},
{(*int)(nil), true},
{new(int), false},
// Slice
{[]string{}, false},
{([]string)(nil), true},
{make([]string, 0), false},
// Strings
{"", true},
{"not-zero", false},
// Structs
{T{}, true},
{T{123, 456.75, "hello", &_i}, false},
// UnsafePointer
{(unsafe.Pointer)(nil), true},
{(unsafe.Pointer)(new(int)), false},
} {
var x Value
if v, ok := tt.x.(Value); ok {
x = v
} else {
x = ValueOf(tt.x)
}
b := x.IsZero()
if b != tt.want {
t.Errorf("%d: IsZero((%s)(%+v)) = %t, want %t", i, x.Kind(), tt.x, b, tt.want)
}
}
}
type MyBytes []byte
type MyByte byte