whatcanGOwrong
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package tomltest
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// CompareTOML compares the given arguments.
|
||||
//
|
||||
// The returned value is a copy of Test with Failure set to a (human-readable)
|
||||
// description of the first element that is unequal. If both arguments are equal
|
||||
// Test is returned unchanged.
|
||||
//
|
||||
// Reflect.DeepEqual could work here, but it won't tell us how the two
|
||||
// structures are different.
|
||||
func (r Test) CompareTOML(want, have interface{}) Test {
|
||||
if isTomlValue(want) {
|
||||
if !isTomlValue(have) {
|
||||
return r.fail("Type for key '%s' differs:\n"+
|
||||
" Expected: %[2]v (%[2]T)\n"+
|
||||
" Your encoder: %[3]v (%[3]T)",
|
||||
r.Key, want, have)
|
||||
}
|
||||
|
||||
if !deepEqual(want, have) {
|
||||
return r.fail("Values for key '%s' differ:\n"+
|
||||
" Expected: %[2]v (%[2]T)\n"+
|
||||
" Your encoder: %[3]v (%[3]T)",
|
||||
r.Key, want, have)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
switch w := want.(type) {
|
||||
case map[string]interface{}:
|
||||
return r.cmpTOMLMap(w, have)
|
||||
case []interface{}:
|
||||
return r.cmpTOMLArrays(w, have)
|
||||
default:
|
||||
return r.fail("Unrecognized TOML structure: %T", want)
|
||||
}
|
||||
}
|
||||
|
||||
func (r Test) cmpTOMLMap(want map[string]interface{}, have interface{}) Test {
|
||||
haveMap, ok := have.(map[string]interface{})
|
||||
if !ok {
|
||||
return r.mismatch("table", want, haveMap)
|
||||
}
|
||||
|
||||
// Check that the keys of each map are equivalent.
|
||||
for k := range want {
|
||||
if _, ok := haveMap[k]; !ok {
|
||||
bunk := r.kjoin(k)
|
||||
return bunk.fail("Could not find key '%s' in encoder output", bunk.Key)
|
||||
}
|
||||
}
|
||||
for k := range haveMap {
|
||||
if _, ok := want[k]; !ok {
|
||||
bunk := r.kjoin(k)
|
||||
return bunk.fail("Could not find key '%s' in expected output", bunk.Key)
|
||||
}
|
||||
}
|
||||
|
||||
// Okay, now make sure that each value is equivalent.
|
||||
for k := range want {
|
||||
if sub := r.kjoin(k).CompareTOML(want[k], haveMap[k]); sub.Failed() {
|
||||
return sub
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r Test) cmpTOMLArrays(want []interface{}, have interface{}) Test {
|
||||
// Slice can be decoded to []interface{} for an array of primitives, or
|
||||
// []map[string]interface{} for an array of tables.
|
||||
//
|
||||
// TODO: it would be nicer if it could always decode to []interface{}?
|
||||
haveSlice, ok := have.([]interface{})
|
||||
if !ok {
|
||||
tblArray, ok := have.([]map[string]interface{})
|
||||
if !ok {
|
||||
return r.mismatch("array", want, have)
|
||||
}
|
||||
|
||||
haveSlice = make([]interface{}, len(tblArray))
|
||||
for i := range tblArray {
|
||||
haveSlice[i] = tblArray[i]
|
||||
}
|
||||
}
|
||||
|
||||
if len(want) != len(haveSlice) {
|
||||
return r.fail("Array lengths differ for key '%s'"+
|
||||
" Expected: %[2]v (len=%[4]d)\n"+
|
||||
" Your encoder: %[3]v (len=%[5]d)",
|
||||
r.Key, want, haveSlice, len(want), len(haveSlice))
|
||||
}
|
||||
for i := 0; i < len(want); i++ {
|
||||
if sub := r.CompareTOML(want[i], haveSlice[i]); sub.Failed() {
|
||||
return sub
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// reflect.DeepEqual() that deals with NaN != NaN
|
||||
func deepEqual(want, have interface{}) bool {
|
||||
var wantF, haveF float64
|
||||
switch f := want.(type) {
|
||||
case float32:
|
||||
wantF = float64(f)
|
||||
case float64:
|
||||
wantF = f
|
||||
}
|
||||
switch f := have.(type) {
|
||||
case float32:
|
||||
haveF = float64(f)
|
||||
case float64:
|
||||
haveF = f
|
||||
}
|
||||
if math.IsNaN(wantF) && math.IsNaN(haveF) {
|
||||
return true
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(want, have)
|
||||
}
|
||||
|
||||
func isTomlValue(v interface{}) bool {
|
||||
switch v.(type) {
|
||||
case map[string]interface{}, []interface{}:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
Reference in New Issue
Block a user