Commit 73b4550a authored by Kyle Lemons's avatar Kyle Lemons

Merge pull request #4 from rmartinjak/skipzerovals

Allow the shortening of diffs by skipping fields with zero values
parents 808ac284 c13a706a
......@@ -35,13 +35,21 @@ type Config struct {
// Field and value options
IncludeUnexported bool // Include unexported fields in output
PrintStringers bool // Call String on a fmt.Stringer
SkipZeroFields bool // Skip struct fields that have a zero value.
// Output transforms
ShortList int // Maximum character length for short lists if nonzero.
}
// DefaultConfig is the default configuration used for all exported non-method functions except Compare.
var DefaultConfig = &Config{}
// ConmpareConfig is the default configuration used for Compare.
var CompareConfig = &Config {
Diffable: true,
IncludeUnexported: true,
}
func (cfg *Config) fprint(buf *bytes.Buffer, vals ...interface{}) {
for i, val := range vals {
if i > 0 {
......@@ -86,16 +94,18 @@ func (cfg *Config) Fprint(w io.Writer, vals ...interface{}) (n int64, err error)
}
// Compare returns a string containing a line-by-line unified diff of the
// values in got and want. Compare includes unexported fields.
// values in got and want, using the default config.
//
// Each line in the output is prefixed with '+', '-', or ' ' to indicate if it
// should be added to, removed from, or is correct for the "got" value with
// respect to the "want" value.
func Compare(got, want interface{}) string {
diffOpt := &Config{
Diffable: true,
IncludeUnexported: true,
}
return CompareConfig.Compare(got, want)
}
return diff.Diff(diffOpt.Sprint(got), diffOpt.Sprint(want))
// Compare returns a string containing a line-by-line unified diff of the
// values in got and want according to the cfg.
func (cfg *Config) Compare(got, want interface{}) string {
cfg.Diffable = true
return diff.Diff(cfg.Sprint(got), cfg.Sprint(want))
}
......@@ -70,3 +70,59 @@ func TestDiff(t *testing.T) {
}
}
}
func TestSkipZeroFields(t *testing.T) {
type example struct {
Name string
Species string
Age int
Friends []string
}
tests := []struct {
desc string
got, want interface{}
diff string
}{
{
desc: "basic struct",
got: example{
Name: "Zaphd",
Species: "Betelgeusian",
Age: 42,
},
want: example{
Name: "Zaphod",
Species: "Betelgeusian",
Age: 42,
Friends: []string{
"Ford Prefect",
"Trillian",
"",
},
},
diff: ` {
- Name: "Zaphd",
+ Name: "Zaphod",
Species: "Betelgeusian",
Age: 42,
+ Friends: [
+ "Ford Prefect",
+ "Trillian",
+ "",
+ ],
}`,
},
}
cfg := *CompareConfig
cfg.SkipZeroFields = true
for _, test := range tests {
if got, want := cfg.Compare(test.got, test.want), test.diff; got != want {
t.Errorf("%s:", test.desc)
t.Errorf(" got: %q", got)
t.Errorf(" want: %q", want)
}
}
}
......@@ -20,6 +20,14 @@ import (
"sort"
)
func isZeroVal(val reflect.Value) bool {
if !val.CanInterface() {
return false
}
z := reflect.Zero(val.Type()).Interface()
return reflect.DeepEqual(val.Interface(), z)
}
func (c *Config) val2node(val reflect.Value) node {
// TODO(kevlar): pointer tracking?
......@@ -63,7 +71,11 @@ func (c *Config) val2node(val reflect.Value) node {
if !c.IncludeUnexported && sf.PkgPath != "" {
continue
}
n = append(n, keyval{sf.Name, c.val2node(val.Field(i))})
field := val.Field(i)
if c.SkipZeroFields && isZeroVal(field) {
continue
}
n = append(n, keyval{sf.Name, c.val2node(field)})
}
return n
case reflect.Bool:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment