mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 12:03:41 +00:00
reflect: add support for DeepEqual
The implementation has been mostly copied from the Go reference implementation with some small changes to fit TinyGo. Source: https://github.com/golang/go/blob/77a11c05d6a6f766c75f804ea9b8796f9a9f85a3/src/reflect/deepequal.go In addition, this commit also contains the following: - A set of tests copied from the Go reflect package. - An increased stack size for the riscv-qemu and hifive1-qemu targets (because they otherwise fail to run the tests). Because these targets are only used for testing, this seems fine to me.
This commit is contained in:
committed by
Ron Evans
parent
5866a47e77
commit
335fb71d2f
@@ -0,0 +1,188 @@
|
||||
// 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 (
|
||||
"math"
|
||||
. "reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
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 MyBytes []byte
|
||||
type MyByte byte
|
||||
Reference in New Issue
Block a user