tinygo/src/reflect/all_test.go

294 строки
7,1 КиБ
Go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package reflect_test
import (
"io"
"math"
. "reflect"
"strings"
"testing"
"time"
"unsafe"
)
type Basic struct {
x int
y float32
}
type NotBasic Basic
type DeepEqualTest struct {
a, b interface{}
eq bool
}
// Simple functions for DeepEqual tests.
var (
fn1 func() // nil.
fn2 func() // nil.
fn3 = func() { fn1() } // Not nil.
)
type self struct{}
type Loopy interface{}
var loopy1, loopy2 Loopy
var cycleMap1, cycleMap2, cycleMap3 map[string]interface{}
type structWithSelfPtr struct {
p *structWithSelfPtr
s string
}
func init() {
loopy1 = &loopy2
loopy2 = &loopy1
cycleMap1 = map[string]interface{}{}
cycleMap1["cycle"] = cycleMap1
cycleMap2 = map[string]interface{}{}
cycleMap2["cycle"] = cycleMap2
cycleMap3 = map[string]interface{}{}
cycleMap3["different"] = cycleMap3
}
// Note: all tests involving maps have been commented out because they aren't
// supported yet.
var deepEqualTests = []DeepEqualTest{
// Equalities
{nil, nil, true},
{1, 1, true},
{int32(1), int32(1), true},
{0.5, 0.5, true},
{float32(0.5), float32(0.5), true},
{"hello", "hello", true},
{make([]int, 10), make([]int, 10), true},
{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
{Basic{1, 0.5}, Basic{1, 0.5}, true},
{error(nil), error(nil), true},
{map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
{fn1, fn2, true},
{[]byte{1, 2, 3}, []byte{1, 2, 3}, true},
{[]MyByte{1, 2, 3}, []MyByte{1, 2, 3}, true},
{MyBytes{1, 2, 3}, MyBytes{1, 2, 3}, true},
// Inequalities
{1, 2, false},
{int32(1), int32(2), false},
{0.5, 0.6, false},
{float32(0.5), float32(0.6), false},
{"hello", "hey", false},
{make([]int, 10), make([]int, 11), false},
{&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},
{Basic{1, 0.5}, Basic{1, 0.6}, false},
{Basic{1, 0}, Basic{2, 0}, false},
{map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false},
{map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false},
{map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false},
{map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false},
{nil, 1, false},
{1, nil, false},
{fn1, fn3, false},
{fn3, fn3, false},
{[][]int{{1}}, [][]int{{2}}, false},
{&structWithSelfPtr{p: &structWithSelfPtr{s: "a"}}, &structWithSelfPtr{p: &structWithSelfPtr{s: "b"}}, false},
// Fun with floating point.
{math.NaN(), math.NaN(), false},
{&[1]float64{math.NaN()}, &[1]float64{math.NaN()}, false},
{&[1]float64{math.NaN()}, self{}, true},
{[]float64{math.NaN()}, []float64{math.NaN()}, false},
{[]float64{math.NaN()}, self{}, true},
{map[float64]float64{math.NaN(): 1}, map[float64]float64{1: 2}, false},
{map[float64]float64{math.NaN(): 1}, self{}, true},
// Nil vs empty: not the same.
{[]int{}, []int(nil), false},
{[]int{}, []int{}, true},
{[]int(nil), []int(nil), true},
{map[int]int{}, map[int]int(nil), false},
{map[int]int{}, map[int]int{}, true},
{map[int]int(nil), map[int]int(nil), true},
// Mismatched types
{1, 1.0, false},
{int32(1), int64(1), false},
{0.5, "hello", false},
{[]int{1, 2, 3}, [3]int{1, 2, 3}, false},
{&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
{Basic{1, 0.5}, NotBasic{1, 0.5}, false},
{map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
{[]byte{1, 2, 3}, []MyByte{1, 2, 3}, false},
{[]MyByte{1, 2, 3}, MyBytes{1, 2, 3}, false},
{[]byte{1, 2, 3}, MyBytes{1, 2, 3}, false},
// Possible loops.
{&loopy1, &loopy1, true},
{&loopy1, &loopy2, true},
{&cycleMap1, &cycleMap2, true},
{&cycleMap1, &cycleMap3, false},
}
func TestDeepEqual(t *testing.T) {
for _, test := range deepEqualTests {
if test.b == (self{}) {
test.b = test.a
}
if r := DeepEqual(test.a, test.b); r != test.eq {
t.Errorf("DeepEqual(%#v, %#v) = %v, want %v", test.a, test.b, r, test.eq)
}
}
}
type Recursive struct {
x int
r *Recursive
}
func TestDeepEqualRecursiveStruct(t *testing.T) {
a, b := new(Recursive), new(Recursive)
*a = Recursive{12, a}
*b = Recursive{12, b}
if !DeepEqual(a, b) {
t.Error("DeepEqual(recursive same) = false, want true")
}
}
type _Complex struct {
a int
b [3]*_Complex
c *string
d map[float64]float64
}
func TestDeepEqualComplexStruct(t *testing.T) {
m := make(map[float64]float64)
stra, strb := "hello", "hello"
a, b := new(_Complex), new(_Complex)
*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
if !DeepEqual(a, b) {
t.Error("DeepEqual(complex same) = false, want true")
}
}
func TestDeepEqualComplexStructInequality(t *testing.T) {
m := make(map[float64]float64)
stra, strb := "hello", "helloo" // Difference is here
a, b := new(_Complex), new(_Complex)
*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
if DeepEqual(a, b) {
t.Error("DeepEqual(complex different) = true, want false")
}
}
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