diff --git a/spew/config.go b/spew/config.go index 5e619d9..076a503 100644 --- a/spew/config.go +++ b/spew/config.go @@ -16,12 +16,30 @@ package spew -// ConfigState is used to describe configuration options used by spew to format -// and display values. There is a global instance, Config, that is used to -// control all top-level Formatter and Dump functionality. In addition, each -// SpewState instance provides access to a unique ConfigState which can be used -// to control the configuration of that particular instance. +import ( + "fmt" + "io" + "os" +) + +// ConfigState houses the configuration options used by spew to format and +// display values. There is a global instance, Config, that is used to control +// all top-level Formatter and Dump functionality. Each ConfigState instance +// provides methods equivalent to the top-level functions. +// +// The zero value for ConfigState provides no indentation. You would typically +// want to set it to a space or a tab. +// +// Alternatively, you can use NewDefaultConfig to get a ConfigState instance +// with default settings. See the documentation of NewDefaultConfig for default +// values. type ConfigState struct { + // Indent specifies the string to use for each indentation level. The + // global config instance that all top-level functions use set this to a + // single space by default. If you would like more indentation, you might + // set this to a tab with "\t" or perhaps two spaces with " ". + Indent string + // MaxDepth controls the maximum number of levels to descend into nested // data structures. The default, 0, means there is no limit. // @@ -30,11 +48,6 @@ type ConfigState struct { // nested data structures. MaxDepth int - // Indent specifies the string to use for each indentation level. It is - // a single space by default. If you would like more indentation, you might - // set this to a tab with "\t" or perhaps two spaces with " ". - Indent string - // DisableMethods specifies whether or not error and Stringer interfaces are // invoked for types that implement them. DisableMethods bool @@ -55,4 +68,157 @@ type ConfigState struct { // The configuration can be changed by modifying the contents of spew.Config. var Config ConfigState = ConfigState{Indent: " "} -var defaultConfig = ConfigState{Indent: " "} +// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the formatted string as a value that satisfies error. See NewFormatter +// for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { + return fmt.Errorf(format, c.convertArgs(a)...) +} + +// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprint(w, c.convertArgs(a)...) +} + +// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { + return fmt.Fprintf(w, format, c.convertArgs(a)...) +} + +// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it +// passed with a Formatter interface returned by c.NewFormatter. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { + return fmt.Fprintln(w, c.convertArgs(a)...) +} + +// Print is a wrapper for fmt.Print that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Print(a ...interface{}) (n int, err error) { + return fmt.Print(c.convertArgs(a)...) +} + +// Printf is a wrapper for fmt.Printf that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { + return fmt.Printf(format, c.convertArgs(a)...) +} + +// Println is a wrapper for fmt.Println that treats each argument as if it were +// passed with a Formatter interface returned by c.NewFormatter. It returns +// the number of bytes written and any write error encountered. See +// NewFormatter for formatting details. +// +// This function is shorthand for the following syntax: +// +// fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) +func (c *ConfigState) Println(a ...interface{}) (n int, err error) { + return fmt.Println(c.convertArgs(a)...) +} + +/* +NewFormatter returns a custom formatter that satisfies the fmt.Formatter +interface. As a result, it integrates cleanly with standard fmt package +printing functions. The formatter is useful for inline printing of smaller data +types similar to the standard %v format specifier. + +The custom formatter only responds to the %v (most compact), %+v (adds pointer +addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb +combinations. Any other verbs such as %x and %q will be sent to the the +standard fmt package for formatting. In addition, the custom formatter ignores +the width and precision arguments (however they will still work on the format +specifiers not handled by the custom formatter). + +Typically this function shouldn't be called directly. It is much easier to make +use of the custom formatter by calling one of the convenience functions such as +c.Printf, c.Println, or c.Printf. +*/ +func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { + return newFormatter(c, v) +} + +// Fdump formats and displays the passed arguments to io.Writer w. It formats +// exactly the same as Dump. +func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { + fdump(c, w, a...) +} + +/* +Dump displays the passed parameters to standard out with newlines, customizable +indentation, and additional debug information such as complete types and all +pointer addresses used to indirect to the final value. It provides the +following features over the built-in printing facilities provided by the fmt +package: + + * Pointers are dereferenced and followed + * Circular data structures are detected and handled properly + * Custom Stringer/error interfaces are optionally invoked, including + on unexported types + * Custom types which only implement the Stringer/error interfaces via + a pointer receiver are optionally invoked when passing non-pointer + variables + +The configuration options are controlled by modifying the public members +of c. See ConfigState for options documentation. + +See Fdump if you would prefer dumping to an arbitrary io.Writer. +*/ +func (c *ConfigState) Dump(a ...interface{}) { + fdump(c, os.Stdout, a...) +} + +// convertArgs accepts a slice of arguments and returns a slice of the same +// length with each argument converted to a spew Formatter interface using +// the ConfigState associated with s. +func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { + formatters = make([]interface{}, len(args)) + for index, arg := range args { + formatters[index] = newFormatter(c, arg) + } + return formatters +} + +// NewDefaultConfig returns a ConfigState with the following default settings. +// +// Indent: " " +// MaxDepth: 0 +// DisableMethods: false +// DisablePointerMethods: false +func NewDefaultConfig() *ConfigState { + return &ConfigState{Indent: " "} +} diff --git a/spew/doc.go b/spew/doc.go index 84cc1b3..5b0725c 100644 --- a/spew/doc.go +++ b/spew/doc.go @@ -65,10 +65,9 @@ Configuration of spew is handled by fields in the ConfigState type. For convenience, all of the top-level functions use a global state available via the spew.Config global. -It is also possible to create a SpewState instance which provides a unique -ConfigState accessible via the Config method. The methods of SpewState are +It is also possible to create a ConfigState instance that provides methods equivalent to the top-level functions. This allows concurrent configuration -options. See the SpewState documentation for more details. +options. See the ConfigState documentation for more details. The following configuration options are available: * MaxDepth diff --git a/spew/example_test.go b/spew/example_test.go index 7a60202..acbfb2a 100644 --- a/spew/example_test.go +++ b/spew/example_test.go @@ -131,20 +131,16 @@ func ExamplePrintf() { // circular: {1 <*>{1 <*>}} } -// This example demonstrates how to use a SpewState. -func ExampleSpewState() { - // A SpewState does not need initialization. - ss := new(spew.SpewState) // or var ss spew.SpewState +// This example demonstrates how to use a ConfigState. +func ExampleConfigState() { + // Modify the indent level of the ConfigState only. The global + // configuration is not modified. + scs := spew.ConfigState{Indent: "\t"} - // Modify the indent level of the SpewState only. The global configuration - // is not modified. - ssc := ss.Config() - ssc.Indent = "\t" - - // Output using the SpewState instance. + // Output using the ConfigState instance. v := map[string]int{"one": 1} - ss.Printf("v: %v\n", v) - ss.Dump(v) + scs.Printf("v: %v\n", v) + scs.Dump(v) // Output: // v: map[one:1] @@ -153,27 +149,23 @@ func ExampleSpewState() { // } } -// This example demonstrates how to use a SpewState.Dump to dump variables to +// This example demonstrates how to use ConfigState.Dump to dump variables to // stdout -func ExampleSpewState_Dump() { +func ExampleConfigState_Dump() { // See the top-level Dump example for details on the types used in this // example. - // A SpewState does not need initialization. - ss := new(spew.SpewState) // or var ss spew.SpewState - ss2 := new(spew.SpewState) // or var ss2 spew.SpewState - - // Modify the indent level of the first SpewState only. - ssc := ss.Config() - ssc.Indent = "\t" + // Create two ConfigState instances with different indentation. + scs := spew.ConfigState{Indent: "\t"} + scs2 := spew.ConfigState{Indent: " "} // Setup some sample data structures for the example. bar := Bar{Flag(flagTwo), uintptr(0)} s1 := Foo{bar, map[interface{}]interface{}{"one": true}} - // Dump using the SpewState instances. - ss.Dump(s1) - ss2.Dump(s1) + // Dump using the ConfigState instances. + scs.Dump(s1) + scs2.Dump(s1) // Output: // (spew_test.Foo) { @@ -197,26 +189,28 @@ func ExampleSpewState_Dump() { // } -// This example demonstrates how to use SpewState.Printf to display a variable +// This example demonstrates how to use ConfigState.Printf to display a variable // with a format string and inline formatting. -func ExampleSpewState_Printf() { +func ExampleConfigState_Printf() { // See the top-level Dump example for details on the types used in this // example. - // A SpewState does not need initialization. - ss := new(spew.SpewState) // or var ss spew.SpewState - ss2 := new(spew.SpewState) // or var ss2 spew.SpewState + // Create two ConfigState instances and modify the method handling of the + // first ConfigState only. + scs := spew.NewDefaultConfig() + scs2 := spew.NewDefaultConfig() + scs.DisableMethods = true - // Modify the method handling of the first SpewState only. - ssc := ss.Config() - ssc.DisableMethods = true + // Alternatively + // scs := spew.ConfigState{Indent: " ", DisableMethods: true} + // scs2 := spew.ConfigState{Indent: " "} // This is of type Flag which implements a Stringer and has raw value 1. f := flagTwo - // Dump using the SpewState instances. - ss.Printf("f: %v\n", f) - ss2.Printf("f: %v\n", f) + // Dump using the ConfigState instances. + scs.Printf("f: %v\n", f) + scs2.Printf("f: %v\n", f) // Output: // f: 1 diff --git a/spew/spew.go b/spew/spew.go index 657664b..a599978 100644 --- a/spew/spew.go +++ b/spew/spew.go @@ -19,7 +19,6 @@ package spew import ( "fmt" "io" - "os" ) // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were @@ -114,179 +113,3 @@ func convertArgs(args []interface{}) (formatters []interface{}) { } return formatters } - -// SpewState provides a context which can have its own configuration options. -// The configuration options can be manipulated via the Config method. The -// methods of SpewState are equivalent to the top-level functions. -// -// A SpewState does not need any special initialization, so new(SpewState) or -// just declaring a SpewState variable, is sufficient to initialilize a -// SpewState using the default configuration options. -type SpewState struct { - cs *ConfigState -} - -// Config returns a pointer to the active ConfigState for the SpewState -// instance. Set the fields of the returned structure to the desired -// configuration settings for the instance. -func (s *SpewState) Config() (cs *ConfigState) { - if s.cs == nil { - cs := defaultConfig - s.cs = &cs - } - return s.cs -} - -// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were -// passed with a Formatter interface returned by s.NewFormatter. It returns -// the formatted string as a value that satisfies error. See NewFormatter -// for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Errorf(format, s.NewFormatter(a), s.NewFormatter(b)) -func (s *SpewState) Errorf(format string, a ...interface{}) (err error) { - return fmt.Errorf(format, s.convertArgs(a)...) -} - -// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were -// passed with a Formatter interface returned by s.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprint(w, s.NewFormatter(a), s.NewFormatter(b)) -func (s *SpewState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprint(w, s.convertArgs(a)...) -} - -// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were -// passed with a Formatter interface returned by s.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintf(w, format, s.NewFormatter(a), s.NewFormatter(b)) -func (s *SpewState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { - return fmt.Fprintf(w, format, s.convertArgs(a)...) -} - -// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it -// passed with a Formatter interface returned by s.NewFormatter. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Fprintln(w, s.NewFormatter(a), s.NewFormatter(b)) -func (s *SpewState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprintln(w, s.convertArgs(a)...) -} - -// Print is a wrapper for fmt.Print that treats each argument as if it were -// passed with a Formatter interface returned by s.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Print(s.NewFormatter(a), s.NewFormatter(b)) -func (s *SpewState) Print(a ...interface{}) (n int, err error) { - return fmt.Print(s.convertArgs(a)...) -} - -// Printf is a wrapper for fmt.Printf that treats each argument as if it were -// passed with a Formatter interface returned by s.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Printf(format, s.NewFormatter(a), s.NewFormatter(b)) -func (s *SpewState) Printf(format string, a ...interface{}) (n int, err error) { - return fmt.Printf(format, s.convertArgs(a)...) -} - -// Println is a wrapper for fmt.Println that treats each argument as if it were -// passed with a Formatter interface returned by s.NewFormatter. It returns -// the number of bytes written and any write error encountered. See -// NewFormatter for formatting details. -// -// This function is shorthand for the following syntax: -// -// fmt.Println(s.NewFormatter(a), s.NewFormatter(b)) -func (s *SpewState) Println(a ...interface{}) (n int, err error) { - return fmt.Println(s.convertArgs(a)...) -} - -/* -NewFormatter returns a custom formatter that satisfies the fmt.Formatter -interface. As a result, it integrates cleanly with standard fmt package -printing functions. The formatter is useful for inline printing of smaller data -types similar to the standard %v format specifier. - -The custom formatter only responds to the %v (most compact), %+v (adds pointer -addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb -combinations. Any other verbs such as %x and %q will be sent to the the -standard fmt package for formatting. In addition, the custom formatter ignores -the width and precision arguments (however they will still work on the format -specifiers not handled by the custom formatter). - -Typically this function shouldn't be called directly. It is much easier to make -use of the custom formatter by calling one of the convenience functions such as -s.Printf, s.Println, or s.Printf. -*/ -func (s *SpewState) NewFormatter(v interface{}) fmt.Formatter { - // The Config method creates the config state if needed, so call it instead - // of using s.cs directly to ensure the zero value SpewState is sane. - return newFormatter(s.Config(), v) -} - -// Fdump formats and displays the passed arguments to io.Writer w. It formats -// exactly the same as Dump. -func (s *SpewState) Fdump(w io.Writer, a ...interface{}) { - // The Config method creates the config state if needed, so call it instead - // of using s.cs directly to ensure the zero value SpewState is sane. - fdump(s.Config(), w, a...) -} - -/* -Dump displays the passed parameters to standard out with newlines, customizable -indentation, and additional debug information such as complete types and all -pointer addresses used to indirect to the final value. It provides the -following features over the built-in printing facilities provided by the fmt -package: - - * Pointers are dereferenced and followed - * Circular data structures are detected and handled properly - * Custom Stringer/error interfaces are optionally invoked, including - on unexported types - * Custom types which only implement the Stringer/error interfaces via - a pointer receiver are optionally invoked when passing non-pointer - variables - -The configuration options are controlled by accessing the ConfigState associated -with s via the Config method. See ConfigState for options documentation. - -See Fdump if you would prefer dumping to an arbitrary io.Writer. -*/ -func (s *SpewState) Dump(a ...interface{}) { - // The Config method creates the config state if needed, so call it instead - // of using s.cs directly to ensure the zero value SpewState is sane. - fdump(s.Config(), os.Stdout, a...) -} - -// convertArgs accepts a slice of arguments and returns a slice of the same -// length with each argument converted to a spew Formatter interface using -// the ConfigState associated with s. -func (s *SpewState) convertArgs(args []interface{}) (formatters []interface{}) { - // The Config method creates the config state if needed, so call it instead - // of using s.cs directly to ensure the zero value SpewState is sane. - cs := s.Config() - formatters = make([]interface{}, len(args)) - for index, arg := range args { - formatters[index] = newFormatter(cs, arg) - } - return formatters -} diff --git a/spew/spew_test.go b/spew/spew_test.go index 47557dd..d2d620e 100644 --- a/spew/spew_test.go +++ b/spew/spew_test.go @@ -26,18 +26,18 @@ import ( ) // spewFunc is used to identify which public function of the spew package or -// SpewState a test applies to. +// ConfigState a test applies to. type spewFunc int const ( - fSSFdump spewFunc = iota - fSSFprint - fSSFprintf - fSSFprintln - fSSPrint - fSSPrintln - fSSErrorf - fSSNewFormatter + fCSFdump spewFunc = iota + fCSFprint + fCSFprintf + fCSFprintln + fCSPrint + fCSPrintln + fCSErrorf + fCSNewFormatter fErrorf fFprint fFprintln @@ -47,14 +47,14 @@ const ( // Map of spewFunc values to names for pretty printing. var spewFuncStrings = map[spewFunc]string{ - fSSFdump: "SpewState.Fdump", - fSSFprint: "SpewState.Fprint", - fSSFprintf: "SpewState.Fprintf", - fSSFprintln: "SpewState.Fprintln", - fSSPrint: "SpewState.Print", - fSSPrintln: "SpewState.Println", - fSSErrorf: "SpewState.Errorf", - fSSNewFormatter: "SpewState.NewFormatter", + fCSFdump: "ConfigState.Fdump", + fCSFprint: "ConfigState.Fprint", + fCSFprintf: "ConfigState.Fprintf", + fCSFprintln: "ConfigState.Fprintln", + fCSPrint: "ConfigState.Print", + fCSPrintln: "ConfigState.Println", + fCSErrorf: "ConfigState.Errorf", + fCSNewFormatter: "ConfigState.NewFormatter", fErrorf: "spew.Errorf", fFprint: "spew.Fprint", fFprintln: "spew.Fprintln", @@ -70,7 +70,7 @@ func (f spewFunc) String() string { } // spewTest is used to describe a test to be performed against the public -// functions of the spew package or SpewState. +// functions of the spew package or ConfigState. type spewTest struct { f spewFunc format string @@ -79,20 +79,20 @@ type spewTest struct { } // spewTests houses the tests to be performed against the public functions of -// the spew package and SpewState. +// the spew package and ConfigState. // // These tests are only intended to ensure the public functions are exercised // and are intentionally not exhaustive of types. The exhaustive type // tests are handled in the dump and format tests. var spewTests = []spewTest{ - {fSSFdump, "", int8(127), "(int8) 127\n"}, - {fSSFprint, "", int16(32767), "32767"}, - {fSSFprintf, "%v", int32(2147483647), "2147483647"}, - {fSSFprintln, "", int(2147483647), "2147483647\n"}, - {fSSPrint, "", int64(9223372036854775807), "9223372036854775807"}, - {fSSPrintln, "", uint8(255), "255\n"}, - {fSSErrorf, "%#v", uint16(65535), "(uint16)65535"}, - {fSSNewFormatter, "%v", uint32(4294967295), "4294967295"}, + {fCSFdump, "", int8(127), "(int8) 127\n"}, + {fCSFprint, "", int16(32767), "32767"}, + {fCSFprintf, "%v", int32(2147483647), "2147483647"}, + {fCSFprintln, "", int(2147483647), "2147483647\n"}, + {fCSPrint, "", int64(9223372036854775807), "9223372036854775807"}, + {fCSPrintln, "", uint8(255), "255\n"}, + {fCSErrorf, "%#v", uint16(65535), "(uint16)65535"}, + {fCSNewFormatter, "%v", uint32(4294967295), "4294967295"}, {fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"}, {fFprint, "", float32(3.14), "3.14"}, {fFprintln, "", float64(6.28), "6.28\n"}, @@ -121,46 +121,46 @@ func redirStdout(f func()) ([]byte, error) { // TestSpew executes all of the tests described by spewTests. func TestSpew(t *testing.T) { - ss := new(spew.SpewState) + scs := spew.NewDefaultConfig() t.Logf("Running %d tests", len(spewTests)) for i, test := range spewTests { buf := new(bytes.Buffer) switch test.f { - case fSSFdump: - ss.Fdump(buf, test.in) + case fCSFdump: + scs.Fdump(buf, test.in) - case fSSFprint: - ss.Fprint(buf, test.in) + case fCSFprint: + scs.Fprint(buf, test.in) - case fSSFprintf: - ss.Fprintf(buf, test.format, test.in) + case fCSFprintf: + scs.Fprintf(buf, test.format, test.in) - case fSSFprintln: - ss.Fprintln(buf, test.in) + case fCSFprintln: + scs.Fprintln(buf, test.in) - case fSSPrint: - b, err := redirStdout(func() { ss.Print(test.in) }) + case fCSPrint: + b, err := redirStdout(func() { scs.Print(test.in) }) if err != nil { t.Errorf("%v #%d %v", test.f, i, err) continue } buf.Write(b) - case fSSPrintln: - b, err := redirStdout(func() { ss.Println(test.in) }) + case fCSPrintln: + b, err := redirStdout(func() { scs.Println(test.in) }) if err != nil { t.Errorf("%v #%d %v", test.f, i, err) continue } buf.Write(b) - case fSSErrorf: - err := ss.Errorf(test.format, test.in) + case fCSErrorf: + err := scs.Errorf(test.format, test.in) buf.WriteString(err.Error()) - case fSSNewFormatter: - fmt.Fprintf(buf, test.format, ss.NewFormatter(test.in)) + case fCSNewFormatter: + fmt.Fprintf(buf, test.format, scs.NewFormatter(test.in)) case fErrorf: err := spew.Errorf(test.format, test.in) @@ -194,7 +194,7 @@ func TestSpew(t *testing.T) { } s := buf.String() if test.want != s { - t.Errorf("SpewState #%d\n got: %s want: %s", i, s, test.want) + t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want) continue } }