Skip to content

Commit

Permalink
Merge branch 'master' into diff-heuristic
Browse files Browse the repository at this point in the history
  • Loading branch information
dsnet authored Sep 28, 2017
2 parents f8cbfe4 + f46009a commit f4b3429
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 17 deletions.
2 changes: 1 addition & 1 deletion cmp/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
"github.com/google/go-cmp/cmp/internal/value"
)

// BUG: Maps with keys containing NaN values cannot be properly compared due to
// BUG(dsnet): Maps with keys containing NaN values cannot be properly compared due to
// the reflection package's inability to retrieve such entries. Equal will panic
// anytime it comes across a NaN key, but this behavior may change.
//
Expand Down
56 changes: 55 additions & 1 deletion cmp/compare_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package cmp_test
import (
"bytes"
"crypto/md5"
"encoding/json"
"fmt"
"io"
"math"
Expand Down Expand Up @@ -408,7 +409,9 @@ root:
}

func transformerTests() []test {
const label = "Transformer/"
type JSON string

const label = "Transformer"

return []test{{
label: label,
Expand Down Expand Up @@ -469,6 +472,57 @@ func transformerTests() []test {
λ({int}):
-: "string"
+: 1`,
}, {
label: label,
x: JSON(`{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"isAlive": true,
"address": {
"city": "Los Angeles",
"postalCode": "10021-3100",
"state": "CA",
"streetAddress": "21 2nd Street"
},
"phoneNumbers": [{
"type": "home",
"number": "212 555-4321"
},{
"type": "office",
"number": "646 555-4567"
},{
"number": "123 456-7890",
"type": "mobile"
}],
"children": []
}`),
y: JSON(`{"firstName":"John","lastName":"Smith","isAlive":true,"age":25,
"address":{"streetAddress":"21 2nd Street","city":"New York",
"state":"NY","postalCode":"10021-3100"},"phoneNumbers":[{"type":"home",
"number":"212 555-1234"},{"type":"office","number":"646 555-4567"},{
"type":"mobile","number":"123 456-7890"}],"children":[],"spouse":null}`),
opts: []cmp.Option{
cmp.Transformer("ParseJSON", func(s JSON) (m map[string]interface{}) {
if err := json.Unmarshal([]byte(s), &m); err != nil {
panic(err)
}
return m
}),
},
wantDiff: `
ParseJSON({cmp_test.JSON})["address"]["city"]:
-: "Los Angeles"
+: "New York"
ParseJSON({cmp_test.JSON})["address"]["state"]:
-: "CA"
+: "NY"
ParseJSON({cmp_test.JSON})["phoneNumbers"][0]["number"]:
-: "212 555-4321"
+: "212 555-1234"
ParseJSON({cmp_test.JSON})["spouse"]:
-: <non-existent>
+: interface {}(nil)`,
}}
}

Expand Down
6 changes: 1 addition & 5 deletions cmp/internal/value/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ import (
"unicode/utf8"
)

// formatFakePointers controls whether to substitute pointer addresses with nil.
// This is used for deterministic testing.
var formatFakePointers = false

var stringerIface = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()

// Format formats the value v as a string.
Expand All @@ -27,7 +23,7 @@ var stringerIface = reflect.TypeOf((*fmt.Stringer)(nil)).Elem()
// * Prints a nil-slice as being nil, not empty
// * Prints map entries in deterministic order
func Format(v reflect.Value, useStringer bool) string {
return formatAny(v, formatConfig{useStringer, true, true, !formatFakePointers}, nil)
return formatAny(v, formatConfig{useStringer, true, true, true}, nil)
}

type formatConfig struct {
Expand Down
8 changes: 5 additions & 3 deletions cmp/internal/value/format_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,12 @@ func TestFormat(t *testing.T) {
want: "[2]interface {}{&[2]interface {}{(*[2]interface {})(0x00), interface {}(nil)}, interface {}(nil)}",
}}

formatFakePointers = true
defer func() { formatFakePointers = false }()
for i, tt := range tests {
got := Format(reflect.ValueOf(tt.in), true)
// Intentionally retrieve the value through an unexported field to
// ensure the format logic does not depend on read-write access
// to the reflect.Value.
v := reflect.ValueOf(struct{ x interface{} }{tt.in}).Field(0)
got := formatAny(v, formatConfig{useStringer: true, printType: true, followPointers: true}, nil)
if got != tt.want {
t.Errorf("test %d, Format():\ngot %q\nwant %q", i, got, tt.want)
}
Expand Down
13 changes: 6 additions & 7 deletions cmp/path.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,12 @@ func (pa Path) GoString() string {
ssPost = append(ssPost, ")")
continue
case *typeAssertion:
// Elide type assertions immediately following a transform to
// prevent overly verbose path printouts.
// Some transforms return interface{} because of Go's lack of
// generics, but typically take in and return the exact same
// concrete type. Other times, the transform creates an anonymous
// struct, which will be very verbose to print.
if _, ok := nextStep.(*transform); ok {
// As a special-case, elide type assertions on anonymous types
// since they are typically generated dynamically and can be very
// verbose. For example, some transforms return interface{} because
// of Go's lack of generics, but typically take in and return the
// exact same concrete type.
if s.Type().PkgPath() == "" {
continue
}
}
Expand Down

0 comments on commit f4b3429

Please sign in to comment.