Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
7b933418
Commit
7b933418
authored
May 15, 2015
by
Felix Lange
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Godeps: add github.com/davecgh/go-spew
parent
dbdc5fd4
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
5776 additions
and
0 deletions
+5776
-0
Godeps.json
Godeps/Godeps.json
+4
-0
common.go
.../_workspace/src/github.com/davecgh/go-spew/spew/common.go
+450
-0
common_test.go
...kspace/src/github.com/davecgh/go-spew/spew/common_test.go
+298
-0
config.go
.../_workspace/src/github.com/davecgh/go-spew/spew/config.go
+294
-0
doc.go
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/doc.go
+202
-0
dump.go
...ps/_workspace/src/github.com/davecgh/go-spew/spew/dump.go
+506
-0
dump_test.go
...orkspace/src/github.com/davecgh/go-spew/spew/dump_test.go
+1021
-0
dumpcgo_test.go
...space/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go
+97
-0
dumpnocgo_test.go
...ace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go
+26
-0
example_test.go
...space/src/github.com/davecgh/go-spew/spew/example_test.go
+230
-0
format.go
.../_workspace/src/github.com/davecgh/go-spew/spew/format.go
+419
-0
format_test.go
...kspace/src/github.com/davecgh/go-spew/spew/format_test.go
+1535
-0
internal_test.go
...pace/src/github.com/davecgh/go-spew/spew/internal_test.go
+156
-0
spew.go
...ps/_workspace/src/github.com/davecgh/go-spew/spew/spew.go
+148
-0
spew_test.go
...orkspace/src/github.com/davecgh/go-spew/spew/spew_test.go
+308
-0
dumpcgo.go
...e/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go
+82
-0
No files found.
Godeps/Godeps.json
View file @
7b933418
...
...
@@ -15,6 +15,10 @@
"Comment"
:
"1.2.0-95-g9b2bd2b"
,
"Rev"
:
"9b2bd2b3489748d4d0a204fa4eb2ee9e89e0ebc6"
},
{
"ImportPath"
:
"github.com/davecgh/go-spew/spew"
,
"Rev"
:
"3e6e67c4dcea3ac2f25fd4731abc0e1deaf36216"
},
{
"ImportPath"
:
"github.com/ethereum/ethash"
,
"Comment"
:
"v23.1-206-gf0e6321"
,
...
...
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package
spew
import
(
"bytes"
"fmt"
"io"
"reflect"
"sort"
"strconv"
"unsafe"
)
const
(
// ptrSize is the size of a pointer on the current arch.
ptrSize
=
unsafe
.
Sizeof
((
*
byte
)(
nil
))
)
var
(
// offsetPtr, offsetScalar, and offsetFlag are the offsets for the
// internal reflect.Value fields. These values are valid before golang
// commit ecccf07e7f9d which changed the format. The are also valid
// after commit 82f48826c6c7 which changed the format again to mirror
// the original format. Code in the init function updates these offsets
// as necessary.
offsetPtr
=
uintptr
(
ptrSize
)
offsetScalar
=
uintptr
(
0
)
offsetFlag
=
uintptr
(
ptrSize
*
2
)
// flagKindWidth and flagKindShift indicate various bits that the
// reflect package uses internally to track kind information.
//
// flagRO indicates whether or not the value field of a reflect.Value is
// read-only.
//
// flagIndir indicates whether the value field of a reflect.Value is
// the actual data or a pointer to the data.
//
// These values are valid before golang commit 90a7c3c86944 which
// changed their positions. Code in the init function updates these
// flags as necessary.
flagKindWidth
=
uintptr
(
5
)
flagKindShift
=
uintptr
(
flagKindWidth
-
1
)
flagRO
=
uintptr
(
1
<<
0
)
flagIndir
=
uintptr
(
1
<<
1
)
)
func
init
()
{
// Older versions of reflect.Value stored small integers directly in the
// ptr field (which is named val in the older versions). Versions
// between commits ecccf07e7f9d and 82f48826c6c7 added a new field named
// scalar for this purpose which unfortunately came before the flag
// field, so the offset of the flag field is different for those
// versions.
//
// This code constructs a new reflect.Value from a known small integer
// and checks if the size of the reflect.Value struct indicates it has
// the scalar field. When it does, the offsets are updated accordingly.
vv
:=
reflect
.
ValueOf
(
0xf00
)
if
unsafe
.
Sizeof
(
vv
)
==
(
ptrSize
*
4
)
{
offsetScalar
=
ptrSize
*
2
offsetFlag
=
ptrSize
*
3
}
// Commit 90a7c3c86944 changed the flag positions such that the low
// order bits are the kind. This code extracts the kind from the flags
// field and ensures it's the correct type. When it's not, the flag
// order has been changed to the newer format, so the flags are updated
// accordingly.
upf
:=
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
&
vv
))
+
offsetFlag
)
upfv
:=
*
(
*
uintptr
)(
upf
)
flagKindMask
:=
uintptr
((
1
<<
flagKindWidth
-
1
)
<<
flagKindShift
)
if
(
upfv
&
flagKindMask
)
>>
flagKindShift
!=
uintptr
(
reflect
.
Int
)
{
flagKindShift
=
0
flagRO
=
1
<<
5
flagIndir
=
1
<<
6
}
}
// unsafeReflectValue converts the passed reflect.Value into a one that bypasses
// the typical safety restrictions preventing access to unaddressable and
// unexported data. It works by digging the raw pointer to the underlying
// value out of the protected value and generating a new unprotected (unsafe)
// reflect.Value to it.
//
// This allows us to check for implementations of the Stringer and error
// interfaces to be used for pretty printing ordinarily unaddressable and
// inaccessible values such as unexported struct fields.
func
unsafeReflectValue
(
v
reflect
.
Value
)
(
rv
reflect
.
Value
)
{
indirects
:=
1
vt
:=
v
.
Type
()
upv
:=
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
&
v
))
+
offsetPtr
)
rvf
:=
*
(
*
uintptr
)(
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
&
v
))
+
offsetFlag
))
if
rvf
&
flagIndir
!=
0
{
vt
=
reflect
.
PtrTo
(
v
.
Type
())
indirects
++
}
else
if
offsetScalar
!=
0
{
// The value is in the scalar field when it's not one of the
// reference types.
switch
vt
.
Kind
()
{
case
reflect
.
Uintptr
:
case
reflect
.
Chan
:
case
reflect
.
Func
:
case
reflect
.
Map
:
case
reflect
.
Ptr
:
case
reflect
.
UnsafePointer
:
default
:
upv
=
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
&
v
))
+
offsetScalar
)
}
}
pv
:=
reflect
.
NewAt
(
vt
,
upv
)
rv
=
pv
for
i
:=
0
;
i
<
indirects
;
i
++
{
rv
=
rv
.
Elem
()
}
return
rv
}
// Some constants in the form of bytes to avoid string overhead. This mirrors
// the technique used in the fmt package.
var
(
panicBytes
=
[]
byte
(
"(PANIC="
)
plusBytes
=
[]
byte
(
"+"
)
iBytes
=
[]
byte
(
"i"
)
trueBytes
=
[]
byte
(
"true"
)
falseBytes
=
[]
byte
(
"false"
)
interfaceBytes
=
[]
byte
(
"(interface {})"
)
commaNewlineBytes
=
[]
byte
(
",
\n
"
)
newlineBytes
=
[]
byte
(
"
\n
"
)
openBraceBytes
=
[]
byte
(
"{"
)
openBraceNewlineBytes
=
[]
byte
(
"{
\n
"
)
closeBraceBytes
=
[]
byte
(
"}"
)
asteriskBytes
=
[]
byte
(
"*"
)
colonBytes
=
[]
byte
(
":"
)
colonSpaceBytes
=
[]
byte
(
": "
)
openParenBytes
=
[]
byte
(
"("
)
closeParenBytes
=
[]
byte
(
")"
)
spaceBytes
=
[]
byte
(
" "
)
pointerChainBytes
=
[]
byte
(
"->"
)
nilAngleBytes
=
[]
byte
(
"<nil>"
)
maxNewlineBytes
=
[]
byte
(
"<max depth reached>
\n
"
)
maxShortBytes
=
[]
byte
(
"<max>"
)
circularBytes
=
[]
byte
(
"<already shown>"
)
circularShortBytes
=
[]
byte
(
"<shown>"
)
invalidAngleBytes
=
[]
byte
(
"<invalid>"
)
openBracketBytes
=
[]
byte
(
"["
)
closeBracketBytes
=
[]
byte
(
"]"
)
percentBytes
=
[]
byte
(
"%"
)
precisionBytes
=
[]
byte
(
"."
)
openAngleBytes
=
[]
byte
(
"<"
)
closeAngleBytes
=
[]
byte
(
">"
)
openMapBytes
=
[]
byte
(
"map["
)
closeMapBytes
=
[]
byte
(
"]"
)
lenEqualsBytes
=
[]
byte
(
"len="
)
capEqualsBytes
=
[]
byte
(
"cap="
)
)
// hexDigits is used to map a decimal value to a hex digit.
var
hexDigits
=
"0123456789abcdef"
// catchPanic handles any panics that might occur during the handleMethods
// calls.
func
catchPanic
(
w
io
.
Writer
,
v
reflect
.
Value
)
{
if
err
:=
recover
();
err
!=
nil
{
w
.
Write
(
panicBytes
)
fmt
.
Fprintf
(
w
,
"%v"
,
err
)
w
.
Write
(
closeParenBytes
)
}
}
// handleMethods attempts to call the Error and String methods on the underlying
// type the passed reflect.Value represents and outputes the result to Writer w.
//
// It handles panics in any called methods by catching and displaying the error
// as the formatted value.
func
handleMethods
(
cs
*
ConfigState
,
w
io
.
Writer
,
v
reflect
.
Value
)
(
handled
bool
)
{
// We need an interface to check if the type implements the error or
// Stringer interface. However, the reflect package won't give us an
// interface on certain things like unexported struct fields in order
// to enforce visibility rules. We use unsafe to bypass these restrictions
// since this package does not mutate the values.
if
!
v
.
CanInterface
()
{
v
=
unsafeReflectValue
(
v
)
}
// Choose whether or not to do error and Stringer interface lookups against
// the base type or a pointer to the base type depending on settings.
// Technically calling one of these methods with a pointer receiver can
// mutate the value, however, types which choose to satisify an error or
// Stringer interface with a pointer receiver should not be mutating their
// state inside these interface methods.
var
viface
interface
{}
if
!
cs
.
DisablePointerMethods
{
if
!
v
.
CanAddr
()
{
v
=
unsafeReflectValue
(
v
)
}
viface
=
v
.
Addr
()
.
Interface
()
}
else
{
if
v
.
CanAddr
()
{
v
=
v
.
Addr
()
}
viface
=
v
.
Interface
()
}
// Is it an error or Stringer?
switch
iface
:=
viface
.
(
type
)
{
case
error
:
defer
catchPanic
(
w
,
v
)
if
cs
.
ContinueOnMethod
{
w
.
Write
(
openParenBytes
)
w
.
Write
([]
byte
(
iface
.
Error
()))
w
.
Write
(
closeParenBytes
)
w
.
Write
(
spaceBytes
)
return
false
}
w
.
Write
([]
byte
(
iface
.
Error
()))
return
true
case
fmt
.
Stringer
:
defer
catchPanic
(
w
,
v
)
if
cs
.
ContinueOnMethod
{
w
.
Write
(
openParenBytes
)
w
.
Write
([]
byte
(
iface
.
String
()))
w
.
Write
(
closeParenBytes
)
w
.
Write
(
spaceBytes
)
return
false
}
w
.
Write
([]
byte
(
iface
.
String
()))
return
true
}
return
false
}
// printBool outputs a boolean value as true or false to Writer w.
func
printBool
(
w
io
.
Writer
,
val
bool
)
{
if
val
{
w
.
Write
(
trueBytes
)
}
else
{
w
.
Write
(
falseBytes
)
}
}
// printInt outputs a signed integer value to Writer w.
func
printInt
(
w
io
.
Writer
,
val
int64
,
base
int
)
{
w
.
Write
([]
byte
(
strconv
.
FormatInt
(
val
,
base
)))
}
// printUint outputs an unsigned integer value to Writer w.
func
printUint
(
w
io
.
Writer
,
val
uint64
,
base
int
)
{
w
.
Write
([]
byte
(
strconv
.
FormatUint
(
val
,
base
)))
}
// printFloat outputs a floating point value using the specified precision,
// which is expected to be 32 or 64bit, to Writer w.
func
printFloat
(
w
io
.
Writer
,
val
float64
,
precision
int
)
{
w
.
Write
([]
byte
(
strconv
.
FormatFloat
(
val
,
'g'
,
-
1
,
precision
)))
}
// printComplex outputs a complex value using the specified float precision
// for the real and imaginary parts to Writer w.
func
printComplex
(
w
io
.
Writer
,
c
complex128
,
floatPrecision
int
)
{
r
:=
real
(
c
)
w
.
Write
(
openParenBytes
)
w
.
Write
([]
byte
(
strconv
.
FormatFloat
(
r
,
'g'
,
-
1
,
floatPrecision
)))
i
:=
imag
(
c
)
if
i
>=
0
{
w
.
Write
(
plusBytes
)
}
w
.
Write
([]
byte
(
strconv
.
FormatFloat
(
i
,
'g'
,
-
1
,
floatPrecision
)))
w
.
Write
(
iBytes
)
w
.
Write
(
closeParenBytes
)
}
// printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x'
// prefix to Writer w.
func
printHexPtr
(
w
io
.
Writer
,
p
uintptr
)
{
// Null pointer.
num
:=
uint64
(
p
)
if
num
==
0
{
w
.
Write
(
nilAngleBytes
)
return
}
// Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix
buf
:=
make
([]
byte
,
18
)
// It's simpler to construct the hex string right to left.
base
:=
uint64
(
16
)
i
:=
len
(
buf
)
-
1
for
num
>=
base
{
buf
[
i
]
=
hexDigits
[
num
%
base
]
num
/=
base
i
--
}
buf
[
i
]
=
hexDigits
[
num
]
// Add '0x' prefix.
i
--
buf
[
i
]
=
'x'
i
--
buf
[
i
]
=
'0'
// Strip unused leading bytes.
buf
=
buf
[
i
:
]
w
.
Write
(
buf
)
}
// valuesSorter implements sort.Interface to allow a slice of reflect.Value
// elements to be sorted.
type
valuesSorter
struct
{
values
[]
reflect
.
Value
strings
[]
string
// either nil or same len and values
cs
*
ConfigState
}
// newValuesSorter initializes a valuesSorter instance, which holds a set of
// surrogate keys on which the data should be sorted. It uses flags in
// ConfigState to decide if and how to populate those surrogate keys.
func
newValuesSorter
(
values
[]
reflect
.
Value
,
cs
*
ConfigState
)
sort
.
Interface
{
vs
:=
&
valuesSorter
{
values
:
values
,
cs
:
cs
}
if
canSortSimply
(
vs
.
values
[
0
]
.
Kind
())
{
return
vs
}
if
!
cs
.
DisableMethods
{
vs
.
strings
=
make
([]
string
,
len
(
values
))
for
i
:=
range
vs
.
values
{
b
:=
bytes
.
Buffer
{}
if
!
handleMethods
(
cs
,
&
b
,
vs
.
values
[
i
])
{
vs
.
strings
=
nil
break
}
vs
.
strings
[
i
]
=
b
.
String
()
}
}
if
vs
.
strings
==
nil
&&
cs
.
SpewKeys
{
vs
.
strings
=
make
([]
string
,
len
(
values
))
for
i
:=
range
vs
.
values
{
vs
.
strings
[
i
]
=
Sprintf
(
"%#v"
,
vs
.
values
[
i
]
.
Interface
())
}
}
return
vs
}
// canSortSimply tests whether a reflect.Kind is a primitive that can be sorted
// directly, or whether it should be considered for sorting by surrogate keys
// (if the ConfigState allows it).
func
canSortSimply
(
kind
reflect
.
Kind
)
bool
{
// This switch parallels valueSortLess, except for the default case.
switch
kind
{
case
reflect
.
Bool
:
return
true
case
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
,
reflect
.
Int
:
return
true
case
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
,
reflect
.
Uint
:
return
true
case
reflect
.
Float32
,
reflect
.
Float64
:
return
true
case
reflect
.
String
:
return
true
case
reflect
.
Uintptr
:
return
true
case
reflect
.
Array
:
return
true
}
return
false
}
// Len returns the number of values in the slice. It is part of the
// sort.Interface implementation.
func
(
s
*
valuesSorter
)
Len
()
int
{
return
len
(
s
.
values
)
}
// Swap swaps the values at the passed indices. It is part of the
// sort.Interface implementation.
func
(
s
*
valuesSorter
)
Swap
(
i
,
j
int
)
{
s
.
values
[
i
],
s
.
values
[
j
]
=
s
.
values
[
j
],
s
.
values
[
i
]
if
s
.
strings
!=
nil
{
s
.
strings
[
i
],
s
.
strings
[
j
]
=
s
.
strings
[
j
],
s
.
strings
[
i
]
}
}
// valueSortLess returns whether the first value should sort before the second
// value. It is used by valueSorter.Less as part of the sort.Interface
// implementation.
func
valueSortLess
(
a
,
b
reflect
.
Value
)
bool
{
switch
a
.
Kind
()
{
case
reflect
.
Bool
:
return
!
a
.
Bool
()
&&
b
.
Bool
()
case
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
,
reflect
.
Int
:
return
a
.
Int
()
<
b
.
Int
()
case
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
,
reflect
.
Uint
:
return
a
.
Uint
()
<
b
.
Uint
()
case
reflect
.
Float32
,
reflect
.
Float64
:
return
a
.
Float
()
<
b
.
Float
()
case
reflect
.
String
:
return
a
.
String
()
<
b
.
String
()
case
reflect
.
Uintptr
:
return
a
.
Uint
()
<
b
.
Uint
()
case
reflect
.
Array
:
// Compare the contents of both arrays.
l
:=
a
.
Len
()
for
i
:=
0
;
i
<
l
;
i
++
{
av
:=
a
.
Index
(
i
)
bv
:=
b
.
Index
(
i
)
if
av
.
Interface
()
==
bv
.
Interface
()
{
continue
}
return
valueSortLess
(
av
,
bv
)
}
}
return
a
.
String
()
<
b
.
String
()
}
// Less returns whether the value at index i should sort before the
// value at index j. It is part of the sort.Interface implementation.
func
(
s
*
valuesSorter
)
Less
(
i
,
j
int
)
bool
{
if
s
.
strings
==
nil
{
return
valueSortLess
(
s
.
values
[
i
],
s
.
values
[
j
])
}
return
s
.
strings
[
i
]
<
s
.
strings
[
j
]
}
// sortValues is a sort function that handles both native types and any type that
// can be converted to error or Stringer. Other inputs are sorted according to
// their Value.String() value to ensure display stability.
func
sortValues
(
values
[]
reflect
.
Value
,
cs
*
ConfigState
)
{
if
len
(
values
)
==
0
{
return
}
sort
.
Sort
(
newValuesSorter
(
values
,
cs
))
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/common_test.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package
spew_test
import
(
"fmt"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
)
// custom type to test Stinger interface on non-pointer receiver.
type
stringer
string
// String implements the Stringer interface for testing invocation of custom
// stringers on types with non-pointer receivers.
func
(
s
stringer
)
String
()
string
{
return
"stringer "
+
string
(
s
)
}
// custom type to test Stinger interface on pointer receiver.
type
pstringer
string
// String implements the Stringer interface for testing invocation of custom
// stringers on types with only pointer receivers.
func
(
s
*
pstringer
)
String
()
string
{
return
"stringer "
+
string
(
*
s
)
}
// xref1 and xref2 are cross referencing structs for testing circular reference
// detection.
type
xref1
struct
{
ps2
*
xref2
}
type
xref2
struct
{
ps1
*
xref1
}
// indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular
// reference for testing detection.
type
indirCir1
struct
{
ps2
*
indirCir2
}
type
indirCir2
struct
{
ps3
*
indirCir3
}
type
indirCir3
struct
{
ps1
*
indirCir1
}
// embed is used to test embedded structures.
type
embed
struct
{
a
string
}
// embedwrap is used to test embedded structures.
type
embedwrap
struct
{
*
embed
e
*
embed
}
// panicer is used to intentionally cause a panic for testing spew properly
// handles them
type
panicer
int
func
(
p
panicer
)
String
()
string
{
panic
(
"test panic"
)
}
// customError is used to test custom error interface invocation.
type
customError
int
func
(
e
customError
)
Error
()
string
{
return
fmt
.
Sprintf
(
"error: %d"
,
int
(
e
))
}
// stringizeWants converts a slice of wanted test output into a format suitable
// for a test error message.
func
stringizeWants
(
wants
[]
string
)
string
{
s
:=
""
for
i
,
want
:=
range
wants
{
if
i
>
0
{
s
+=
fmt
.
Sprintf
(
"want%d: %s"
,
i
+
1
,
want
)
}
else
{
s
+=
"want: "
+
want
}
}
return
s
}
// testFailed returns whether or not a test failed by checking if the result
// of the test is in the slice of wanted strings.
func
testFailed
(
result
string
,
wants
[]
string
)
bool
{
for
_
,
want
:=
range
wants
{
if
result
==
want
{
return
false
}
}
return
true
}
type
sortableStruct
struct
{
x
int
}
func
(
ss
sortableStruct
)
String
()
string
{
return
fmt
.
Sprintf
(
"ss.%d"
,
ss
.
x
)
}
type
unsortableStruct
struct
{
x
int
}
type
sortTestCase
struct
{
input
[]
reflect
.
Value
expected
[]
reflect
.
Value
}
func
helpTestSortValues
(
tests
[]
sortTestCase
,
cs
*
spew
.
ConfigState
,
t
*
testing
.
T
)
{
getInterfaces
:=
func
(
values
[]
reflect
.
Value
)
[]
interface
{}
{
interfaces
:=
[]
interface
{}{}
for
_
,
v
:=
range
values
{
interfaces
=
append
(
interfaces
,
v
.
Interface
())
}
return
interfaces
}
for
_
,
test
:=
range
tests
{
spew
.
SortValues
(
test
.
input
,
cs
)
// reflect.DeepEqual cannot really make sense of reflect.Value,
// probably because of all the pointer tricks. For instance,
// v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{}
// instead.
input
:=
getInterfaces
(
test
.
input
)
expected
:=
getInterfaces
(
test
.
expected
)
if
!
reflect
.
DeepEqual
(
input
,
expected
)
{
t
.
Errorf
(
"Sort mismatch:
\n
%v != %v"
,
input
,
expected
)
}
}
}
// TestSortValues ensures the sort functionality for relect.Value based sorting
// works as intended.
func
TestSortValues
(
t
*
testing
.
T
)
{
v
:=
reflect
.
ValueOf
a
:=
v
(
"a"
)
b
:=
v
(
"b"
)
c
:=
v
(
"c"
)
embedA
:=
v
(
embed
{
"a"
})
embedB
:=
v
(
embed
{
"b"
})
embedC
:=
v
(
embed
{
"c"
})
tests
:=
[]
sortTestCase
{
// No values.
{
[]
reflect
.
Value
{},
[]
reflect
.
Value
{},
},
// Bools.
{
[]
reflect
.
Value
{
v
(
false
),
v
(
true
),
v
(
false
)},
[]
reflect
.
Value
{
v
(
false
),
v
(
false
),
v
(
true
)},
},
// Ints.
{
[]
reflect
.
Value
{
v
(
2
),
v
(
1
),
v
(
3
)},
[]
reflect
.
Value
{
v
(
1
),
v
(
2
),
v
(
3
)},
},
// Uints.
{
[]
reflect
.
Value
{
v
(
uint8
(
2
)),
v
(
uint8
(
1
)),
v
(
uint8
(
3
))},
[]
reflect
.
Value
{
v
(
uint8
(
1
)),
v
(
uint8
(
2
)),
v
(
uint8
(
3
))},
},
// Floats.
{
[]
reflect
.
Value
{
v
(
2.0
),
v
(
1.0
),
v
(
3.0
)},
[]
reflect
.
Value
{
v
(
1.0
),
v
(
2.0
),
v
(
3.0
)},
},
// Strings.
{
[]
reflect
.
Value
{
b
,
a
,
c
},
[]
reflect
.
Value
{
a
,
b
,
c
},
},
// Array
{
[]
reflect
.
Value
{
v
([
3
]
int
{
3
,
2
,
1
}),
v
([
3
]
int
{
1
,
3
,
2
}),
v
([
3
]
int
{
1
,
2
,
3
})},
[]
reflect
.
Value
{
v
([
3
]
int
{
1
,
2
,
3
}),
v
([
3
]
int
{
1
,
3
,
2
}),
v
([
3
]
int
{
3
,
2
,
1
})},
},
// Uintptrs.
{
[]
reflect
.
Value
{
v
(
uintptr
(
2
)),
v
(
uintptr
(
1
)),
v
(
uintptr
(
3
))},
[]
reflect
.
Value
{
v
(
uintptr
(
1
)),
v
(
uintptr
(
2
)),
v
(
uintptr
(
3
))},
},
// SortableStructs.
{
// Note: not sorted - DisableMethods is set.
[]
reflect
.
Value
{
v
(
sortableStruct
{
2
}),
v
(
sortableStruct
{
1
}),
v
(
sortableStruct
{
3
})},
[]
reflect
.
Value
{
v
(
sortableStruct
{
2
}),
v
(
sortableStruct
{
1
}),
v
(
sortableStruct
{
3
})},
},
// UnsortableStructs.
{
// Note: not sorted - SpewKeys is false.
[]
reflect
.
Value
{
v
(
unsortableStruct
{
2
}),
v
(
unsortableStruct
{
1
}),
v
(
unsortableStruct
{
3
})},
[]
reflect
.
Value
{
v
(
unsortableStruct
{
2
}),
v
(
unsortableStruct
{
1
}),
v
(
unsortableStruct
{
3
})},
},
// Invalid.
{
[]
reflect
.
Value
{
embedB
,
embedA
,
embedC
},
[]
reflect
.
Value
{
embedB
,
embedA
,
embedC
},
},
}
cs
:=
spew
.
ConfigState
{
DisableMethods
:
true
,
SpewKeys
:
false
}
helpTestSortValues
(
tests
,
&
cs
,
t
)
}
// TestSortValuesWithMethods ensures the sort functionality for relect.Value
// based sorting works as intended when using string methods.
func
TestSortValuesWithMethods
(
t
*
testing
.
T
)
{
v
:=
reflect
.
ValueOf
a
:=
v
(
"a"
)
b
:=
v
(
"b"
)
c
:=
v
(
"c"
)
tests
:=
[]
sortTestCase
{
// Ints.
{
[]
reflect
.
Value
{
v
(
2
),
v
(
1
),
v
(
3
)},
[]
reflect
.
Value
{
v
(
1
),
v
(
2
),
v
(
3
)},
},
// Strings.
{
[]
reflect
.
Value
{
b
,
a
,
c
},
[]
reflect
.
Value
{
a
,
b
,
c
},
},
// SortableStructs.
{
[]
reflect
.
Value
{
v
(
sortableStruct
{
2
}),
v
(
sortableStruct
{
1
}),
v
(
sortableStruct
{
3
})},
[]
reflect
.
Value
{
v
(
sortableStruct
{
1
}),
v
(
sortableStruct
{
2
}),
v
(
sortableStruct
{
3
})},
},
// UnsortableStructs.
{
// Note: not sorted - SpewKeys is false.
[]
reflect
.
Value
{
v
(
unsortableStruct
{
2
}),
v
(
unsortableStruct
{
1
}),
v
(
unsortableStruct
{
3
})},
[]
reflect
.
Value
{
v
(
unsortableStruct
{
2
}),
v
(
unsortableStruct
{
1
}),
v
(
unsortableStruct
{
3
})},
},
}
cs
:=
spew
.
ConfigState
{
DisableMethods
:
false
,
SpewKeys
:
false
}
helpTestSortValues
(
tests
,
&
cs
,
t
)
}
// TestSortValuesWithSpew ensures the sort functionality for relect.Value
// based sorting works as intended when using spew to stringify keys.
func
TestSortValuesWithSpew
(
t
*
testing
.
T
)
{
v
:=
reflect
.
ValueOf
a
:=
v
(
"a"
)
b
:=
v
(
"b"
)
c
:=
v
(
"c"
)
tests
:=
[]
sortTestCase
{
// Ints.
{
[]
reflect
.
Value
{
v
(
2
),
v
(
1
),
v
(
3
)},
[]
reflect
.
Value
{
v
(
1
),
v
(
2
),
v
(
3
)},
},
// Strings.
{
[]
reflect
.
Value
{
b
,
a
,
c
},
[]
reflect
.
Value
{
a
,
b
,
c
},
},
// SortableStructs.
{
[]
reflect
.
Value
{
v
(
sortableStruct
{
2
}),
v
(
sortableStruct
{
1
}),
v
(
sortableStruct
{
3
})},
[]
reflect
.
Value
{
v
(
sortableStruct
{
1
}),
v
(
sortableStruct
{
2
}),
v
(
sortableStruct
{
3
})},
},
// UnsortableStructs.
{
[]
reflect
.
Value
{
v
(
unsortableStruct
{
2
}),
v
(
unsortableStruct
{
1
}),
v
(
unsortableStruct
{
3
})},
[]
reflect
.
Value
{
v
(
unsortableStruct
{
1
}),
v
(
unsortableStruct
{
2
}),
v
(
unsortableStruct
{
3
})},
},
}
cs
:=
spew
.
ConfigState
{
DisableMethods
:
true
,
SpewKeys
:
true
}
helpTestSortValues
(
tests
,
&
cs
,
t
)
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/config.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package
spew
import
(
"bytes"
"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.
//
// NOTE: Circular data structures are properly detected, so it is not
// necessary to set this value unless you specifically want to limit deeply
// nested data structures.
MaxDepth
int
// DisableMethods specifies whether or not error and Stringer interfaces are
// invoked for types that implement them.
DisableMethods
bool
// DisablePointerMethods specifies whether or not to check for and invoke
// error and Stringer interfaces on types which only accept a pointer
// receiver when the current type is not a pointer.
//
// NOTE: This might be an unsafe action since calling one of these methods
// with a pointer receiver could technically mutate the value, however,
// in practice, types which choose to satisify an error or Stringer
// interface with a pointer receiver should not be mutating their state
// inside these interface methods.
DisablePointerMethods
bool
// ContinueOnMethod specifies whether or not recursion should continue once
// a custom error or Stringer interface is invoked. The default, false,
// means it will print the results of invoking the custom error or Stringer
// interface and return immediately instead of continuing to recurse into
// the internals of the data type.
//
// NOTE: This flag does not have any effect if method invocation is disabled
// via the DisableMethods or DisablePointerMethods options.
ContinueOnMethod
bool
// SortKeys specifies map keys should be sorted before being printed. Use
// this to have a more deterministic, diffable output. Note that only
// native types (bool, int, uint, floats, uintptr and string) and types
// that support the error or Stringer interfaces (if methods are
// enabled) are supported, with other types sorted according to the
// reflect.Value.String() output which guarantees display stability.
SortKeys
bool
// SpewKeys specifies that, as a last resort attempt, map keys should
// be spewed to strings and sorted by those strings. This is only
// considered if SortKeys is true.
SpewKeys
bool
}
// Config is the active configuration of the top-level functions.
// The configuration can be changed by modifying the contents of spew.Config.
var
Config
=
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
)
...
)
}
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b))
func
(
c
*
ConfigState
)
Sprint
(
a
...
interface
{})
string
{
return
fmt
.
Sprint
(
c
.
convertArgs
(
a
)
...
)
}
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
// passed with a Formatter interface returned by c.NewFormatter. It returns
// the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b))
func
(
c
*
ConfigState
)
Sprintf
(
format
string
,
a
...
interface
{})
string
{
return
fmt
.
Sprintf
(
format
,
c
.
convertArgs
(
a
)
...
)
}
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
// were passed with a Formatter interface returned by c.NewFormatter. It
// returns the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b))
func
(
c
*
ConfigState
)
Sprintln
(
a
...
interface
{})
string
{
return
fmt
.
Sprintln
(
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
* Byte arrays and slices are dumped like the hexdump -C command which
includes offsets, byte values in hex, and ASCII output
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 or Sdump to
get the formatted result as a string.
*/
func
(
c
*
ConfigState
)
Dump
(
a
...
interface
{})
{
fdump
(
c
,
os
.
Stdout
,
a
...
)
}
// Sdump returns a string with the passed arguments formatted exactly the same
// as Dump.
func
(
c
*
ConfigState
)
Sdump
(
a
...
interface
{})
string
{
var
buf
bytes
.
Buffer
fdump
(
c
,
&
buf
,
a
...
)
return
buf
.
String
()
}
// 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
// ContinueOnMethod: false
// SortKeys: false
func
NewDefaultConfig
()
*
ConfigState
{
return
&
ConfigState
{
Indent
:
" "
}
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/doc.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
Package spew implements a deep pretty printer for Go data structures to aid in
debugging.
A quick overview of the additional features spew provides over the built-in
printing facilities for Go data types are as follows:
* 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
* Byte arrays and slices are dumped like the hexdump -C command which
includes offsets, byte values in hex, and ASCII output (only when using
Dump style)
There are two different approaches spew allows for dumping Go data structures:
* Dump style which prints with newlines, customizable indentation,
and additional debug information such as types and all pointer addresses
used to indirect to the final value
* A custom Formatter interface that integrates cleanly with the standard fmt
package and replaces %v, %+v, %#v, and %#+v to provide inline printing
similar to the default %v while providing the additional functionality
outlined above and passing unsupported format verbs such as %x and %q
along to fmt
Quick Start
This section demonstrates how to quickly get started with spew. See the
sections below for further details on formatting and configuration options.
To dump a variable with full newlines, indentation, type, and pointer
information use Dump, Fdump, or Sdump:
spew.Dump(myVar1, myVar2, ...)
spew.Fdump(someWriter, myVar1, myVar2, ...)
str := spew.Sdump(myVar1, myVar2, ...)
Alternatively, if you would prefer to use format strings with a compacted inline
printing style, use the convenience wrappers Printf, Fprintf, etc with
%v (most compact), %+v (adds pointer addresses), %#v (adds types), or
%#+v (adds types and pointer addresses):
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
Configuration Options
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 ConfigState instance that provides methods
equivalent to the top-level functions. This allows concurrent configuration
options. See the ConfigState documentation for more details.
The following configuration options are available:
* Indent
String to use for each indentation level for Dump functions.
It is a single space by default. A popular alternative is "\t".
* MaxDepth
Maximum number of levels to descend into nested data structures.
There is no limit by default.
* DisableMethods
Disables invocation of error and Stringer interface methods.
Method invocation is enabled by default.
* DisablePointerMethods
Disables invocation of error and Stringer interface methods on types
which only accept pointer receivers from non-pointer variables.
Pointer method invocation is enabled by default.
* ContinueOnMethod
Enables recursion into types after invoking error and Stringer interface
methods. Recursion after method invocation is disabled by default.
* SortKeys
Specifies map keys should be sorted before being printed. Use
this to have a more deterministic, diffable output. Note that
only native types (bool, int, uint, floats, uintptr and string)
and types which implement error or Stringer interfaces are
supported with other types sorted according to the
reflect.Value.String() output which guarantees display
stability. Natural map order is used by default.
* SpewKeys
Specifies that, as a last resort attempt, map keys should be
spewed to strings and sorted by those strings. This is only
considered if SortKeys is true.
Dump Usage
Simply call spew.Dump with a list of variables you want to dump:
spew.Dump(myVar1, myVar2, ...)
You may also call spew.Fdump if you would prefer to output to an arbitrary
io.Writer. For example, to dump to standard error:
spew.Fdump(os.Stderr, myVar1, myVar2, ...)
A third option is to call spew.Sdump to get the formatted output as a string:
str := spew.Sdump(myVar1, myVar2, ...)
Sample Dump Output
See the Dump example for details on the setup of the types and variables being
shown here.
(main.Foo) {
unexportedField: (*main.Bar)(0xf84002e210)({
flag: (main.Flag) flagTwo,
data: (uintptr) <nil>
}),
ExportedField: (map[interface {}]interface {}) (len=1) {
(string) (len=3) "one": (bool) true
}
}
Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C
command as shown.
([]uint8) (len=32 cap=32) {
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
00000020 31 32 |12|
}
Custom Formatter
Spew provides a custom formatter that implements the fmt.Formatter interface
so that 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).
Custom Formatter Usage
The simplest way to make use of the spew custom formatter is to call one of the
convenience functions such as spew.Printf, spew.Println, or spew.Printf. The
functions have syntax you are most likely already familiar with:
spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
spew.Println(myVar, myVar2)
spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2)
spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4)
See the Index for the full list convenience functions.
Sample Formatter Output
Double pointer to a uint8:
%v: <**>5
%+v: <**>(0xf8400420d0->0xf8400420c8)5
%#v: (**uint8)5
%#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5
Pointer to circular struct with a uint8 field and a pointer to itself:
%v: <*>{1 <*><shown>}
%+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)<shown>}
%#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)<shown>}
%#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)<shown>}
See the Printf example for details on the setup of variables being shown
here.
Errors
Since it is possible for custom Stringer/error interfaces to panic, spew
detects them and handles them internally by printing the panic information
inline with the output. Since spew is intended to provide deep pretty printing
capabilities on structures, it intentionally does not return any errors.
*/
package
spew
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package
spew
import
(
"bytes"
"encoding/hex"
"fmt"
"io"
"os"
"reflect"
"regexp"
"strconv"
"strings"
)
var
(
// uint8Type is a reflect.Type representing a uint8. It is used to
// convert cgo types to uint8 slices for hexdumping.
uint8Type
=
reflect
.
TypeOf
(
uint8
(
0
))
// cCharRE is a regular expression that matches a cgo char.
// It is used to detect character arrays to hexdump them.
cCharRE
=
regexp
.
MustCompile
(
"^.*
\\
._Ctype_char$"
)
// cUnsignedCharRE is a regular expression that matches a cgo unsigned
// char. It is used to detect unsigned character arrays to hexdump
// them.
cUnsignedCharRE
=
regexp
.
MustCompile
(
"^.*
\\
._Ctype_unsignedchar$"
)
// cUint8tCharRE is a regular expression that matches a cgo uint8_t.
// It is used to detect uint8_t arrays to hexdump them.
cUint8tCharRE
=
regexp
.
MustCompile
(
"^.*
\\
._Ctype_uint8_t$"
)
)
// dumpState contains information about the state of a dump operation.
type
dumpState
struct
{
w
io
.
Writer
depth
int
pointers
map
[
uintptr
]
int
ignoreNextType
bool
ignoreNextIndent
bool
cs
*
ConfigState
}
// indent performs indentation according to the depth level and cs.Indent
// option.
func
(
d
*
dumpState
)
indent
()
{
if
d
.
ignoreNextIndent
{
d
.
ignoreNextIndent
=
false
return
}
d
.
w
.
Write
(
bytes
.
Repeat
([]
byte
(
d
.
cs
.
Indent
),
d
.
depth
))
}
// unpackValue returns values inside of non-nil interfaces when possible.
// This is useful for data types like structs, arrays, slices, and maps which
// can contain varying types packed inside an interface.
func
(
d
*
dumpState
)
unpackValue
(
v
reflect
.
Value
)
reflect
.
Value
{
if
v
.
Kind
()
==
reflect
.
Interface
&&
!
v
.
IsNil
()
{
v
=
v
.
Elem
()
}
return
v
}
// dumpPtr handles formatting of pointers by indirecting them as necessary.
func
(
d
*
dumpState
)
dumpPtr
(
v
reflect
.
Value
)
{
// Remove pointers at or below the current depth from map used to detect
// circular refs.
for
k
,
depth
:=
range
d
.
pointers
{
if
depth
>=
d
.
depth
{
delete
(
d
.
pointers
,
k
)
}
}
// Keep list of all dereferenced pointers to show later.
pointerChain
:=
make
([]
uintptr
,
0
)
// Figure out how many levels of indirection there are by dereferencing
// pointers and unpacking interfaces down the chain while detecting circular
// references.
nilFound
:=
false
cycleFound
:=
false
indirects
:=
0
ve
:=
v
for
ve
.
Kind
()
==
reflect
.
Ptr
{
if
ve
.
IsNil
()
{
nilFound
=
true
break
}
indirects
++
addr
:=
ve
.
Pointer
()
pointerChain
=
append
(
pointerChain
,
addr
)
if
pd
,
ok
:=
d
.
pointers
[
addr
];
ok
&&
pd
<
d
.
depth
{
cycleFound
=
true
indirects
--
break
}
d
.
pointers
[
addr
]
=
d
.
depth
ve
=
ve
.
Elem
()
if
ve
.
Kind
()
==
reflect
.
Interface
{
if
ve
.
IsNil
()
{
nilFound
=
true
break
}
ve
=
ve
.
Elem
()
}
}
// Display type information.
d
.
w
.
Write
(
openParenBytes
)
d
.
w
.
Write
(
bytes
.
Repeat
(
asteriskBytes
,
indirects
))
d
.
w
.
Write
([]
byte
(
ve
.
Type
()
.
String
()))
d
.
w
.
Write
(
closeParenBytes
)
// Display pointer information.
if
len
(
pointerChain
)
>
0
{
d
.
w
.
Write
(
openParenBytes
)
for
i
,
addr
:=
range
pointerChain
{
if
i
>
0
{
d
.
w
.
Write
(
pointerChainBytes
)
}
printHexPtr
(
d
.
w
,
addr
)
}
d
.
w
.
Write
(
closeParenBytes
)
}
// Display dereferenced value.
d
.
w
.
Write
(
openParenBytes
)
switch
{
case
nilFound
==
true
:
d
.
w
.
Write
(
nilAngleBytes
)
case
cycleFound
==
true
:
d
.
w
.
Write
(
circularBytes
)
default
:
d
.
ignoreNextType
=
true
d
.
dump
(
ve
)
}
d
.
w
.
Write
(
closeParenBytes
)
}
// dumpSlice handles formatting of arrays and slices. Byte (uint8 under
// reflection) arrays and slices are dumped in hexdump -C fashion.
func
(
d
*
dumpState
)
dumpSlice
(
v
reflect
.
Value
)
{
// Determine whether this type should be hex dumped or not. Also,
// for types which should be hexdumped, try to use the underlying data
// first, then fall back to trying to convert them to a uint8 slice.
var
buf
[]
uint8
doConvert
:=
false
doHexDump
:=
false
numEntries
:=
v
.
Len
()
if
numEntries
>
0
{
vt
:=
v
.
Index
(
0
)
.
Type
()
vts
:=
vt
.
String
()
switch
{
// C types that need to be converted.
case
cCharRE
.
MatchString
(
vts
)
:
fallthrough
case
cUnsignedCharRE
.
MatchString
(
vts
)
:
fallthrough
case
cUint8tCharRE
.
MatchString
(
vts
)
:
doConvert
=
true
// Try to use existing uint8 slices and fall back to converting
// and copying if that fails.
case
vt
.
Kind
()
==
reflect
.
Uint8
:
// We need an addressable interface to convert the type back
// into a byte slice. However, the reflect package won't give
// us an interface on certain things like unexported struct
// fields in order to enforce visibility rules. We use unsafe
// to bypass these restrictions since this package does not
// mutate the values.
vs
:=
v
if
!
vs
.
CanInterface
()
||
!
vs
.
CanAddr
()
{
vs
=
unsafeReflectValue
(
vs
)
}
vs
=
vs
.
Slice
(
0
,
numEntries
)
// Use the existing uint8 slice if it can be type
// asserted.
iface
:=
vs
.
Interface
()
if
slice
,
ok
:=
iface
.
([]
uint8
);
ok
{
buf
=
slice
doHexDump
=
true
break
}
// The underlying data needs to be converted if it can't
// be type asserted to a uint8 slice.
doConvert
=
true
}
// Copy and convert the underlying type if needed.
if
doConvert
&&
vt
.
ConvertibleTo
(
uint8Type
)
{
// Convert and copy each element into a uint8 byte
// slice.
buf
=
make
([]
uint8
,
numEntries
)
for
i
:=
0
;
i
<
numEntries
;
i
++
{
vv
:=
v
.
Index
(
i
)
buf
[
i
]
=
uint8
(
vv
.
Convert
(
uint8Type
)
.
Uint
())
}
doHexDump
=
true
}
}
// Hexdump the entire slice as needed.
if
doHexDump
{
indent
:=
strings
.
Repeat
(
d
.
cs
.
Indent
,
d
.
depth
)
str
:=
indent
+
hex
.
Dump
(
buf
)
str
=
strings
.
Replace
(
str
,
"
\n
"
,
"
\n
"
+
indent
,
-
1
)
str
=
strings
.
TrimRight
(
str
,
d
.
cs
.
Indent
)
d
.
w
.
Write
([]
byte
(
str
))
return
}
// Recursively call dump for each item.
for
i
:=
0
;
i
<
numEntries
;
i
++
{
d
.
dump
(
d
.
unpackValue
(
v
.
Index
(
i
)))
if
i
<
(
numEntries
-
1
)
{
d
.
w
.
Write
(
commaNewlineBytes
)
}
else
{
d
.
w
.
Write
(
newlineBytes
)
}
}
}
// dump is the main workhorse for dumping a value. It uses the passed reflect
// value to figure out what kind of object we are dealing with and formats it
// appropriately. It is a recursive function, however circular data structures
// are detected and handled properly.
func
(
d
*
dumpState
)
dump
(
v
reflect
.
Value
)
{
// Handle invalid reflect values immediately.
kind
:=
v
.
Kind
()
if
kind
==
reflect
.
Invalid
{
d
.
w
.
Write
(
invalidAngleBytes
)
return
}
// Handle pointers specially.
if
kind
==
reflect
.
Ptr
{
d
.
indent
()
d
.
dumpPtr
(
v
)
return
}
// Print type information unless already handled elsewhere.
if
!
d
.
ignoreNextType
{
d
.
indent
()
d
.
w
.
Write
(
openParenBytes
)
d
.
w
.
Write
([]
byte
(
v
.
Type
()
.
String
()))
d
.
w
.
Write
(
closeParenBytes
)
d
.
w
.
Write
(
spaceBytes
)
}
d
.
ignoreNextType
=
false
// Display length and capacity if the built-in len and cap functions
// work with the value's kind and the len/cap itself is non-zero.
valueLen
,
valueCap
:=
0
,
0
switch
v
.
Kind
()
{
case
reflect
.
Array
,
reflect
.
Slice
,
reflect
.
Chan
:
valueLen
,
valueCap
=
v
.
Len
(),
v
.
Cap
()
case
reflect
.
Map
,
reflect
.
String
:
valueLen
=
v
.
Len
()
}
if
valueLen
!=
0
||
valueCap
!=
0
{
d
.
w
.
Write
(
openParenBytes
)
if
valueLen
!=
0
{
d
.
w
.
Write
(
lenEqualsBytes
)
printInt
(
d
.
w
,
int64
(
valueLen
),
10
)
}
if
valueCap
!=
0
{
if
valueLen
!=
0
{
d
.
w
.
Write
(
spaceBytes
)
}
d
.
w
.
Write
(
capEqualsBytes
)
printInt
(
d
.
w
,
int64
(
valueCap
),
10
)
}
d
.
w
.
Write
(
closeParenBytes
)
d
.
w
.
Write
(
spaceBytes
)
}
// Call Stringer/error interfaces if they exist and the handle methods flag
// is enabled
if
!
d
.
cs
.
DisableMethods
{
if
(
kind
!=
reflect
.
Invalid
)
&&
(
kind
!=
reflect
.
Interface
)
{
if
handled
:=
handleMethods
(
d
.
cs
,
d
.
w
,
v
);
handled
{
return
}
}
}
switch
kind
{
case
reflect
.
Invalid
:
// Do nothing. We should never get here since invalid has already
// been handled above.
case
reflect
.
Bool
:
printBool
(
d
.
w
,
v
.
Bool
())
case
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
,
reflect
.
Int
:
printInt
(
d
.
w
,
v
.
Int
(),
10
)
case
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
,
reflect
.
Uint
:
printUint
(
d
.
w
,
v
.
Uint
(),
10
)
case
reflect
.
Float32
:
printFloat
(
d
.
w
,
v
.
Float
(),
32
)
case
reflect
.
Float64
:
printFloat
(
d
.
w
,
v
.
Float
(),
64
)
case
reflect
.
Complex64
:
printComplex
(
d
.
w
,
v
.
Complex
(),
32
)
case
reflect
.
Complex128
:
printComplex
(
d
.
w
,
v
.
Complex
(),
64
)
case
reflect
.
Slice
:
if
v
.
IsNil
()
{
d
.
w
.
Write
(
nilAngleBytes
)
break
}
fallthrough
case
reflect
.
Array
:
d
.
w
.
Write
(
openBraceNewlineBytes
)
d
.
depth
++
if
(
d
.
cs
.
MaxDepth
!=
0
)
&&
(
d
.
depth
>
d
.
cs
.
MaxDepth
)
{
d
.
indent
()
d
.
w
.
Write
(
maxNewlineBytes
)
}
else
{
d
.
dumpSlice
(
v
)
}
d
.
depth
--
d
.
indent
()
d
.
w
.
Write
(
closeBraceBytes
)
case
reflect
.
String
:
d
.
w
.
Write
([]
byte
(
strconv
.
Quote
(
v
.
String
())))
case
reflect
.
Interface
:
// The only time we should get here is for nil interfaces due to
// unpackValue calls.
if
v
.
IsNil
()
{
d
.
w
.
Write
(
nilAngleBytes
)
}
case
reflect
.
Ptr
:
// Do nothing. We should never get here since pointers have already
// been handled above.
case
reflect
.
Map
:
// nil maps should be indicated as different than empty maps
if
v
.
IsNil
()
{
d
.
w
.
Write
(
nilAngleBytes
)
break
}
d
.
w
.
Write
(
openBraceNewlineBytes
)
d
.
depth
++
if
(
d
.
cs
.
MaxDepth
!=
0
)
&&
(
d
.
depth
>
d
.
cs
.
MaxDepth
)
{
d
.
indent
()
d
.
w
.
Write
(
maxNewlineBytes
)
}
else
{
numEntries
:=
v
.
Len
()
keys
:=
v
.
MapKeys
()
if
d
.
cs
.
SortKeys
{
sortValues
(
keys
,
d
.
cs
)
}
for
i
,
key
:=
range
keys
{
d
.
dump
(
d
.
unpackValue
(
key
))
d
.
w
.
Write
(
colonSpaceBytes
)
d
.
ignoreNextIndent
=
true
d
.
dump
(
d
.
unpackValue
(
v
.
MapIndex
(
key
)))
if
i
<
(
numEntries
-
1
)
{
d
.
w
.
Write
(
commaNewlineBytes
)
}
else
{
d
.
w
.
Write
(
newlineBytes
)
}
}
}
d
.
depth
--
d
.
indent
()
d
.
w
.
Write
(
closeBraceBytes
)
case
reflect
.
Struct
:
d
.
w
.
Write
(
openBraceNewlineBytes
)
d
.
depth
++
if
(
d
.
cs
.
MaxDepth
!=
0
)
&&
(
d
.
depth
>
d
.
cs
.
MaxDepth
)
{
d
.
indent
()
d
.
w
.
Write
(
maxNewlineBytes
)
}
else
{
vt
:=
v
.
Type
()
numFields
:=
v
.
NumField
()
for
i
:=
0
;
i
<
numFields
;
i
++
{
d
.
indent
()
vtf
:=
vt
.
Field
(
i
)
d
.
w
.
Write
([]
byte
(
vtf
.
Name
))
d
.
w
.
Write
(
colonSpaceBytes
)
d
.
ignoreNextIndent
=
true
d
.
dump
(
d
.
unpackValue
(
v
.
Field
(
i
)))
if
i
<
(
numFields
-
1
)
{
d
.
w
.
Write
(
commaNewlineBytes
)
}
else
{
d
.
w
.
Write
(
newlineBytes
)
}
}
}
d
.
depth
--
d
.
indent
()
d
.
w
.
Write
(
closeBraceBytes
)
case
reflect
.
Uintptr
:
printHexPtr
(
d
.
w
,
uintptr
(
v
.
Uint
()))
case
reflect
.
UnsafePointer
,
reflect
.
Chan
,
reflect
.
Func
:
printHexPtr
(
d
.
w
,
v
.
Pointer
())
// There were not any other types at the time this code was written, but
// fall back to letting the default fmt package handle it in case any new
// types are added.
default
:
if
v
.
CanInterface
()
{
fmt
.
Fprintf
(
d
.
w
,
"%v"
,
v
.
Interface
())
}
else
{
fmt
.
Fprintf
(
d
.
w
,
"%v"
,
v
.
String
())
}
}
}
// fdump is a helper function to consolidate the logic from the various public
// methods which take varying writers and config states.
func
fdump
(
cs
*
ConfigState
,
w
io
.
Writer
,
a
...
interface
{})
{
for
_
,
arg
:=
range
a
{
if
arg
==
nil
{
w
.
Write
(
interfaceBytes
)
w
.
Write
(
spaceBytes
)
w
.
Write
(
nilAngleBytes
)
w
.
Write
(
newlineBytes
)
continue
}
d
:=
dumpState
{
w
:
w
,
cs
:
cs
}
d
.
pointers
=
make
(
map
[
uintptr
]
int
)
d
.
dump
(
reflect
.
ValueOf
(
arg
))
d
.
w
.
Write
(
newlineBytes
)
}
}
// Fdump formats and displays the passed arguments to io.Writer w. It formats
// exactly the same as Dump.
func
Fdump
(
w
io
.
Writer
,
a
...
interface
{})
{
fdump
(
&
Config
,
w
,
a
...
)
}
// Sdump returns a string with the passed arguments formatted exactly the same
// as Dump.
func
Sdump
(
a
...
interface
{})
string
{
var
buf
bytes
.
Buffer
fdump
(
&
Config
,
&
buf
,
a
...
)
return
buf
.
String
()
}
/*
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
* Byte arrays and slices are dumped like the hexdump -C command which
includes offsets, byte values in hex, and ASCII output
The configuration options are controlled by an exported package global,
spew.Config. See ConfigState for options documentation.
See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to
get the formatted result as a string.
*/
func
Dump
(
a
...
interface
{})
{
fdump
(
&
Config
,
os
.
Stdout
,
a
...
)
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dump_test.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
Test Summary:
NOTE: For each test, a nil pointer, a single pointer and double pointer to the
base test element are also tested to ensure proper indirection across all types.
- Max int8, int16, int32, int64, int
- Max uint8, uint16, uint32, uint64, uint
- Boolean true and false
- Standard complex64 and complex128
- Array containing standard ints
- Array containing type with custom formatter on pointer receiver only
- Array containing interfaces
- Array containing bytes
- Slice containing standard float32 values
- Slice containing type with custom formatter on pointer receiver only
- Slice containing interfaces
- Slice containing bytes
- Nil slice
- Standard string
- Nil interface
- Sub-interface
- Map with string keys and int vals
- Map with custom formatter type on pointer receiver only keys and vals
- Map with interface keys and values
- Map with nil interface value
- Struct with primitives
- Struct that contains another struct
- Struct that contains custom type with Stringer pointer interface via both
exported and unexported fields
- Struct that contains embedded struct and field to same struct
- Uintptr to 0 (null pointer)
- Uintptr address of real variable
- Unsafe.Pointer to 0 (null pointer)
- Unsafe.Pointer to address of real variable
- Nil channel
- Standard int channel
- Function with no params and no returns
- Function with param and no returns
- Function with multiple params and multiple returns
- Struct that is circular through self referencing
- Structs that are circular through cross referencing
- Structs that are indirectly circular
- Type that panics in its Stringer interface
*/
package
spew_test
import
(
"bytes"
"fmt"
"testing"
"unsafe"
"github.com/davecgh/go-spew/spew"
)
// dumpTest is used to describe a test to be perfomed against the Dump method.
type
dumpTest
struct
{
in
interface
{}
wants
[]
string
}
// dumpTests houses all of the tests to be performed against the Dump method.
var
dumpTests
=
make
([]
dumpTest
,
0
)
// addDumpTest is a helper method to append the passed input and desired result
// to dumpTests
func
addDumpTest
(
in
interface
{},
wants
...
string
)
{
test
:=
dumpTest
{
in
,
wants
}
dumpTests
=
append
(
dumpTests
,
test
)
}
func
addIntDumpTests
()
{
// Max int8.
v
:=
int8
(
127
)
nv
:=
(
*
int8
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"int8"
vs
:=
"127"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Max int16.
v2
:=
int16
(
32767
)
nv2
:=
(
*
int16
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"int16"
v2s
:=
"32767"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*"
+
v2t
+
")(<nil>)
\n
"
)
// Max int32.
v3
:=
int32
(
2147483647
)
nv3
:=
(
*
int32
)(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"int32"
v3s
:=
"2147483647"
addDumpTest
(
v3
,
"("
+
v3t
+
") "
+
v3s
+
"
\n
"
)
addDumpTest
(
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
nv3
,
"(*"
+
v3t
+
")(<nil>)
\n
"
)
// Max int64.
v4
:=
int64
(
9223372036854775807
)
nv4
:=
(
*
int64
)(
nil
)
pv4
:=
&
v4
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"int64"
v4s
:=
"9223372036854775807"
addDumpTest
(
v4
,
"("
+
v4t
+
") "
+
v4s
+
"
\n
"
)
addDumpTest
(
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
nv4
,
"(*"
+
v4t
+
")(<nil>)
\n
"
)
// Max int.
v5
:=
int
(
2147483647
)
nv5
:=
(
*
int
)(
nil
)
pv5
:=
&
v5
v5Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv5
)
pv5Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv5
)
v5t
:=
"int"
v5s
:=
"2147483647"
addDumpTest
(
v5
,
"("
+
v5t
+
") "
+
v5s
+
"
\n
"
)
addDumpTest
(
pv5
,
"(*"
+
v5t
+
")("
+
v5Addr
+
")("
+
v5s
+
")
\n
"
)
addDumpTest
(
&
pv5
,
"(**"
+
v5t
+
")("
+
pv5Addr
+
"->"
+
v5Addr
+
")("
+
v5s
+
")
\n
"
)
addDumpTest
(
nv5
,
"(*"
+
v5t
+
")(<nil>)
\n
"
)
}
func
addUintDumpTests
()
{
// Max uint8.
v
:=
uint8
(
255
)
nv
:=
(
*
uint8
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"uint8"
vs
:=
"255"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Max uint16.
v2
:=
uint16
(
65535
)
nv2
:=
(
*
uint16
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"uint16"
v2s
:=
"65535"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*"
+
v2t
+
")(<nil>)
\n
"
)
// Max uint32.
v3
:=
uint32
(
4294967295
)
nv3
:=
(
*
uint32
)(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"uint32"
v3s
:=
"4294967295"
addDumpTest
(
v3
,
"("
+
v3t
+
") "
+
v3s
+
"
\n
"
)
addDumpTest
(
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
nv3
,
"(*"
+
v3t
+
")(<nil>)
\n
"
)
// Max uint64.
v4
:=
uint64
(
18446744073709551615
)
nv4
:=
(
*
uint64
)(
nil
)
pv4
:=
&
v4
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"uint64"
v4s
:=
"18446744073709551615"
addDumpTest
(
v4
,
"("
+
v4t
+
") "
+
v4s
+
"
\n
"
)
addDumpTest
(
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
nv4
,
"(*"
+
v4t
+
")(<nil>)
\n
"
)
// Max uint.
v5
:=
uint
(
4294967295
)
nv5
:=
(
*
uint
)(
nil
)
pv5
:=
&
v5
v5Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv5
)
pv5Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv5
)
v5t
:=
"uint"
v5s
:=
"4294967295"
addDumpTest
(
v5
,
"("
+
v5t
+
") "
+
v5s
+
"
\n
"
)
addDumpTest
(
pv5
,
"(*"
+
v5t
+
")("
+
v5Addr
+
")("
+
v5s
+
")
\n
"
)
addDumpTest
(
&
pv5
,
"(**"
+
v5t
+
")("
+
pv5Addr
+
"->"
+
v5Addr
+
")("
+
v5s
+
")
\n
"
)
addDumpTest
(
nv5
,
"(*"
+
v5t
+
")(<nil>)
\n
"
)
}
func
addBoolDumpTests
()
{
// Boolean true.
v
:=
bool
(
true
)
nv
:=
(
*
bool
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"bool"
vs
:=
"true"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Boolean false.
v2
:=
bool
(
false
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"bool"
v2s
:=
"false"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
}
func
addFloatDumpTests
()
{
// Standard float32.
v
:=
float32
(
3.1415
)
nv
:=
(
*
float32
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"float32"
vs
:=
"3.1415"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Standard float64.
v2
:=
float64
(
3.1415926
)
nv2
:=
(
*
float64
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"float64"
v2s
:=
"3.1415926"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*"
+
v2t
+
")(<nil>)
\n
"
)
}
func
addComplexDumpTests
()
{
// Standard complex64.
v
:=
complex
(
float32
(
6
),
-
2
)
nv
:=
(
*
complex64
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"complex64"
vs
:=
"(6-2i)"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Standard complex128.
v2
:=
complex
(
float64
(
-
6
),
2
)
nv2
:=
(
*
complex128
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"complex128"
v2s
:=
"(-6+2i)"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*"
+
v2t
+
")(<nil>)
\n
"
)
}
func
addArrayDumpTests
()
{
// Array containing standard ints.
v
:=
[
3
]
int
{
1
,
2
,
3
}
vLen
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v
))
vCap
:=
fmt
.
Sprintf
(
"%d"
,
cap
(
v
))
nv
:=
(
*
[
3
]
int
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"int"
vs
:=
"(len="
+
vLen
+
" cap="
+
vCap
+
") {
\n
("
+
vt
+
") 1,
\n
("
+
vt
+
") 2,
\n
("
+
vt
+
") 3
\n
}"
addDumpTest
(
v
,
"([3]"
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*[3]"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**[3]"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*[3]"
+
vt
+
")(<nil>)
\n
"
)
// Array containing type with custom formatter on pointer receiver only.
v2i0
:=
pstringer
(
"1"
)
v2i1
:=
pstringer
(
"2"
)
v2i2
:=
pstringer
(
"3"
)
v2
:=
[
3
]
pstringer
{
v2i0
,
v2i1
,
v2i2
}
v2i0Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2i0
))
v2i1Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2i1
))
v2i2Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2i2
))
v2Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2
))
v2Cap
:=
fmt
.
Sprintf
(
"%d"
,
cap
(
v2
))
nv2
:=
(
*
[
3
]
pstringer
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"spew_test.pstringer"
v2s
:=
"(len="
+
v2Len
+
" cap="
+
v2Cap
+
") {
\n
("
+
v2t
+
") (len="
+
v2i0Len
+
") stringer 1,
\n
("
+
v2t
+
") (len="
+
v2i1Len
+
") stringer 2,
\n
("
+
v2t
+
") (len="
+
v2i2Len
+
") "
+
"stringer 3
\n
}"
addDumpTest
(
v2
,
"([3]"
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*[3]"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**[3]"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*[3]"
+
v2t
+
")(<nil>)
\n
"
)
// Array containing interfaces.
v3i0
:=
"one"
v3
:=
[
3
]
interface
{}{
v3i0
,
int
(
2
),
uint
(
3
)}
v3i0Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v3i0
))
v3Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v3
))
v3Cap
:=
fmt
.
Sprintf
(
"%d"
,
cap
(
v3
))
nv3
:=
(
*
[
3
]
interface
{})(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"[3]interface {}"
v3t2
:=
"string"
v3t3
:=
"int"
v3t4
:=
"uint"
v3s
:=
"(len="
+
v3Len
+
" cap="
+
v3Cap
+
") {
\n
("
+
v3t2
+
") "
+
"(len="
+
v3i0Len
+
")
\"
one
\"
,
\n
("
+
v3t3
+
") 2,
\n
("
+
v3t4
+
") 3
\n
}"
addDumpTest
(
v3
,
"("
+
v3t
+
") "
+
v3s
+
"
\n
"
)
addDumpTest
(
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
nv3
,
"(*"
+
v3t
+
")(<nil>)
\n
"
)
// Array containing bytes.
v4
:=
[
34
]
byte
{
0x11
,
0x12
,
0x13
,
0x14
,
0x15
,
0x16
,
0x17
,
0x18
,
0x19
,
0x1a
,
0x1b
,
0x1c
,
0x1d
,
0x1e
,
0x1f
,
0x20
,
0x21
,
0x22
,
0x23
,
0x24
,
0x25
,
0x26
,
0x27
,
0x28
,
0x29
,
0x2a
,
0x2b
,
0x2c
,
0x2d
,
0x2e
,
0x2f
,
0x30
,
0x31
,
0x32
,
}
v4Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v4
))
v4Cap
:=
fmt
.
Sprintf
(
"%d"
,
cap
(
v4
))
nv4
:=
(
*
[
34
]
byte
)(
nil
)
pv4
:=
&
v4
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"[34]uint8"
v4s
:=
"(len="
+
v4Len
+
" cap="
+
v4Cap
+
") "
+
"{
\n
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20"
+
" |............... |
\n
"
+
" 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30"
+
" |!
\"
#$%&'()*+,-./0|
\n
"
+
" 00000020 31 32 "
+
" |12|
\n
}"
addDumpTest
(
v4
,
"("
+
v4t
+
") "
+
v4s
+
"
\n
"
)
addDumpTest
(
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
nv4
,
"(*"
+
v4t
+
")(<nil>)
\n
"
)
}
func
addSliceDumpTests
()
{
// Slice containing standard float32 values.
v
:=
[]
float32
{
3.14
,
6.28
,
12.56
}
vLen
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v
))
vCap
:=
fmt
.
Sprintf
(
"%d"
,
cap
(
v
))
nv
:=
(
*
[]
float32
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"float32"
vs
:=
"(len="
+
vLen
+
" cap="
+
vCap
+
") {
\n
("
+
vt
+
") 3.14,
\n
("
+
vt
+
") 6.28,
\n
("
+
vt
+
") 12.56
\n
}"
addDumpTest
(
v
,
"([]"
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*[]"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**[]"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*[]"
+
vt
+
")(<nil>)
\n
"
)
// Slice containing type with custom formatter on pointer receiver only.
v2i0
:=
pstringer
(
"1"
)
v2i1
:=
pstringer
(
"2"
)
v2i2
:=
pstringer
(
"3"
)
v2
:=
[]
pstringer
{
v2i0
,
v2i1
,
v2i2
}
v2i0Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2i0
))
v2i1Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2i1
))
v2i2Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2i2
))
v2Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2
))
v2Cap
:=
fmt
.
Sprintf
(
"%d"
,
cap
(
v2
))
nv2
:=
(
*
[]
pstringer
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"spew_test.pstringer"
v2s
:=
"(len="
+
v2Len
+
" cap="
+
v2Cap
+
") {
\n
("
+
v2t
+
") (len="
+
v2i0Len
+
") stringer 1,
\n
("
+
v2t
+
") (len="
+
v2i1Len
+
") stringer 2,
\n
("
+
v2t
+
") (len="
+
v2i2Len
+
") "
+
"stringer 3
\n
}"
addDumpTest
(
v2
,
"([]"
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*[]"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**[]"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*[]"
+
v2t
+
")(<nil>)
\n
"
)
// Slice containing interfaces.
v3i0
:=
"one"
v3
:=
[]
interface
{}{
v3i0
,
int
(
2
),
uint
(
3
),
nil
}
v3i0Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v3i0
))
v3Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v3
))
v3Cap
:=
fmt
.
Sprintf
(
"%d"
,
cap
(
v3
))
nv3
:=
(
*
[]
interface
{})(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"[]interface {}"
v3t2
:=
"string"
v3t3
:=
"int"
v3t4
:=
"uint"
v3t5
:=
"interface {}"
v3s
:=
"(len="
+
v3Len
+
" cap="
+
v3Cap
+
") {
\n
("
+
v3t2
+
") "
+
"(len="
+
v3i0Len
+
")
\"
one
\"
,
\n
("
+
v3t3
+
") 2,
\n
("
+
v3t4
+
") 3,
\n
("
+
v3t5
+
") <nil>
\n
}"
addDumpTest
(
v3
,
"("
+
v3t
+
") "
+
v3s
+
"
\n
"
)
addDumpTest
(
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
nv3
,
"(*"
+
v3t
+
")(<nil>)
\n
"
)
// Slice containing bytes.
v4
:=
[]
byte
{
0x11
,
0x12
,
0x13
,
0x14
,
0x15
,
0x16
,
0x17
,
0x18
,
0x19
,
0x1a
,
0x1b
,
0x1c
,
0x1d
,
0x1e
,
0x1f
,
0x20
,
0x21
,
0x22
,
0x23
,
0x24
,
0x25
,
0x26
,
0x27
,
0x28
,
0x29
,
0x2a
,
0x2b
,
0x2c
,
0x2d
,
0x2e
,
0x2f
,
0x30
,
0x31
,
0x32
,
}
v4Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v4
))
v4Cap
:=
fmt
.
Sprintf
(
"%d"
,
cap
(
v4
))
nv4
:=
(
*
[]
byte
)(
nil
)
pv4
:=
&
v4
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"[]uint8"
v4s
:=
"(len="
+
v4Len
+
" cap="
+
v4Cap
+
") "
+
"{
\n
00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20"
+
" |............... |
\n
"
+
" 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30"
+
" |!
\"
#$%&'()*+,-./0|
\n
"
+
" 00000020 31 32 "
+
" |12|
\n
}"
addDumpTest
(
v4
,
"("
+
v4t
+
") "
+
v4s
+
"
\n
"
)
addDumpTest
(
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
nv4
,
"(*"
+
v4t
+
")(<nil>)
\n
"
)
// Nil slice.
v5
:=
[]
int
(
nil
)
nv5
:=
(
*
[]
int
)(
nil
)
pv5
:=
&
v5
v5Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv5
)
pv5Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv5
)
v5t
:=
"[]int"
v5s
:=
"<nil>"
addDumpTest
(
v5
,
"("
+
v5t
+
") "
+
v5s
+
"
\n
"
)
addDumpTest
(
pv5
,
"(*"
+
v5t
+
")("
+
v5Addr
+
")("
+
v5s
+
")
\n
"
)
addDumpTest
(
&
pv5
,
"(**"
+
v5t
+
")("
+
pv5Addr
+
"->"
+
v5Addr
+
")("
+
v5s
+
")
\n
"
)
addDumpTest
(
nv5
,
"(*"
+
v5t
+
")(<nil>)
\n
"
)
}
func
addStringDumpTests
()
{
// Standard string.
v
:=
"test"
vLen
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v
))
nv
:=
(
*
string
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"string"
vs
:=
"(len="
+
vLen
+
")
\"
test
\"
"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
}
func
addInterfaceDumpTests
()
{
// Nil interface.
var
v
interface
{}
nv
:=
(
*
interface
{})(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"interface {}"
vs
:=
"<nil>"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Sub-interface.
v2
:=
interface
{}(
uint16
(
65535
))
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"uint16"
v2s
:=
"65535"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
}
func
addMapDumpTests
()
{
// Map with string keys and int vals.
k
:=
"one"
kk
:=
"two"
m
:=
map
[
string
]
int
{
k
:
1
,
kk
:
2
}
klen
:=
fmt
.
Sprintf
(
"%d"
,
len
(
k
))
// not kLen to shut golint up
kkLen
:=
fmt
.
Sprintf
(
"%d"
,
len
(
kk
))
mLen
:=
fmt
.
Sprintf
(
"%d"
,
len
(
m
))
nilMap
:=
map
[
string
]
int
(
nil
)
nm
:=
(
*
map
[
string
]
int
)(
nil
)
pm
:=
&
m
mAddr
:=
fmt
.
Sprintf
(
"%p"
,
pm
)
pmAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pm
)
mt
:=
"map[string]int"
mt1
:=
"string"
mt2
:=
"int"
ms
:=
"(len="
+
mLen
+
") {
\n
("
+
mt1
+
") (len="
+
klen
+
") "
+
"
\"
one
\"
: ("
+
mt2
+
") 1,
\n
("
+
mt1
+
") (len="
+
kkLen
+
")
\"
two
\"
: ("
+
mt2
+
") 2
\n
}"
ms2
:=
"(len="
+
mLen
+
") {
\n
("
+
mt1
+
") (len="
+
kkLen
+
") "
+
"
\"
two
\"
: ("
+
mt2
+
") 2,
\n
("
+
mt1
+
") (len="
+
klen
+
")
\"
one
\"
: ("
+
mt2
+
") 1
\n
}"
addDumpTest
(
m
,
"("
+
mt
+
") "
+
ms
+
"
\n
"
,
"("
+
mt
+
") "
+
ms2
+
"
\n
"
)
addDumpTest
(
pm
,
"(*"
+
mt
+
")("
+
mAddr
+
")("
+
ms
+
")
\n
"
,
"(*"
+
mt
+
")("
+
mAddr
+
")("
+
ms2
+
")
\n
"
)
addDumpTest
(
&
pm
,
"(**"
+
mt
+
")("
+
pmAddr
+
"->"
+
mAddr
+
")("
+
ms
+
")
\n
"
,
"(**"
+
mt
+
")("
+
pmAddr
+
"->"
+
mAddr
+
")("
+
ms2
+
")
\n
"
)
addDumpTest
(
nm
,
"(*"
+
mt
+
")(<nil>)
\n
"
)
addDumpTest
(
nilMap
,
"("
+
mt
+
") <nil>
\n
"
)
// Map with custom formatter type on pointer receiver only keys and vals.
k2
:=
pstringer
(
"one"
)
v2
:=
pstringer
(
"1"
)
m2
:=
map
[
pstringer
]
pstringer
{
k2
:
v2
}
k2Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
k2
))
v2Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
v2
))
m2Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
m2
))
nilMap2
:=
map
[
pstringer
]
pstringer
(
nil
)
nm2
:=
(
*
map
[
pstringer
]
pstringer
)(
nil
)
pm2
:=
&
m2
m2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pm2
)
pm2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pm2
)
m2t
:=
"map[spew_test.pstringer]spew_test.pstringer"
m2t1
:=
"spew_test.pstringer"
m2t2
:=
"spew_test.pstringer"
m2s
:=
"(len="
+
m2Len
+
") {
\n
("
+
m2t1
+
") (len="
+
k2Len
+
") "
+
"stringer one: ("
+
m2t2
+
") (len="
+
v2Len
+
") stringer 1
\n
}"
addDumpTest
(
m2
,
"("
+
m2t
+
") "
+
m2s
+
"
\n
"
)
addDumpTest
(
pm2
,
"(*"
+
m2t
+
")("
+
m2Addr
+
")("
+
m2s
+
")
\n
"
)
addDumpTest
(
&
pm2
,
"(**"
+
m2t
+
")("
+
pm2Addr
+
"->"
+
m2Addr
+
")("
+
m2s
+
")
\n
"
)
addDumpTest
(
nm2
,
"(*"
+
m2t
+
")(<nil>)
\n
"
)
addDumpTest
(
nilMap2
,
"("
+
m2t
+
") <nil>
\n
"
)
// Map with interface keys and values.
k3
:=
"one"
k3Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
k3
))
m3
:=
map
[
interface
{}]
interface
{}{
k3
:
1
}
m3Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
m3
))
nilMap3
:=
map
[
interface
{}]
interface
{}(
nil
)
nm3
:=
(
*
map
[
interface
{}]
interface
{})(
nil
)
pm3
:=
&
m3
m3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pm3
)
pm3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pm3
)
m3t
:=
"map[interface {}]interface {}"
m3t1
:=
"string"
m3t2
:=
"int"
m3s
:=
"(len="
+
m3Len
+
") {
\n
("
+
m3t1
+
") (len="
+
k3Len
+
") "
+
"
\"
one
\"
: ("
+
m3t2
+
") 1
\n
}"
addDumpTest
(
m3
,
"("
+
m3t
+
") "
+
m3s
+
"
\n
"
)
addDumpTest
(
pm3
,
"(*"
+
m3t
+
")("
+
m3Addr
+
")("
+
m3s
+
")
\n
"
)
addDumpTest
(
&
pm3
,
"(**"
+
m3t
+
")("
+
pm3Addr
+
"->"
+
m3Addr
+
")("
+
m3s
+
")
\n
"
)
addDumpTest
(
nm3
,
"(*"
+
m3t
+
")(<nil>)
\n
"
)
addDumpTest
(
nilMap3
,
"("
+
m3t
+
") <nil>
\n
"
)
// Map with nil interface value.
k4
:=
"nil"
k4Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
k4
))
m4
:=
map
[
string
]
interface
{}{
k4
:
nil
}
m4Len
:=
fmt
.
Sprintf
(
"%d"
,
len
(
m4
))
nilMap4
:=
map
[
string
]
interface
{}(
nil
)
nm4
:=
(
*
map
[
string
]
interface
{})(
nil
)
pm4
:=
&
m4
m4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pm4
)
pm4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pm4
)
m4t
:=
"map[string]interface {}"
m4t1
:=
"string"
m4t2
:=
"interface {}"
m4s
:=
"(len="
+
m4Len
+
") {
\n
("
+
m4t1
+
") (len="
+
k4Len
+
")"
+
"
\"
nil
\"
: ("
+
m4t2
+
") <nil>
\n
}"
addDumpTest
(
m4
,
"("
+
m4t
+
") "
+
m4s
+
"
\n
"
)
addDumpTest
(
pm4
,
"(*"
+
m4t
+
")("
+
m4Addr
+
")("
+
m4s
+
")
\n
"
)
addDumpTest
(
&
pm4
,
"(**"
+
m4t
+
")("
+
pm4Addr
+
"->"
+
m4Addr
+
")("
+
m4s
+
")
\n
"
)
addDumpTest
(
nm4
,
"(*"
+
m4t
+
")(<nil>)
\n
"
)
addDumpTest
(
nilMap4
,
"("
+
m4t
+
") <nil>
\n
"
)
}
func
addStructDumpTests
()
{
// Struct with primitives.
type
s1
struct
{
a
int8
b
uint8
}
v
:=
s1
{
127
,
255
}
nv
:=
(
*
s1
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"spew_test.s1"
vt2
:=
"int8"
vt3
:=
"uint8"
vs
:=
"{
\n
a: ("
+
vt2
+
") 127,
\n
b: ("
+
vt3
+
") 255
\n
}"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Struct that contains another struct.
type
s2
struct
{
s1
s1
b
bool
}
v2
:=
s2
{
s1
{
127
,
255
},
true
}
nv2
:=
(
*
s2
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"spew_test.s2"
v2t2
:=
"spew_test.s1"
v2t3
:=
"int8"
v2t4
:=
"uint8"
v2t5
:=
"bool"
v2s
:=
"{
\n
s1: ("
+
v2t2
+
") {
\n
a: ("
+
v2t3
+
") 127,
\n
b: ("
+
v2t4
+
") 255
\n
},
\n
b: ("
+
v2t5
+
") true
\n
}"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*"
+
v2t
+
")(<nil>)
\n
"
)
// Struct that contains custom type with Stringer pointer interface via both
// exported and unexported fields.
type
s3
struct
{
s
pstringer
S
pstringer
}
v3
:=
s3
{
"test"
,
"test2"
}
nv3
:=
(
*
s3
)(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"spew_test.s3"
v3t2
:=
"spew_test.pstringer"
v3s
:=
"{
\n
s: ("
+
v3t2
+
") (len=4) stringer test,
\n
S: ("
+
v3t2
+
") (len=5) stringer test2
\n
}"
addDumpTest
(
v3
,
"("
+
v3t
+
") "
+
v3s
+
"
\n
"
)
addDumpTest
(
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
nv3
,
"(*"
+
v3t
+
")(<nil>)
\n
"
)
// Struct that contains embedded struct and field to same struct.
e
:=
embed
{
"embedstr"
}
eLen
:=
fmt
.
Sprintf
(
"%d"
,
len
(
"embedstr"
))
v4
:=
embedwrap
{
embed
:
&
e
,
e
:
&
e
}
nv4
:=
(
*
embedwrap
)(
nil
)
pv4
:=
&
v4
eAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
e
)
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"spew_test.embedwrap"
v4t2
:=
"spew_test.embed"
v4t3
:=
"string"
v4s
:=
"{
\n
embed: (*"
+
v4t2
+
")("
+
eAddr
+
")({
\n
a: ("
+
v4t3
+
") (len="
+
eLen
+
")
\"
embedstr
\"\n
}),
\n
e: (*"
+
v4t2
+
")("
+
eAddr
+
")({
\n
a: ("
+
v4t3
+
") (len="
+
eLen
+
")"
+
"
\"
embedstr
\"\n
})
\n
}"
addDumpTest
(
v4
,
"("
+
v4t
+
") "
+
v4s
+
"
\n
"
)
addDumpTest
(
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")("
+
v4s
+
")
\n
"
)
addDumpTest
(
nv4
,
"(*"
+
v4t
+
")(<nil>)
\n
"
)
}
func
addUintptrDumpTests
()
{
// Null pointer.
v
:=
uintptr
(
0
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"uintptr"
vs
:=
"<nil>"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
// Address of real variable.
i
:=
1
v2
:=
uintptr
(
unsafe
.
Pointer
(
&
i
))
nv2
:=
(
*
uintptr
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"uintptr"
v2s
:=
fmt
.
Sprintf
(
"%p"
,
&
i
)
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*"
+
v2t
+
")(<nil>)
\n
"
)
}
func
addUnsafePointerDumpTests
()
{
// Null pointer.
v
:=
unsafe
.
Pointer
(
uintptr
(
0
))
nv
:=
(
*
unsafe
.
Pointer
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"unsafe.Pointer"
vs
:=
"<nil>"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Address of real variable.
i
:=
1
v2
:=
unsafe
.
Pointer
(
&
i
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"unsafe.Pointer"
v2s
:=
fmt
.
Sprintf
(
"%p"
,
&
i
)
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
}
func
addChanDumpTests
()
{
// Nil channel.
var
v
chan
int
pv
:=
&
v
nv
:=
(
*
chan
int
)(
nil
)
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"chan int"
vs
:=
"<nil>"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Real channel.
v2
:=
make
(
chan
int
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"chan int"
v2s
:=
fmt
.
Sprintf
(
"%p"
,
v2
)
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
}
func
addFuncDumpTests
()
{
// Function with no params and no returns.
v
:=
addIntDumpTests
nv
:=
(
*
func
())(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"func()"
vs
:=
fmt
.
Sprintf
(
"%p"
,
v
)
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
// Function with param and no returns.
v2
:=
TestDump
nv2
:=
(
*
func
(
*
testing
.
T
))(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"func(*testing.T)"
v2s
:=
fmt
.
Sprintf
(
"%p"
,
v2
)
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s
+
")
\n
"
)
addDumpTest
(
nv2
,
"(*"
+
v2t
+
")(<nil>)
\n
"
)
// Function with multiple params and multiple returns.
var
v3
=
func
(
i
int
,
s
string
)
(
b
bool
,
err
error
)
{
return
true
,
nil
}
nv3
:=
(
*
func
(
int
,
string
)
(
bool
,
error
))(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"func(int, string) (bool, error)"
v3s
:=
fmt
.
Sprintf
(
"%p"
,
v3
)
addDumpTest
(
v3
,
"("
+
v3t
+
") "
+
v3s
+
"
\n
"
)
addDumpTest
(
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")("
+
v3s
+
")
\n
"
)
addDumpTest
(
nv3
,
"(*"
+
v3t
+
")(<nil>)
\n
"
)
}
func
addCircularDumpTests
()
{
// Struct that is circular through self referencing.
type
circular
struct
{
c
*
circular
}
v
:=
circular
{
nil
}
v
.
c
=
&
v
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"spew_test.circular"
vs
:=
"{
\n
c: (*"
+
vt
+
")("
+
vAddr
+
")({
\n
c: (*"
+
vt
+
")("
+
vAddr
+
")(<already shown>)
\n
})
\n
}"
vs2
:=
"{
\n
c: (*"
+
vt
+
")("
+
vAddr
+
")(<already shown>)
\n
}"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs2
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs2
+
")
\n
"
)
// Structs that are circular through cross referencing.
v2
:=
xref1
{
nil
}
ts2
:=
xref2
{
&
v2
}
v2
.
ps2
=
&
ts2
pv2
:=
&
v2
ts2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
ts2
)
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"spew_test.xref1"
v2t2
:=
"spew_test.xref2"
v2s
:=
"{
\n
ps2: (*"
+
v2t2
+
")("
+
ts2Addr
+
")({
\n
ps1: (*"
+
v2t
+
")("
+
v2Addr
+
")({
\n
ps2: (*"
+
v2t2
+
")("
+
ts2Addr
+
")(<already shown>)
\n
})
\n
})
\n
}"
v2s2
:=
"{
\n
ps2: (*"
+
v2t2
+
")("
+
ts2Addr
+
")({
\n
ps1: (*"
+
v2t
+
")("
+
v2Addr
+
")(<already shown>)
\n
})
\n
}"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
addDumpTest
(
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")("
+
v2s2
+
")
\n
"
)
addDumpTest
(
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")("
+
v2s2
+
")
\n
"
)
// Structs that are indirectly circular.
v3
:=
indirCir1
{
nil
}
tic2
:=
indirCir2
{
nil
}
tic3
:=
indirCir3
{
&
v3
}
tic2
.
ps3
=
&
tic3
v3
.
ps2
=
&
tic2
pv3
:=
&
v3
tic2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
tic2
)
tic3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
tic3
)
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"spew_test.indirCir1"
v3t2
:=
"spew_test.indirCir2"
v3t3
:=
"spew_test.indirCir3"
v3s
:=
"{
\n
ps2: (*"
+
v3t2
+
")("
+
tic2Addr
+
")({
\n
ps3: (*"
+
v3t3
+
")("
+
tic3Addr
+
")({
\n
ps1: (*"
+
v3t
+
")("
+
v3Addr
+
")({
\n
ps2: (*"
+
v3t2
+
")("
+
tic2Addr
+
")(<already shown>)
\n
})
\n
})
\n
})
\n
}"
v3s2
:=
"{
\n
ps2: (*"
+
v3t2
+
")("
+
tic2Addr
+
")({
\n
ps3: (*"
+
v3t3
+
")("
+
tic3Addr
+
")({
\n
ps1: (*"
+
v3t
+
")("
+
v3Addr
+
")(<already shown>)
\n
})
\n
})
\n
}"
addDumpTest
(
v3
,
"("
+
v3t
+
") "
+
v3s
+
"
\n
"
)
addDumpTest
(
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")("
+
v3s2
+
")
\n
"
)
addDumpTest
(
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")("
+
v3s2
+
")
\n
"
)
}
func
addPanicDumpTests
()
{
// Type that panics in its Stringer interface.
v
:=
panicer
(
127
)
nv
:=
(
*
panicer
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"spew_test.panicer"
vs
:=
"(PANIC=test panic)127"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
}
func
addErrorDumpTests
()
{
// Type that has a custom Error interface.
v
:=
customError
(
127
)
nv
:=
(
*
customError
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"spew_test.customError"
vs
:=
"error: 127"
addDumpTest
(
v
,
"("
+
vt
+
") "
+
vs
+
"
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"(*"
+
vt
+
")(<nil>)
\n
"
)
}
// TestDump executes all of the tests described by dumpTests.
func
TestDump
(
t
*
testing
.
T
)
{
// Setup tests.
addIntDumpTests
()
addUintDumpTests
()
addBoolDumpTests
()
addFloatDumpTests
()
addComplexDumpTests
()
addArrayDumpTests
()
addSliceDumpTests
()
addStringDumpTests
()
addInterfaceDumpTests
()
addMapDumpTests
()
addStructDumpTests
()
addUintptrDumpTests
()
addUnsafePointerDumpTests
()
addChanDumpTests
()
addFuncDumpTests
()
addCircularDumpTests
()
addPanicDumpTests
()
addErrorDumpTests
()
addCgoDumpTests
()
t
.
Logf
(
"Running %d tests"
,
len
(
dumpTests
))
for
i
,
test
:=
range
dumpTests
{
buf
:=
new
(
bytes
.
Buffer
)
spew
.
Fdump
(
buf
,
test
.
in
)
s
:=
buf
.
String
()
if
testFailed
(
s
,
test
.
wants
)
{
t
.
Errorf
(
"Dump #%d
\n
got: %s %s"
,
i
,
s
,
stringizeWants
(
test
.
wants
))
continue
}
}
}
func
TestDumpSortedKeys
(
t
*
testing
.
T
)
{
cfg
:=
spew
.
ConfigState
{
SortKeys
:
true
}
s
:=
cfg
.
Sdump
(
map
[
int
]
string
{
1
:
"1"
,
3
:
"3"
,
2
:
"2"
})
expected
:=
`(map[int]string) (len=3) {
(int) 1: (string) (len=1) "1",
(int) 2: (string) (len=1) "2",
(int) 3: (string) (len=1) "3"
}
`
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
s
=
cfg
.
Sdump
(
map
[
stringer
]
int
{
"1"
:
1
,
"3"
:
3
,
"2"
:
2
})
expected
=
`(map[spew_test.stringer]int) (len=3) {
(spew_test.stringer) (len=1) stringer 1: (int) 1,
(spew_test.stringer) (len=1) stringer 2: (int) 2,
(spew_test.stringer) (len=1) stringer 3: (int) 3
}
`
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
s
=
cfg
.
Sdump
(
map
[
pstringer
]
int
{
pstringer
(
"1"
)
:
1
,
pstringer
(
"3"
)
:
3
,
pstringer
(
"2"
)
:
2
})
expected
=
`(map[spew_test.pstringer]int) (len=3) {
(spew_test.pstringer) (len=1) stringer 1: (int) 1,
(spew_test.pstringer) (len=1) stringer 2: (int) 2,
(spew_test.pstringer) (len=1) stringer 3: (int) 3
}
`
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
s
=
cfg
.
Sdump
(
map
[
customError
]
int
{
customError
(
1
)
:
1
,
customError
(
3
)
:
3
,
customError
(
2
)
:
2
})
expected
=
`(map[spew_test.customError]int) (len=3) {
(spew_test.customError) error: 1: (int) 1,
(spew_test.customError) error: 2: (int) 2,
(spew_test.customError) error: 3: (int) 3
}
`
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpcgo_test.go
0 → 100644
View file @
7b933418
// Copyright (c) 2013 Dave Collins <dave@davec.name>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when both cgo is supported and "-tags testcgo" is added to the go test
// command line. This means the cgo tests are only added (and hence run) when
// specifially requested. This configuration is used because spew itself
// does not require cgo to run even though it does handle certain cgo types
// specially. Rather than forcing all clients to require cgo and an external
// C compiler just to run the tests, this scheme makes them optional.
// +build cgo,testcgo
package
spew_test
import
(
"fmt"
"github.com/davecgh/go-spew/spew/testdata"
)
func
addCgoDumpTests
()
{
// C char pointer.
v
:=
testdata
.
GetCgoCharPointer
()
nv
:=
testdata
.
GetCgoNullCharPointer
()
pv
:=
&
v
vcAddr
:=
fmt
.
Sprintf
(
"%p"
,
v
)
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"*testdata._Ctype_char"
vs
:=
"116"
addDumpTest
(
v
,
"("
+
vt
+
")("
+
vcAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
"->"
+
vcAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
"->"
+
vcAddr
+
")("
+
vs
+
")
\n
"
)
addDumpTest
(
nv
,
"("
+
vt
+
")(<nil>)
\n
"
)
// C char array.
v2
,
v2l
,
v2c
:=
testdata
.
GetCgoCharArray
()
v2Len
:=
fmt
.
Sprintf
(
"%d"
,
v2l
)
v2Cap
:=
fmt
.
Sprintf
(
"%d"
,
v2c
)
v2t
:=
"[6]testdata._Ctype_char"
v2s
:=
"(len="
+
v2Len
+
" cap="
+
v2Cap
+
") "
+
"{
\n
00000000 74 65 73 74 32 00 "
+
" |test2.|
\n
}"
addDumpTest
(
v2
,
"("
+
v2t
+
") "
+
v2s
+
"
\n
"
)
// C unsigned char array.
v3
,
v3l
,
v3c
:=
testdata
.
GetCgoUnsignedCharArray
()
v3Len
:=
fmt
.
Sprintf
(
"%d"
,
v3l
)
v3Cap
:=
fmt
.
Sprintf
(
"%d"
,
v3c
)
v3t
:=
"[6]testdata._Ctype_unsignedchar"
v3s
:=
"(len="
+
v3Len
+
" cap="
+
v3Cap
+
") "
+
"{
\n
00000000 74 65 73 74 33 00 "
+
" |test3.|
\n
}"
addDumpTest
(
v3
,
"("
+
v3t
+
") "
+
v3s
+
"
\n
"
)
// C signed char array.
v4
,
v4l
,
v4c
:=
testdata
.
GetCgoSignedCharArray
()
v4Len
:=
fmt
.
Sprintf
(
"%d"
,
v4l
)
v4Cap
:=
fmt
.
Sprintf
(
"%d"
,
v4c
)
v4t
:=
"[6]testdata._Ctype_schar"
v4t2
:=
"testdata._Ctype_schar"
v4s
:=
"(len="
+
v4Len
+
" cap="
+
v4Cap
+
") "
+
"{
\n
("
+
v4t2
+
") 116,
\n
("
+
v4t2
+
") 101,
\n
("
+
v4t2
+
") 115,
\n
("
+
v4t2
+
") 116,
\n
("
+
v4t2
+
") 52,
\n
("
+
v4t2
+
") 0
\n
}"
addDumpTest
(
v4
,
"("
+
v4t
+
") "
+
v4s
+
"
\n
"
)
// C uint8_t array.
v5
,
v5l
,
v5c
:=
testdata
.
GetCgoUint8tArray
()
v5Len
:=
fmt
.
Sprintf
(
"%d"
,
v5l
)
v5Cap
:=
fmt
.
Sprintf
(
"%d"
,
v5c
)
v5t
:=
"[6]testdata._Ctype_uint8_t"
v5s
:=
"(len="
+
v5Len
+
" cap="
+
v5Cap
+
") "
+
"{
\n
00000000 74 65 73 74 35 00 "
+
" |test5.|
\n
}"
addDumpTest
(
v5
,
"("
+
v5t
+
") "
+
v5s
+
"
\n
"
)
// C typedefed unsigned char array.
v6
,
v6l
,
v6c
:=
testdata
.
GetCgoTypdefedUnsignedCharArray
()
v6Len
:=
fmt
.
Sprintf
(
"%d"
,
v6l
)
v6Cap
:=
fmt
.
Sprintf
(
"%d"
,
v6c
)
v6t
:=
"[6]testdata._Ctype_custom_uchar_t"
v6s
:=
"(len="
+
v6Len
+
" cap="
+
v6Cap
+
") "
+
"{
\n
00000000 74 65 73 74 36 00 "
+
" |test6.|
\n
}"
addDumpTest
(
v6
,
"("
+
v6t
+
") "
+
v6s
+
"
\n
"
)
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/dumpnocgo_test.go
0 → 100644
View file @
7b933418
// Copyright (c) 2013 Dave Collins <dave@davec.name>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when either cgo is not supported or "-tags testcgo" is not added to the go
// test command line. This file intentionally does not setup any cgo tests in
// this scenario.
// +build !cgo !testcgo
package
spew_test
func
addCgoDumpTests
()
{
// Don't add any tests for cgo since this file is only compiled when
// there should not be any cgo tests.
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/example_test.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package
spew_test
import
(
"fmt"
"github.com/davecgh/go-spew/spew"
)
type
Flag
int
const
(
flagOne
Flag
=
iota
flagTwo
)
var
flagStrings
=
map
[
Flag
]
string
{
flagOne
:
"flagOne"
,
flagTwo
:
"flagTwo"
,
}
func
(
f
Flag
)
String
()
string
{
if
s
,
ok
:=
flagStrings
[
f
];
ok
{
return
s
}
return
fmt
.
Sprintf
(
"Unknown flag (%d)"
,
int
(
f
))
}
type
Bar
struct
{
flag
Flag
data
uintptr
}
type
Foo
struct
{
unexportedField
Bar
ExportedField
map
[
interface
{}]
interface
{}
}
// This example demonstrates how to use Dump to dump variables to stdout.
func
ExampleDump
()
{
// The following package level declarations are assumed for this example:
/*
type Flag int
const (
flagOne Flag = iota
flagTwo
)
var flagStrings = map[Flag]string{
flagOne: "flagOne",
flagTwo: "flagTwo",
}
func (f Flag) String() string {
if s, ok := flagStrings[f]; ok {
return s
}
return fmt.Sprintf("Unknown flag (%d)", int(f))
}
type Bar struct {
flag Flag
data uintptr
}
type Foo struct {
unexportedField Bar
ExportedField map[interface{}]interface{}
}
*/
// Setup some sample data structures for the example.
bar
:=
Bar
{
Flag
(
flagTwo
),
uintptr
(
0
)}
s1
:=
Foo
{
bar
,
map
[
interface
{}]
interface
{}{
"one"
:
true
}}
f
:=
Flag
(
5
)
b
:=
[]
byte
{
0x11
,
0x12
,
0x13
,
0x14
,
0x15
,
0x16
,
0x17
,
0x18
,
0x19
,
0x1a
,
0x1b
,
0x1c
,
0x1d
,
0x1e
,
0x1f
,
0x20
,
0x21
,
0x22
,
0x23
,
0x24
,
0x25
,
0x26
,
0x27
,
0x28
,
0x29
,
0x2a
,
0x2b
,
0x2c
,
0x2d
,
0x2e
,
0x2f
,
0x30
,
0x31
,
0x32
,
}
// Dump!
spew
.
Dump
(
s1
,
f
,
b
)
// Output:
// (spew_test.Foo) {
// unexportedField: (spew_test.Bar) {
// flag: (spew_test.Flag) flagTwo,
// data: (uintptr) <nil>
// },
// ExportedField: (map[interface {}]interface {}) (len=1) {
// (string) (len=3) "one": (bool) true
// }
// }
// (spew_test.Flag) Unknown flag (5)
// ([]uint8) (len=34 cap=34) {
// 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... |
// 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0|
// 00000020 31 32 |12|
// }
//
}
// This example demonstrates how to use Printf to display a variable with a
// format string and inline formatting.
func
ExamplePrintf
()
{
// Create a double pointer to a uint 8.
ui8
:=
uint8
(
5
)
pui8
:=
&
ui8
ppui8
:=
&
pui8
// Create a circular data type.
type
circular
struct
{
ui8
uint8
c
*
circular
}
c
:=
circular
{
ui8
:
1
}
c
.
c
=
&
c
// Print!
spew
.
Printf
(
"ppui8: %v
\n
"
,
ppui8
)
spew
.
Printf
(
"circular: %v
\n
"
,
c
)
// Output:
// ppui8: <**>5
// circular: {1 <*>{1 <*><shown>}}
}
// 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
"
}
// Output using the ConfigState instance.
v
:=
map
[
string
]
int
{
"one"
:
1
}
scs
.
Printf
(
"v: %v
\n
"
,
v
)
scs
.
Dump
(
v
)
// Output:
// v: map[one:1]
// (map[string]int) (len=1) {
// (string) (len=3) "one": (int) 1
// }
}
// This example demonstrates how to use ConfigState.Dump to dump variables to
// stdout
func
ExampleConfigState_Dump
()
{
// See the top-level Dump example for details on the types used in this
// example.
// 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 ConfigState instances.
scs
.
Dump
(
s1
)
scs2
.
Dump
(
s1
)
// Output:
// (spew_test.Foo) {
// unexportedField: (spew_test.Bar) {
// flag: (spew_test.Flag) flagTwo,
// data: (uintptr) <nil>
// },
// ExportedField: (map[interface {}]interface {}) (len=1) {
// (string) (len=3) "one": (bool) true
// }
// }
// (spew_test.Foo) {
// unexportedField: (spew_test.Bar) {
// flag: (spew_test.Flag) flagTwo,
// data: (uintptr) <nil>
// },
// ExportedField: (map[interface {}]interface {}) (len=1) {
// (string) (len=3) "one": (bool) true
// }
// }
//
}
// This example demonstrates how to use ConfigState.Printf to display a variable
// with a format string and inline formatting.
func
ExampleConfigState_Printf
()
{
// See the top-level Dump example for details on the types used in this
// example.
// Create two ConfigState instances and modify the method handling of the
// first ConfigState only.
scs
:=
spew
.
NewDefaultConfig
()
scs2
:=
spew
.
NewDefaultConfig
()
scs
.
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 ConfigState instances.
scs
.
Printf
(
"f: %v
\n
"
,
f
)
scs2
.
Printf
(
"f: %v
\n
"
,
f
)
// Output:
// f: 1
// f: flagTwo
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package
spew
import
(
"bytes"
"fmt"
"reflect"
"strconv"
"strings"
)
// supportedFlags is a list of all the character flags supported by fmt package.
const
supportedFlags
=
"0-+# "
// formatState implements the fmt.Formatter interface and contains information
// about the state of a formatting operation. The NewFormatter function can
// be used to get a new Formatter which can be used directly as arguments
// in standard fmt package printing calls.
type
formatState
struct
{
value
interface
{}
fs
fmt
.
State
depth
int
pointers
map
[
uintptr
]
int
ignoreNextType
bool
cs
*
ConfigState
}
// buildDefaultFormat recreates the original format string without precision
// and width information to pass in to fmt.Sprintf in the case of an
// unrecognized type. Unless new types are added to the language, this
// function won't ever be called.
func
(
f
*
formatState
)
buildDefaultFormat
()
(
format
string
)
{
buf
:=
bytes
.
NewBuffer
(
percentBytes
)
for
_
,
flag
:=
range
supportedFlags
{
if
f
.
fs
.
Flag
(
int
(
flag
))
{
buf
.
WriteRune
(
flag
)
}
}
buf
.
WriteRune
(
'v'
)
format
=
buf
.
String
()
return
format
}
// constructOrigFormat recreates the original format string including precision
// and width information to pass along to the standard fmt package. This allows
// automatic deferral of all format strings this package doesn't support.
func
(
f
*
formatState
)
constructOrigFormat
(
verb
rune
)
(
format
string
)
{
buf
:=
bytes
.
NewBuffer
(
percentBytes
)
for
_
,
flag
:=
range
supportedFlags
{
if
f
.
fs
.
Flag
(
int
(
flag
))
{
buf
.
WriteRune
(
flag
)
}
}
if
width
,
ok
:=
f
.
fs
.
Width
();
ok
{
buf
.
WriteString
(
strconv
.
Itoa
(
width
))
}
if
precision
,
ok
:=
f
.
fs
.
Precision
();
ok
{
buf
.
Write
(
precisionBytes
)
buf
.
WriteString
(
strconv
.
Itoa
(
precision
))
}
buf
.
WriteRune
(
verb
)
format
=
buf
.
String
()
return
format
}
// unpackValue returns values inside of non-nil interfaces when possible and
// ensures that types for values which have been unpacked from an interface
// are displayed when the show types flag is also set.
// This is useful for data types like structs, arrays, slices, and maps which
// can contain varying types packed inside an interface.
func
(
f
*
formatState
)
unpackValue
(
v
reflect
.
Value
)
reflect
.
Value
{
if
v
.
Kind
()
==
reflect
.
Interface
{
f
.
ignoreNextType
=
false
if
!
v
.
IsNil
()
{
v
=
v
.
Elem
()
}
}
return
v
}
// formatPtr handles formatting of pointers by indirecting them as necessary.
func
(
f
*
formatState
)
formatPtr
(
v
reflect
.
Value
)
{
// Display nil if top level pointer is nil.
showTypes
:=
f
.
fs
.
Flag
(
'#'
)
if
v
.
IsNil
()
&&
(
!
showTypes
||
f
.
ignoreNextType
)
{
f
.
fs
.
Write
(
nilAngleBytes
)
return
}
// Remove pointers at or below the current depth from map used to detect
// circular refs.
for
k
,
depth
:=
range
f
.
pointers
{
if
depth
>=
f
.
depth
{
delete
(
f
.
pointers
,
k
)
}
}
// Keep list of all dereferenced pointers to possibly show later.
pointerChain
:=
make
([]
uintptr
,
0
)
// Figure out how many levels of indirection there are by derferencing
// pointers and unpacking interfaces down the chain while detecting circular
// references.
nilFound
:=
false
cycleFound
:=
false
indirects
:=
0
ve
:=
v
for
ve
.
Kind
()
==
reflect
.
Ptr
{
if
ve
.
IsNil
()
{
nilFound
=
true
break
}
indirects
++
addr
:=
ve
.
Pointer
()
pointerChain
=
append
(
pointerChain
,
addr
)
if
pd
,
ok
:=
f
.
pointers
[
addr
];
ok
&&
pd
<
f
.
depth
{
cycleFound
=
true
indirects
--
break
}
f
.
pointers
[
addr
]
=
f
.
depth
ve
=
ve
.
Elem
()
if
ve
.
Kind
()
==
reflect
.
Interface
{
if
ve
.
IsNil
()
{
nilFound
=
true
break
}
ve
=
ve
.
Elem
()
}
}
// Display type or indirection level depending on flags.
if
showTypes
&&
!
f
.
ignoreNextType
{
f
.
fs
.
Write
(
openParenBytes
)
f
.
fs
.
Write
(
bytes
.
Repeat
(
asteriskBytes
,
indirects
))
f
.
fs
.
Write
([]
byte
(
ve
.
Type
()
.
String
()))
f
.
fs
.
Write
(
closeParenBytes
)
}
else
{
if
nilFound
||
cycleFound
{
indirects
+=
strings
.
Count
(
ve
.
Type
()
.
String
(),
"*"
)
}
f
.
fs
.
Write
(
openAngleBytes
)
f
.
fs
.
Write
([]
byte
(
strings
.
Repeat
(
"*"
,
indirects
)))
f
.
fs
.
Write
(
closeAngleBytes
)
}
// Display pointer information depending on flags.
if
f
.
fs
.
Flag
(
'+'
)
&&
(
len
(
pointerChain
)
>
0
)
{
f
.
fs
.
Write
(
openParenBytes
)
for
i
,
addr
:=
range
pointerChain
{
if
i
>
0
{
f
.
fs
.
Write
(
pointerChainBytes
)
}
printHexPtr
(
f
.
fs
,
addr
)
}
f
.
fs
.
Write
(
closeParenBytes
)
}
// Display dereferenced value.
switch
{
case
nilFound
==
true
:
f
.
fs
.
Write
(
nilAngleBytes
)
case
cycleFound
==
true
:
f
.
fs
.
Write
(
circularShortBytes
)
default
:
f
.
ignoreNextType
=
true
f
.
format
(
ve
)
}
}
// format is the main workhorse for providing the Formatter interface. It
// uses the passed reflect value to figure out what kind of object we are
// dealing with and formats it appropriately. It is a recursive function,
// however circular data structures are detected and handled properly.
func
(
f
*
formatState
)
format
(
v
reflect
.
Value
)
{
// Handle invalid reflect values immediately.
kind
:=
v
.
Kind
()
if
kind
==
reflect
.
Invalid
{
f
.
fs
.
Write
(
invalidAngleBytes
)
return
}
// Handle pointers specially.
if
kind
==
reflect
.
Ptr
{
f
.
formatPtr
(
v
)
return
}
// Print type information unless already handled elsewhere.
if
!
f
.
ignoreNextType
&&
f
.
fs
.
Flag
(
'#'
)
{
f
.
fs
.
Write
(
openParenBytes
)
f
.
fs
.
Write
([]
byte
(
v
.
Type
()
.
String
()))
f
.
fs
.
Write
(
closeParenBytes
)
}
f
.
ignoreNextType
=
false
// Call Stringer/error interfaces if they exist and the handle methods
// flag is enabled.
if
!
f
.
cs
.
DisableMethods
{
if
(
kind
!=
reflect
.
Invalid
)
&&
(
kind
!=
reflect
.
Interface
)
{
if
handled
:=
handleMethods
(
f
.
cs
,
f
.
fs
,
v
);
handled
{
return
}
}
}
switch
kind
{
case
reflect
.
Invalid
:
// Do nothing. We should never get here since invalid has already
// been handled above.
case
reflect
.
Bool
:
printBool
(
f
.
fs
,
v
.
Bool
())
case
reflect
.
Int8
,
reflect
.
Int16
,
reflect
.
Int32
,
reflect
.
Int64
,
reflect
.
Int
:
printInt
(
f
.
fs
,
v
.
Int
(),
10
)
case
reflect
.
Uint8
,
reflect
.
Uint16
,
reflect
.
Uint32
,
reflect
.
Uint64
,
reflect
.
Uint
:
printUint
(
f
.
fs
,
v
.
Uint
(),
10
)
case
reflect
.
Float32
:
printFloat
(
f
.
fs
,
v
.
Float
(),
32
)
case
reflect
.
Float64
:
printFloat
(
f
.
fs
,
v
.
Float
(),
64
)
case
reflect
.
Complex64
:
printComplex
(
f
.
fs
,
v
.
Complex
(),
32
)
case
reflect
.
Complex128
:
printComplex
(
f
.
fs
,
v
.
Complex
(),
64
)
case
reflect
.
Slice
:
if
v
.
IsNil
()
{
f
.
fs
.
Write
(
nilAngleBytes
)
break
}
fallthrough
case
reflect
.
Array
:
f
.
fs
.
Write
(
openBracketBytes
)
f
.
depth
++
if
(
f
.
cs
.
MaxDepth
!=
0
)
&&
(
f
.
depth
>
f
.
cs
.
MaxDepth
)
{
f
.
fs
.
Write
(
maxShortBytes
)
}
else
{
numEntries
:=
v
.
Len
()
for
i
:=
0
;
i
<
numEntries
;
i
++
{
if
i
>
0
{
f
.
fs
.
Write
(
spaceBytes
)
}
f
.
ignoreNextType
=
true
f
.
format
(
f
.
unpackValue
(
v
.
Index
(
i
)))
}
}
f
.
depth
--
f
.
fs
.
Write
(
closeBracketBytes
)
case
reflect
.
String
:
f
.
fs
.
Write
([]
byte
(
v
.
String
()))
case
reflect
.
Interface
:
// The only time we should get here is for nil interfaces due to
// unpackValue calls.
if
v
.
IsNil
()
{
f
.
fs
.
Write
(
nilAngleBytes
)
}
case
reflect
.
Ptr
:
// Do nothing. We should never get here since pointers have already
// been handled above.
case
reflect
.
Map
:
// nil maps should be indicated as different than empty maps
if
v
.
IsNil
()
{
f
.
fs
.
Write
(
nilAngleBytes
)
break
}
f
.
fs
.
Write
(
openMapBytes
)
f
.
depth
++
if
(
f
.
cs
.
MaxDepth
!=
0
)
&&
(
f
.
depth
>
f
.
cs
.
MaxDepth
)
{
f
.
fs
.
Write
(
maxShortBytes
)
}
else
{
keys
:=
v
.
MapKeys
()
if
f
.
cs
.
SortKeys
{
sortValues
(
keys
,
f
.
cs
)
}
for
i
,
key
:=
range
keys
{
if
i
>
0
{
f
.
fs
.
Write
(
spaceBytes
)
}
f
.
ignoreNextType
=
true
f
.
format
(
f
.
unpackValue
(
key
))
f
.
fs
.
Write
(
colonBytes
)
f
.
ignoreNextType
=
true
f
.
format
(
f
.
unpackValue
(
v
.
MapIndex
(
key
)))
}
}
f
.
depth
--
f
.
fs
.
Write
(
closeMapBytes
)
case
reflect
.
Struct
:
numFields
:=
v
.
NumField
()
f
.
fs
.
Write
(
openBraceBytes
)
f
.
depth
++
if
(
f
.
cs
.
MaxDepth
!=
0
)
&&
(
f
.
depth
>
f
.
cs
.
MaxDepth
)
{
f
.
fs
.
Write
(
maxShortBytes
)
}
else
{
vt
:=
v
.
Type
()
for
i
:=
0
;
i
<
numFields
;
i
++
{
if
i
>
0
{
f
.
fs
.
Write
(
spaceBytes
)
}
vtf
:=
vt
.
Field
(
i
)
if
f
.
fs
.
Flag
(
'+'
)
||
f
.
fs
.
Flag
(
'#'
)
{
f
.
fs
.
Write
([]
byte
(
vtf
.
Name
))
f
.
fs
.
Write
(
colonBytes
)
}
f
.
format
(
f
.
unpackValue
(
v
.
Field
(
i
)))
}
}
f
.
depth
--
f
.
fs
.
Write
(
closeBraceBytes
)
case
reflect
.
Uintptr
:
printHexPtr
(
f
.
fs
,
uintptr
(
v
.
Uint
()))
case
reflect
.
UnsafePointer
,
reflect
.
Chan
,
reflect
.
Func
:
printHexPtr
(
f
.
fs
,
v
.
Pointer
())
// There were not any other types at the time this code was written, but
// fall back to letting the default fmt package handle it if any get added.
default
:
format
:=
f
.
buildDefaultFormat
()
if
v
.
CanInterface
()
{
fmt
.
Fprintf
(
f
.
fs
,
format
,
v
.
Interface
())
}
else
{
fmt
.
Fprintf
(
f
.
fs
,
format
,
v
.
String
())
}
}
}
// Format satisfies the fmt.Formatter interface. See NewFormatter for usage
// details.
func
(
f
*
formatState
)
Format
(
fs
fmt
.
State
,
verb
rune
)
{
f
.
fs
=
fs
// Use standard formatting for verbs that are not v.
if
verb
!=
'v'
{
format
:=
f
.
constructOrigFormat
(
verb
)
fmt
.
Fprintf
(
fs
,
format
,
f
.
value
)
return
}
if
f
.
value
==
nil
{
if
fs
.
Flag
(
'#'
)
{
fs
.
Write
(
interfaceBytes
)
}
fs
.
Write
(
nilAngleBytes
)
return
}
f
.
format
(
reflect
.
ValueOf
(
f
.
value
))
}
// newFormatter is a helper function to consolidate the logic from the various
// public methods which take varying config states.
func
newFormatter
(
cs
*
ConfigState
,
v
interface
{})
fmt
.
Formatter
{
fs
:=
&
formatState
{
value
:
v
,
cs
:
cs
}
fs
.
pointers
=
make
(
map
[
uintptr
]
int
)
return
fs
}
/*
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
Printf, Println, or Fprintf.
*/
func
NewFormatter
(
v
interface
{})
fmt
.
Formatter
{
return
newFormatter
(
&
Config
,
v
)
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/format_test.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
Test Summary:
NOTE: For each test, a nil pointer, a single pointer and double pointer to the
base test element are also tested to ensure proper indirection across all types.
- Max int8, int16, int32, int64, int
- Max uint8, uint16, uint32, uint64, uint
- Boolean true and false
- Standard complex64 and complex128
- Array containing standard ints
- Array containing type with custom formatter on pointer receiver only
- Array containing interfaces
- Slice containing standard float32 values
- Slice containing type with custom formatter on pointer receiver only
- Slice containing interfaces
- Nil slice
- Standard string
- Nil interface
- Sub-interface
- Map with string keys and int vals
- Map with custom formatter type on pointer receiver only keys and vals
- Map with interface keys and values
- Map with nil interface value
- Struct with primitives
- Struct that contains another struct
- Struct that contains custom type with Stringer pointer interface via both
exported and unexported fields
- Struct that contains embedded struct and field to same struct
- Uintptr to 0 (null pointer)
- Uintptr address of real variable
- Unsafe.Pointer to 0 (null pointer)
- Unsafe.Pointer to address of real variable
- Nil channel
- Standard int channel
- Function with no params and no returns
- Function with param and no returns
- Function with multiple params and multiple returns
- Struct that is circular through self referencing
- Structs that are circular through cross referencing
- Structs that are indirectly circular
- Type that panics in its Stringer interface
- Type that has a custom Error interface
- %x passthrough with uint
- %#x passthrough with uint
- %f passthrough with precision
- %f passthrough with width and precision
- %d passthrough with width
- %q passthrough with string
*/
package
spew_test
import
(
"bytes"
"fmt"
"testing"
"unsafe"
"github.com/davecgh/go-spew/spew"
)
// formatterTest is used to describe a test to be perfomed against NewFormatter.
type
formatterTest
struct
{
format
string
in
interface
{}
wants
[]
string
}
// formatterTests houses all of the tests to be performed against NewFormatter.
var
formatterTests
=
make
([]
formatterTest
,
0
)
// addFormatterTest is a helper method to append the passed input and desired
// result to formatterTests.
func
addFormatterTest
(
format
string
,
in
interface
{},
wants
...
string
)
{
test
:=
formatterTest
{
format
,
in
,
wants
}
formatterTests
=
append
(
formatterTests
,
test
)
}
func
addIntFormatterTests
()
{
// Max int8.
v
:=
int8
(
127
)
nv
:=
(
*
int8
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"int8"
vs
:=
"127"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Max int16.
v2
:=
int16
(
32767
)
nv2
:=
(
*
int16
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"int16"
v2s
:=
"32767"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
// Max int32.
v3
:=
int32
(
2147483647
)
nv3
:=
(
*
int32
)(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"int32"
v3s
:=
"2147483647"
addFormatterTest
(
"%v"
,
v3
,
v3s
)
addFormatterTest
(
"%v"
,
pv3
,
"<*>"
+
v3s
)
addFormatterTest
(
"%v"
,
&
pv3
,
"<**>"
+
v3s
)
addFormatterTest
(
"%v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v3
,
v3s
)
addFormatterTest
(
"%+v"
,
pv3
,
"<*>("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
&
pv3
,
"<**>("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v3
,
"("
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
pv3
,
"(*"
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
&
pv3
,
"(**"
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v3
,
"("
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#+v"
,
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%#+v"
,
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
// Max int64.
v4
:=
int64
(
9223372036854775807
)
nv4
:=
(
*
int64
)(
nil
)
pv4
:=
&
v4
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"int64"
v4s
:=
"9223372036854775807"
addFormatterTest
(
"%v"
,
v4
,
v4s
)
addFormatterTest
(
"%v"
,
pv4
,
"<*>"
+
v4s
)
addFormatterTest
(
"%v"
,
&
pv4
,
"<**>"
+
v4s
)
addFormatterTest
(
"%v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v4
,
v4s
)
addFormatterTest
(
"%+v"
,
pv4
,
"<*>("
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%+v"
,
&
pv4
,
"<**>("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%+v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v4
,
"("
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
pv4
,
"(*"
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
&
pv4
,
"(**"
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v4
,
"("
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
// Max int.
v5
:=
int
(
2147483647
)
nv5
:=
(
*
int
)(
nil
)
pv5
:=
&
v5
v5Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv5
)
pv5Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv5
)
v5t
:=
"int"
v5s
:=
"2147483647"
addFormatterTest
(
"%v"
,
v5
,
v5s
)
addFormatterTest
(
"%v"
,
pv5
,
"<*>"
+
v5s
)
addFormatterTest
(
"%v"
,
&
pv5
,
"<**>"
+
v5s
)
addFormatterTest
(
"%v"
,
nv5
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v5
,
v5s
)
addFormatterTest
(
"%+v"
,
pv5
,
"<*>("
+
v5Addr
+
")"
+
v5s
)
addFormatterTest
(
"%+v"
,
&
pv5
,
"<**>("
+
pv5Addr
+
"->"
+
v5Addr
+
")"
+
v5s
)
addFormatterTest
(
"%+v"
,
nv5
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v5
,
"("
+
v5t
+
")"
+
v5s
)
addFormatterTest
(
"%#v"
,
pv5
,
"(*"
+
v5t
+
")"
+
v5s
)
addFormatterTest
(
"%#v"
,
&
pv5
,
"(**"
+
v5t
+
")"
+
v5s
)
addFormatterTest
(
"%#v"
,
nv5
,
"(*"
+
v5t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v5
,
"("
+
v5t
+
")"
+
v5s
)
addFormatterTest
(
"%#+v"
,
pv5
,
"(*"
+
v5t
+
")("
+
v5Addr
+
")"
+
v5s
)
addFormatterTest
(
"%#+v"
,
&
pv5
,
"(**"
+
v5t
+
")("
+
pv5Addr
+
"->"
+
v5Addr
+
")"
+
v5s
)
addFormatterTest
(
"%#+v"
,
nv5
,
"(*"
+
v5t
+
")"
+
"<nil>"
)
}
func
addUintFormatterTests
()
{
// Max uint8.
v
:=
uint8
(
255
)
nv
:=
(
*
uint8
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"uint8"
vs
:=
"255"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Max uint16.
v2
:=
uint16
(
65535
)
nv2
:=
(
*
uint16
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"uint16"
v2s
:=
"65535"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
// Max uint32.
v3
:=
uint32
(
4294967295
)
nv3
:=
(
*
uint32
)(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"uint32"
v3s
:=
"4294967295"
addFormatterTest
(
"%v"
,
v3
,
v3s
)
addFormatterTest
(
"%v"
,
pv3
,
"<*>"
+
v3s
)
addFormatterTest
(
"%v"
,
&
pv3
,
"<**>"
+
v3s
)
addFormatterTest
(
"%v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v3
,
v3s
)
addFormatterTest
(
"%+v"
,
pv3
,
"<*>("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
&
pv3
,
"<**>("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v3
,
"("
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
pv3
,
"(*"
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
&
pv3
,
"(**"
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v3
,
"("
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#+v"
,
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%#+v"
,
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
// Max uint64.
v4
:=
uint64
(
18446744073709551615
)
nv4
:=
(
*
uint64
)(
nil
)
pv4
:=
&
v4
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"uint64"
v4s
:=
"18446744073709551615"
addFormatterTest
(
"%v"
,
v4
,
v4s
)
addFormatterTest
(
"%v"
,
pv4
,
"<*>"
+
v4s
)
addFormatterTest
(
"%v"
,
&
pv4
,
"<**>"
+
v4s
)
addFormatterTest
(
"%v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v4
,
v4s
)
addFormatterTest
(
"%+v"
,
pv4
,
"<*>("
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%+v"
,
&
pv4
,
"<**>("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%+v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v4
,
"("
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
pv4
,
"(*"
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
&
pv4
,
"(**"
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v4
,
"("
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
// Max uint.
v5
:=
uint
(
4294967295
)
nv5
:=
(
*
uint
)(
nil
)
pv5
:=
&
v5
v5Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv5
)
pv5Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv5
)
v5t
:=
"uint"
v5s
:=
"4294967295"
addFormatterTest
(
"%v"
,
v5
,
v5s
)
addFormatterTest
(
"%v"
,
pv5
,
"<*>"
+
v5s
)
addFormatterTest
(
"%v"
,
&
pv5
,
"<**>"
+
v5s
)
addFormatterTest
(
"%v"
,
nv5
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v5
,
v5s
)
addFormatterTest
(
"%+v"
,
pv5
,
"<*>("
+
v5Addr
+
")"
+
v5s
)
addFormatterTest
(
"%+v"
,
&
pv5
,
"<**>("
+
pv5Addr
+
"->"
+
v5Addr
+
")"
+
v5s
)
addFormatterTest
(
"%+v"
,
nv5
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v5
,
"("
+
v5t
+
")"
+
v5s
)
addFormatterTest
(
"%#v"
,
pv5
,
"(*"
+
v5t
+
")"
+
v5s
)
addFormatterTest
(
"%#v"
,
&
pv5
,
"(**"
+
v5t
+
")"
+
v5s
)
addFormatterTest
(
"%#v"
,
nv5
,
"(*"
+
v5t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v5
,
"("
+
v5t
+
")"
+
v5s
)
addFormatterTest
(
"%#+v"
,
pv5
,
"(*"
+
v5t
+
")("
+
v5Addr
+
")"
+
v5s
)
addFormatterTest
(
"%#+v"
,
&
pv5
,
"(**"
+
v5t
+
")("
+
pv5Addr
+
"->"
+
v5Addr
+
")"
+
v5s
)
addFormatterTest
(
"%#v"
,
nv5
,
"(*"
+
v5t
+
")"
+
"<nil>"
)
}
func
addBoolFormatterTests
()
{
// Boolean true.
v
:=
bool
(
true
)
nv
:=
(
*
bool
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"bool"
vs
:=
"true"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Boolean false.
v2
:=
bool
(
false
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"bool"
v2s
:=
"false"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
}
func
addFloatFormatterTests
()
{
// Standard float32.
v
:=
float32
(
3.1415
)
nv
:=
(
*
float32
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"float32"
vs
:=
"3.1415"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Standard float64.
v2
:=
float64
(
3.1415926
)
nv2
:=
(
*
float64
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"float64"
v2s
:=
"3.1415926"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
}
func
addComplexFormatterTests
()
{
// Standard complex64.
v
:=
complex
(
float32
(
6
),
-
2
)
nv
:=
(
*
complex64
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"complex64"
vs
:=
"(6-2i)"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Standard complex128.
v2
:=
complex
(
float64
(
-
6
),
2
)
nv2
:=
(
*
complex128
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"complex128"
v2s
:=
"(-6+2i)"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
}
func
addArrayFormatterTests
()
{
// Array containing standard ints.
v
:=
[
3
]
int
{
1
,
2
,
3
}
nv
:=
(
*
[
3
]
int
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"[3]int"
vs
:=
"[1 2 3]"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Array containing type with custom formatter on pointer receiver only.
v2
:=
[
3
]
pstringer
{
"1"
,
"2"
,
"3"
}
nv2
:=
(
*
[
3
]
pstringer
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"[3]spew_test.pstringer"
v2s
:=
"[stringer 1 stringer 2 stringer 3]"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
// Array containing interfaces.
v3
:=
[
3
]
interface
{}{
"one"
,
int
(
2
),
uint
(
3
)}
nv3
:=
(
*
[
3
]
interface
{})(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"[3]interface {}"
v3t2
:=
"string"
v3t3
:=
"int"
v3t4
:=
"uint"
v3s
:=
"[one 2 3]"
v3s2
:=
"[("
+
v3t2
+
")one ("
+
v3t3
+
")2 ("
+
v3t4
+
")3]"
addFormatterTest
(
"%v"
,
v3
,
v3s
)
addFormatterTest
(
"%v"
,
pv3
,
"<*>"
+
v3s
)
addFormatterTest
(
"%v"
,
&
pv3
,
"<**>"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v3
,
v3s
)
addFormatterTest
(
"%+v"
,
pv3
,
"<*>("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
&
pv3
,
"<**>("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v3
,
"("
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
pv3
,
"(*"
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
&
pv3
,
"(**"
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v3
,
"("
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
}
func
addSliceFormatterTests
()
{
// Slice containing standard float32 values.
v
:=
[]
float32
{
3.14
,
6.28
,
12.56
}
nv
:=
(
*
[]
float32
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"[]float32"
vs
:=
"[3.14 6.28 12.56]"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Slice containing type with custom formatter on pointer receiver only.
v2
:=
[]
pstringer
{
"1"
,
"2"
,
"3"
}
nv2
:=
(
*
[]
pstringer
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"[]spew_test.pstringer"
v2s
:=
"[stringer 1 stringer 2 stringer 3]"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
// Slice containing interfaces.
v3
:=
[]
interface
{}{
"one"
,
int
(
2
),
uint
(
3
),
nil
}
nv3
:=
(
*
[]
interface
{})(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"[]interface {}"
v3t2
:=
"string"
v3t3
:=
"int"
v3t4
:=
"uint"
v3t5
:=
"interface {}"
v3s
:=
"[one 2 3 <nil>]"
v3s2
:=
"[("
+
v3t2
+
")one ("
+
v3t3
+
")2 ("
+
v3t4
+
")3 ("
+
v3t5
+
")<nil>]"
addFormatterTest
(
"%v"
,
v3
,
v3s
)
addFormatterTest
(
"%v"
,
pv3
,
"<*>"
+
v3s
)
addFormatterTest
(
"%v"
,
&
pv3
,
"<**>"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v3
,
v3s
)
addFormatterTest
(
"%+v"
,
pv3
,
"<*>("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
&
pv3
,
"<**>("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v3
,
"("
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
pv3
,
"(*"
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
&
pv3
,
"(**"
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v3
,
"("
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
// Nil slice.
var
v4
[]
int
nv4
:=
(
*
[]
int
)(
nil
)
pv4
:=
&
v4
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"[]int"
v4s
:=
"<nil>"
addFormatterTest
(
"%v"
,
v4
,
v4s
)
addFormatterTest
(
"%v"
,
pv4
,
"<*>"
+
v4s
)
addFormatterTest
(
"%v"
,
&
pv4
,
"<**>"
+
v4s
)
addFormatterTest
(
"%+v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v4
,
v4s
)
addFormatterTest
(
"%+v"
,
pv4
,
"<*>("
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%+v"
,
&
pv4
,
"<**>("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%+v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v4
,
"("
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
pv4
,
"(*"
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
&
pv4
,
"(**"
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v4
,
"("
+
v4t
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%#+v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
}
func
addStringFormatterTests
()
{
// Standard string.
v
:=
"test"
nv
:=
(
*
string
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"string"
vs
:=
"test"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
}
func
addInterfaceFormatterTests
()
{
// Nil interface.
var
v
interface
{}
nv
:=
(
*
interface
{})(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"interface {}"
vs
:=
"<nil>"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Sub-interface.
v2
:=
interface
{}(
uint16
(
65535
))
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"uint16"
v2s
:=
"65535"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
}
func
addMapFormatterTests
()
{
// Map with string keys and int vals.
v
:=
map
[
string
]
int
{
"one"
:
1
,
"two"
:
2
}
nilMap
:=
map
[
string
]
int
(
nil
)
nv
:=
(
*
map
[
string
]
int
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"map[string]int"
vs
:=
"map[one:1 two:2]"
vs2
:=
"map[two:2 one:1]"
addFormatterTest
(
"%v"
,
v
,
vs
,
vs2
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
,
"<*>"
+
vs2
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
,
"<**>"
+
vs2
)
addFormatterTest
(
"%+v"
,
nilMap
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
,
vs2
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
,
"<*>("
+
vAddr
+
")"
+
vs2
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs2
)
addFormatterTest
(
"%+v"
,
nilMap
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
,
"("
+
vt
+
")"
+
vs2
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
,
"(*"
+
vt
+
")"
+
vs2
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
,
"(**"
+
vt
+
")"
+
vs2
)
addFormatterTest
(
"%#v"
,
nilMap
,
"("
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
,
"("
+
vt
+
")"
+
vs2
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs2
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs2
)
addFormatterTest
(
"%#+v"
,
nilMap
,
"("
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Map with custom formatter type on pointer receiver only keys and vals.
v2
:=
map
[
pstringer
]
pstringer
{
"one"
:
"1"
}
nv2
:=
(
*
map
[
pstringer
]
pstringer
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"map[spew_test.pstringer]spew_test.pstringer"
v2s
:=
"map[stringer one:stringer 1]"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
// Map with interface keys and values.
v3
:=
map
[
interface
{}]
interface
{}{
"one"
:
1
}
nv3
:=
(
*
map
[
interface
{}]
interface
{})(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"map[interface {}]interface {}"
v3t1
:=
"string"
v3t2
:=
"int"
v3s
:=
"map[one:1]"
v3s2
:=
"map[("
+
v3t1
+
")one:("
+
v3t2
+
")1]"
addFormatterTest
(
"%v"
,
v3
,
v3s
)
addFormatterTest
(
"%v"
,
pv3
,
"<*>"
+
v3s
)
addFormatterTest
(
"%v"
,
&
pv3
,
"<**>"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v3
,
v3s
)
addFormatterTest
(
"%+v"
,
pv3
,
"<*>("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
&
pv3
,
"<**>("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v3
,
"("
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
pv3
,
"(*"
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
&
pv3
,
"(**"
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v3
,
"("
+
v3t
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s2
)
addFormatterTest
(
"%#+v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
// Map with nil interface value
v4
:=
map
[
string
]
interface
{}{
"nil"
:
nil
}
nv4
:=
(
*
map
[
string
]
interface
{})(
nil
)
pv4
:=
&
v4
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"map[string]interface {}"
v4t1
:=
"interface {}"
v4s
:=
"map[nil:<nil>]"
v4s2
:=
"map[nil:("
+
v4t1
+
")<nil>]"
addFormatterTest
(
"%v"
,
v4
,
v4s
)
addFormatterTest
(
"%v"
,
pv4
,
"<*>"
+
v4s
)
addFormatterTest
(
"%v"
,
&
pv4
,
"<**>"
+
v4s
)
addFormatterTest
(
"%+v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v4
,
v4s
)
addFormatterTest
(
"%+v"
,
pv4
,
"<*>("
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%+v"
,
&
pv4
,
"<**>("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s
)
addFormatterTest
(
"%+v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v4
,
"("
+
v4t
+
")"
+
v4s2
)
addFormatterTest
(
"%#v"
,
pv4
,
"(*"
+
v4t
+
")"
+
v4s2
)
addFormatterTest
(
"%#v"
,
&
pv4
,
"(**"
+
v4t
+
")"
+
v4s2
)
addFormatterTest
(
"%#v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v4
,
"("
+
v4t
+
")"
+
v4s2
)
addFormatterTest
(
"%#+v"
,
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")"
+
v4s2
)
addFormatterTest
(
"%#+v"
,
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s2
)
addFormatterTest
(
"%#+v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
}
func
addStructFormatterTests
()
{
// Struct with primitives.
type
s1
struct
{
a
int8
b
uint8
}
v
:=
s1
{
127
,
255
}
nv
:=
(
*
s1
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"spew_test.s1"
vt2
:=
"int8"
vt3
:=
"uint8"
vs
:=
"{127 255}"
vs2
:=
"{a:127 b:255}"
vs3
:=
"{a:("
+
vt2
+
")127 b:("
+
vt3
+
")255}"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs2
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs2
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs2
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs3
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs3
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs3
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs3
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs3
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs3
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Struct that contains another struct.
type
s2
struct
{
s1
s1
b
bool
}
v2
:=
s2
{
s1
{
127
,
255
},
true
}
nv2
:=
(
*
s2
)(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"spew_test.s2"
v2t2
:=
"spew_test.s1"
v2t3
:=
"int8"
v2t4
:=
"uint8"
v2t5
:=
"bool"
v2s
:=
"{{127 255} true}"
v2s2
:=
"{s1:{a:127 b:255} b:true}"
v2s3
:=
"{s1:("
+
v2t2
+
"){a:("
+
v2t3
+
")127 b:("
+
v2t4
+
")255} b:("
+
v2t5
+
")true}"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s2
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s2
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s2
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s3
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s3
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s3
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s3
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s3
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s3
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
// Struct that contains custom type with Stringer pointer interface via both
// exported and unexported fields.
type
s3
struct
{
s
pstringer
S
pstringer
}
v3
:=
s3
{
"test"
,
"test2"
}
nv3
:=
(
*
s3
)(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"spew_test.s3"
v3t2
:=
"spew_test.pstringer"
v3s
:=
"{stringer test stringer test2}"
v3s2
:=
"{s:stringer test S:stringer test2}"
v3s3
:=
"{s:("
+
v3t2
+
")stringer test S:("
+
v3t2
+
")stringer test2}"
addFormatterTest
(
"%v"
,
v3
,
v3s
)
addFormatterTest
(
"%v"
,
pv3
,
"<*>"
+
v3s
)
addFormatterTest
(
"%v"
,
&
pv3
,
"<**>"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v3
,
v3s2
)
addFormatterTest
(
"%+v"
,
pv3
,
"<*>("
+
v3Addr
+
")"
+
v3s2
)
addFormatterTest
(
"%+v"
,
&
pv3
,
"<**>("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s2
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v3
,
"("
+
v3t
+
")"
+
v3s3
)
addFormatterTest
(
"%#v"
,
pv3
,
"(*"
+
v3t
+
")"
+
v3s3
)
addFormatterTest
(
"%#v"
,
&
pv3
,
"(**"
+
v3t
+
")"
+
v3s3
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v3
,
"("
+
v3t
+
")"
+
v3s3
)
addFormatterTest
(
"%#+v"
,
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")"
+
v3s3
)
addFormatterTest
(
"%#+v"
,
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s3
)
addFormatterTest
(
"%#+v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
// Struct that contains embedded struct and field to same struct.
e
:=
embed
{
"embedstr"
}
v4
:=
embedwrap
{
embed
:
&
e
,
e
:
&
e
}
nv4
:=
(
*
embedwrap
)(
nil
)
pv4
:=
&
v4
eAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
e
)
v4Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv4
)
pv4Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv4
)
v4t
:=
"spew_test.embedwrap"
v4t2
:=
"spew_test.embed"
v4t3
:=
"string"
v4s
:=
"{<*>{embedstr} <*>{embedstr}}"
v4s2
:=
"{embed:<*>("
+
eAddr
+
"){a:embedstr} e:<*>("
+
eAddr
+
"){a:embedstr}}"
v4s3
:=
"{embed:(*"
+
v4t2
+
"){a:("
+
v4t3
+
")embedstr} e:(*"
+
v4t2
+
"){a:("
+
v4t3
+
")embedstr}}"
v4s4
:=
"{embed:(*"
+
v4t2
+
")("
+
eAddr
+
"){a:("
+
v4t3
+
")embedstr} e:(*"
+
v4t2
+
")("
+
eAddr
+
"){a:("
+
v4t3
+
")embedstr}}"
addFormatterTest
(
"%v"
,
v4
,
v4s
)
addFormatterTest
(
"%v"
,
pv4
,
"<*>"
+
v4s
)
addFormatterTest
(
"%v"
,
&
pv4
,
"<**>"
+
v4s
)
addFormatterTest
(
"%+v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v4
,
v4s2
)
addFormatterTest
(
"%+v"
,
pv4
,
"<*>("
+
v4Addr
+
")"
+
v4s2
)
addFormatterTest
(
"%+v"
,
&
pv4
,
"<**>("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s2
)
addFormatterTest
(
"%+v"
,
nv4
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v4
,
"("
+
v4t
+
")"
+
v4s3
)
addFormatterTest
(
"%#v"
,
pv4
,
"(*"
+
v4t
+
")"
+
v4s3
)
addFormatterTest
(
"%#v"
,
&
pv4
,
"(**"
+
v4t
+
")"
+
v4s3
)
addFormatterTest
(
"%#v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v4
,
"("
+
v4t
+
")"
+
v4s4
)
addFormatterTest
(
"%#+v"
,
pv4
,
"(*"
+
v4t
+
")("
+
v4Addr
+
")"
+
v4s4
)
addFormatterTest
(
"%#+v"
,
&
pv4
,
"(**"
+
v4t
+
")("
+
pv4Addr
+
"->"
+
v4Addr
+
")"
+
v4s4
)
addFormatterTest
(
"%#+v"
,
nv4
,
"(*"
+
v4t
+
")"
+
"<nil>"
)
}
func
addUintptrFormatterTests
()
{
// Null pointer.
v
:=
uintptr
(
0
)
nv
:=
(
*
uintptr
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"uintptr"
vs
:=
"<nil>"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Address of real variable.
i
:=
1
v2
:=
uintptr
(
unsafe
.
Pointer
(
&
i
))
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"uintptr"
v2s
:=
fmt
.
Sprintf
(
"%p"
,
&
i
)
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
}
func
addUnsafePointerFormatterTests
()
{
// Null pointer.
v
:=
unsafe
.
Pointer
(
uintptr
(
0
))
nv
:=
(
*
unsafe
.
Pointer
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"unsafe.Pointer"
vs
:=
"<nil>"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Address of real variable.
i
:=
1
v2
:=
unsafe
.
Pointer
(
&
i
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"unsafe.Pointer"
v2s
:=
fmt
.
Sprintf
(
"%p"
,
&
i
)
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
}
func
addChanFormatterTests
()
{
// Nil channel.
var
v
chan
int
pv
:=
&
v
nv
:=
(
*
chan
int
)(
nil
)
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"chan int"
vs
:=
"<nil>"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Real channel.
v2
:=
make
(
chan
int
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"chan int"
v2s
:=
fmt
.
Sprintf
(
"%p"
,
v2
)
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
}
func
addFuncFormatterTests
()
{
// Function with no params and no returns.
v
:=
addIntFormatterTests
nv
:=
(
*
func
())(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"func()"
vs
:=
fmt
.
Sprintf
(
"%p"
,
v
)
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
// Function with param and no returns.
v2
:=
TestFormatter
nv2
:=
(
*
func
(
*
testing
.
T
))(
nil
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"func(*testing.T)"
v2s
:=
fmt
.
Sprintf
(
"%p"
,
v2
)
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v2
,
v2s
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%+v"
,
nv2
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s
)
addFormatterTest
(
"%#+v"
,
nv2
,
"(*"
+
v2t
+
")"
+
"<nil>"
)
// Function with multiple params and multiple returns.
var
v3
=
func
(
i
int
,
s
string
)
(
b
bool
,
err
error
)
{
return
true
,
nil
}
nv3
:=
(
*
func
(
int
,
string
)
(
bool
,
error
))(
nil
)
pv3
:=
&
v3
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"func(int, string) (bool, error)"
v3s
:=
fmt
.
Sprintf
(
"%p"
,
v3
)
addFormatterTest
(
"%v"
,
v3
,
v3s
)
addFormatterTest
(
"%v"
,
pv3
,
"<*>"
+
v3s
)
addFormatterTest
(
"%v"
,
&
pv3
,
"<**>"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v3
,
v3s
)
addFormatterTest
(
"%+v"
,
pv3
,
"<*>("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
&
pv3
,
"<**>("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%+v"
,
nv3
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v3
,
"("
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
pv3
,
"(*"
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
&
pv3
,
"(**"
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v3
,
"("
+
v3t
+
")"
+
v3s
)
addFormatterTest
(
"%#+v"
,
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%#+v"
,
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s
)
addFormatterTest
(
"%#+v"
,
nv3
,
"(*"
+
v3t
+
")"
+
"<nil>"
)
}
func
addCircularFormatterTests
()
{
// Struct that is circular through self referencing.
type
circular
struct
{
c
*
circular
}
v
:=
circular
{
nil
}
v
.
c
=
&
v
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"spew_test.circular"
vs
:=
"{<*>{<*><shown>}}"
vs2
:=
"{<*><shown>}"
vs3
:=
"{c:<*>("
+
vAddr
+
"){c:<*>("
+
vAddr
+
")<shown>}}"
vs4
:=
"{c:<*>("
+
vAddr
+
")<shown>}"
vs5
:=
"{c:(*"
+
vt
+
"){c:(*"
+
vt
+
")<shown>}}"
vs6
:=
"{c:(*"
+
vt
+
")<shown>}"
vs7
:=
"{c:(*"
+
vt
+
")("
+
vAddr
+
"){c:(*"
+
vt
+
")("
+
vAddr
+
")<shown>}}"
vs8
:=
"{c:(*"
+
vt
+
")("
+
vAddr
+
")<shown>}"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs2
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs2
)
addFormatterTest
(
"%+v"
,
v
,
vs3
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs4
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs4
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs5
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs6
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs6
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs7
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs8
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs8
)
// Structs that are circular through cross referencing.
v2
:=
xref1
{
nil
}
ts2
:=
xref2
{
&
v2
}
v2
.
ps2
=
&
ts2
pv2
:=
&
v2
ts2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
ts2
)
v2Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv2
)
v2t
:=
"spew_test.xref1"
v2t2
:=
"spew_test.xref2"
v2s
:=
"{<*>{<*>{<*><shown>}}}"
v2s2
:=
"{<*>{<*><shown>}}"
v2s3
:=
"{ps2:<*>("
+
ts2Addr
+
"){ps1:<*>("
+
v2Addr
+
"){ps2:<*>("
+
ts2Addr
+
")<shown>}}}"
v2s4
:=
"{ps2:<*>("
+
ts2Addr
+
"){ps1:<*>("
+
v2Addr
+
")<shown>}}"
v2s5
:=
"{ps2:(*"
+
v2t2
+
"){ps1:(*"
+
v2t
+
"){ps2:(*"
+
v2t2
+
")<shown>}}}"
v2s6
:=
"{ps2:(*"
+
v2t2
+
"){ps1:(*"
+
v2t
+
")<shown>}}"
v2s7
:=
"{ps2:(*"
+
v2t2
+
")("
+
ts2Addr
+
"){ps1:(*"
+
v2t
+
")("
+
v2Addr
+
"){ps2:(*"
+
v2t2
+
")("
+
ts2Addr
+
")<shown>}}}"
v2s8
:=
"{ps2:(*"
+
v2t2
+
")("
+
ts2Addr
+
"){ps1:(*"
+
v2t
+
")("
+
v2Addr
+
")<shown>}}"
addFormatterTest
(
"%v"
,
v2
,
v2s
)
addFormatterTest
(
"%v"
,
pv2
,
"<*>"
+
v2s2
)
addFormatterTest
(
"%v"
,
&
pv2
,
"<**>"
+
v2s2
)
addFormatterTest
(
"%+v"
,
v2
,
v2s3
)
addFormatterTest
(
"%+v"
,
pv2
,
"<*>("
+
v2Addr
+
")"
+
v2s4
)
addFormatterTest
(
"%+v"
,
&
pv2
,
"<**>("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s4
)
addFormatterTest
(
"%#v"
,
v2
,
"("
+
v2t
+
")"
+
v2s5
)
addFormatterTest
(
"%#v"
,
pv2
,
"(*"
+
v2t
+
")"
+
v2s6
)
addFormatterTest
(
"%#v"
,
&
pv2
,
"(**"
+
v2t
+
")"
+
v2s6
)
addFormatterTest
(
"%#+v"
,
v2
,
"("
+
v2t
+
")"
+
v2s7
)
addFormatterTest
(
"%#+v"
,
pv2
,
"(*"
+
v2t
+
")("
+
v2Addr
+
")"
+
v2s8
)
addFormatterTest
(
"%#+v"
,
&
pv2
,
"(**"
+
v2t
+
")("
+
pv2Addr
+
"->"
+
v2Addr
+
")"
+
v2s8
)
// Structs that are indirectly circular.
v3
:=
indirCir1
{
nil
}
tic2
:=
indirCir2
{
nil
}
tic3
:=
indirCir3
{
&
v3
}
tic2
.
ps3
=
&
tic3
v3
.
ps2
=
&
tic2
pv3
:=
&
v3
tic2Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
tic2
)
tic3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
tic3
)
v3Addr
:=
fmt
.
Sprintf
(
"%p"
,
pv3
)
pv3Addr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv3
)
v3t
:=
"spew_test.indirCir1"
v3t2
:=
"spew_test.indirCir2"
v3t3
:=
"spew_test.indirCir3"
v3s
:=
"{<*>{<*>{<*>{<*><shown>}}}}"
v3s2
:=
"{<*>{<*>{<*><shown>}}}"
v3s3
:=
"{ps2:<*>("
+
tic2Addr
+
"){ps3:<*>("
+
tic3Addr
+
"){ps1:<*>("
+
v3Addr
+
"){ps2:<*>("
+
tic2Addr
+
")<shown>}}}}"
v3s4
:=
"{ps2:<*>("
+
tic2Addr
+
"){ps3:<*>("
+
tic3Addr
+
"){ps1:<*>("
+
v3Addr
+
")<shown>}}}"
v3s5
:=
"{ps2:(*"
+
v3t2
+
"){ps3:(*"
+
v3t3
+
"){ps1:(*"
+
v3t
+
"){ps2:(*"
+
v3t2
+
")<shown>}}}}"
v3s6
:=
"{ps2:(*"
+
v3t2
+
"){ps3:(*"
+
v3t3
+
"){ps1:(*"
+
v3t
+
")<shown>}}}"
v3s7
:=
"{ps2:(*"
+
v3t2
+
")("
+
tic2Addr
+
"){ps3:(*"
+
v3t3
+
")("
+
tic3Addr
+
"){ps1:(*"
+
v3t
+
")("
+
v3Addr
+
"){ps2:(*"
+
v3t2
+
")("
+
tic2Addr
+
")<shown>}}}}"
v3s8
:=
"{ps2:(*"
+
v3t2
+
")("
+
tic2Addr
+
"){ps3:(*"
+
v3t3
+
")("
+
tic3Addr
+
"){ps1:(*"
+
v3t
+
")("
+
v3Addr
+
")<shown>}}}"
addFormatterTest
(
"%v"
,
v3
,
v3s
)
addFormatterTest
(
"%v"
,
pv3
,
"<*>"
+
v3s2
)
addFormatterTest
(
"%v"
,
&
pv3
,
"<**>"
+
v3s2
)
addFormatterTest
(
"%+v"
,
v3
,
v3s3
)
addFormatterTest
(
"%+v"
,
pv3
,
"<*>("
+
v3Addr
+
")"
+
v3s4
)
addFormatterTest
(
"%+v"
,
&
pv3
,
"<**>("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s4
)
addFormatterTest
(
"%#v"
,
v3
,
"("
+
v3t
+
")"
+
v3s5
)
addFormatterTest
(
"%#v"
,
pv3
,
"(*"
+
v3t
+
")"
+
v3s6
)
addFormatterTest
(
"%#v"
,
&
pv3
,
"(**"
+
v3t
+
")"
+
v3s6
)
addFormatterTest
(
"%#+v"
,
v3
,
"("
+
v3t
+
")"
+
v3s7
)
addFormatterTest
(
"%#+v"
,
pv3
,
"(*"
+
v3t
+
")("
+
v3Addr
+
")"
+
v3s8
)
addFormatterTest
(
"%#+v"
,
&
pv3
,
"(**"
+
v3t
+
")("
+
pv3Addr
+
"->"
+
v3Addr
+
")"
+
v3s8
)
}
func
addPanicFormatterTests
()
{
// Type that panics in its Stringer interface.
v
:=
panicer
(
127
)
nv
:=
(
*
panicer
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"spew_test.panicer"
vs
:=
"(PANIC=test panic)127"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
}
func
addErrorFormatterTests
()
{
// Type that has a custom Error interface.
v
:=
customError
(
127
)
nv
:=
(
*
customError
)(
nil
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%p"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%p"
,
&
pv
)
vt
:=
"spew_test.customError"
vs
:=
"error: 127"
addFormatterTest
(
"%v"
,
v
,
vs
)
addFormatterTest
(
"%v"
,
pv
,
"<*>"
+
vs
)
addFormatterTest
(
"%v"
,
&
pv
,
"<**>"
+
vs
)
addFormatterTest
(
"%v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%+v"
,
v
,
vs
)
addFormatterTest
(
"%+v"
,
pv
,
"<*>("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
&
pv
,
"<**>("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%+v"
,
nv
,
"<nil>"
)
addFormatterTest
(
"%#v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
pv
,
"(*"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
&
pv
,
"(**"
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
addFormatterTest
(
"%#+v"
,
v
,
"("
+
vt
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
pv
,
"(*"
+
vt
+
")("
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
&
pv
,
"(**"
+
vt
+
")("
+
pvAddr
+
"->"
+
vAddr
+
")"
+
vs
)
addFormatterTest
(
"%#+v"
,
nv
,
"(*"
+
vt
+
")"
+
"<nil>"
)
}
func
addPassthroughFormatterTests
()
{
// %x passthrough with uint.
v
:=
uint
(
4294967295
)
pv
:=
&
v
vAddr
:=
fmt
.
Sprintf
(
"%x"
,
pv
)
pvAddr
:=
fmt
.
Sprintf
(
"%x"
,
&
pv
)
vs
:=
"ffffffff"
addFormatterTest
(
"%x"
,
v
,
vs
)
addFormatterTest
(
"%x"
,
pv
,
vAddr
)
addFormatterTest
(
"%x"
,
&
pv
,
pvAddr
)
// %#x passthrough with uint.
v2
:=
int
(
2147483647
)
pv2
:=
&
v2
v2Addr
:=
fmt
.
Sprintf
(
"%#x"
,
pv2
)
pv2Addr
:=
fmt
.
Sprintf
(
"%#x"
,
&
pv2
)
v2s
:=
"0x7fffffff"
addFormatterTest
(
"%#x"
,
v2
,
v2s
)
addFormatterTest
(
"%#x"
,
pv2
,
v2Addr
)
addFormatterTest
(
"%#x"
,
&
pv2
,
pv2Addr
)
// %f passthrough with precision.
addFormatterTest
(
"%.2f"
,
3.1415
,
"3.14"
)
addFormatterTest
(
"%.3f"
,
3.1415
,
"3.142"
)
addFormatterTest
(
"%.4f"
,
3.1415
,
"3.1415"
)
// %f passthrough with width and precision.
addFormatterTest
(
"%5.2f"
,
3.1415
,
" 3.14"
)
addFormatterTest
(
"%6.3f"
,
3.1415
,
" 3.142"
)
addFormatterTest
(
"%7.4f"
,
3.1415
,
" 3.1415"
)
// %d passthrough with width.
addFormatterTest
(
"%3d"
,
127
,
"127"
)
addFormatterTest
(
"%4d"
,
127
,
" 127"
)
addFormatterTest
(
"%5d"
,
127
,
" 127"
)
// %q passthrough with string.
addFormatterTest
(
"%q"
,
"test"
,
"
\"
test
\"
"
)
}
// TestFormatter executes all of the tests described by formatterTests.
func
TestFormatter
(
t
*
testing
.
T
)
{
// Setup tests.
addIntFormatterTests
()
addUintFormatterTests
()
addBoolFormatterTests
()
addFloatFormatterTests
()
addComplexFormatterTests
()
addArrayFormatterTests
()
addSliceFormatterTests
()
addStringFormatterTests
()
addInterfaceFormatterTests
()
addMapFormatterTests
()
addStructFormatterTests
()
addUintptrFormatterTests
()
addUnsafePointerFormatterTests
()
addChanFormatterTests
()
addFuncFormatterTests
()
addCircularFormatterTests
()
addPanicFormatterTests
()
addErrorFormatterTests
()
addPassthroughFormatterTests
()
t
.
Logf
(
"Running %d tests"
,
len
(
formatterTests
))
for
i
,
test
:=
range
formatterTests
{
buf
:=
new
(
bytes
.
Buffer
)
spew
.
Fprintf
(
buf
,
test
.
format
,
test
.
in
)
s
:=
buf
.
String
()
if
testFailed
(
s
,
test
.
wants
)
{
t
.
Errorf
(
"Formatter #%d format: %s got: %s %s"
,
i
,
test
.
format
,
s
,
stringizeWants
(
test
.
wants
))
continue
}
}
}
type
testStruct
struct
{
x
int
}
func
(
ts
testStruct
)
String
()
string
{
return
fmt
.
Sprintf
(
"ts.%d"
,
ts
.
x
)
}
type
testStructP
struct
{
x
int
}
func
(
ts
*
testStructP
)
String
()
string
{
return
fmt
.
Sprintf
(
"ts.%d"
,
ts
.
x
)
}
func
TestPrintSortedKeys
(
t
*
testing
.
T
)
{
cfg
:=
spew
.
ConfigState
{
SortKeys
:
true
}
s
:=
cfg
.
Sprint
(
map
[
int
]
string
{
1
:
"1"
,
3
:
"3"
,
2
:
"2"
})
expected
:=
"map[1:1 2:2 3:3]"
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
s
=
cfg
.
Sprint
(
map
[
stringer
]
int
{
"1"
:
1
,
"3"
:
3
,
"2"
:
2
})
expected
=
"map[stringer 1:1 stringer 2:2 stringer 3:3]"
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
s
=
cfg
.
Sprint
(
map
[
pstringer
]
int
{
pstringer
(
"1"
)
:
1
,
pstringer
(
"3"
)
:
3
,
pstringer
(
"2"
)
:
2
})
expected
=
"map[stringer 1:1 stringer 2:2 stringer 3:3]"
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
s
=
cfg
.
Sprint
(
map
[
testStruct
]
int
{
testStruct
{
1
}
:
1
,
testStruct
{
3
}
:
3
,
testStruct
{
2
}
:
2
})
expected
=
"map[ts.1:1 ts.2:2 ts.3:3]"
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
s
=
cfg
.
Sprint
(
map
[
testStructP
]
int
{
testStructP
{
1
}
:
1
,
testStructP
{
3
}
:
3
,
testStructP
{
2
}
:
2
})
expected
=
"map[ts.1:1 ts.2:2 ts.3:3]"
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
s
=
cfg
.
Sprint
(
map
[
customError
]
int
{
customError
(
1
)
:
1
,
customError
(
3
)
:
3
,
customError
(
2
)
:
2
})
expected
=
"map[error: 1:1 error: 2:2 error: 3:3]"
if
s
!=
expected
{
t
.
Errorf
(
"Sorted keys mismatch:
\n
%v %v"
,
s
,
expected
)
}
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/internal_test.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
This test file is part of the spew package rather than than the spew_test
package because it needs access to internals to properly test certain cases
which are not possible via the public interface since they should never happen.
*/
package
spew
import
(
"bytes"
"reflect"
"testing"
"unsafe"
)
// dummyFmtState implements a fake fmt.State to use for testing invalid
// reflect.Value handling. This is necessary because the fmt package catches
// invalid values before invoking the formatter on them.
type
dummyFmtState
struct
{
bytes
.
Buffer
}
func
(
dfs
*
dummyFmtState
)
Flag
(
f
int
)
bool
{
if
f
==
int
(
'+'
)
{
return
true
}
return
false
}
func
(
dfs
*
dummyFmtState
)
Precision
()
(
int
,
bool
)
{
return
0
,
false
}
func
(
dfs
*
dummyFmtState
)
Width
()
(
int
,
bool
)
{
return
0
,
false
}
// TestInvalidReflectValue ensures the dump and formatter code handles an
// invalid reflect value properly. This needs access to internal state since it
// should never happen in real code and therefore can't be tested via the public
// API.
func
TestInvalidReflectValue
(
t
*
testing
.
T
)
{
i
:=
1
// Dump invalid reflect value.
v
:=
new
(
reflect
.
Value
)
buf
:=
new
(
bytes
.
Buffer
)
d
:=
dumpState
{
w
:
buf
,
cs
:
&
Config
}
d
.
dump
(
*
v
)
s
:=
buf
.
String
()
want
:=
"<invalid>"
if
s
!=
want
{
t
.
Errorf
(
"InvalidReflectValue #%d
\n
got: %s want: %s"
,
i
,
s
,
want
)
}
i
++
// Formatter invalid reflect value.
buf2
:=
new
(
dummyFmtState
)
f
:=
formatState
{
value
:
*
v
,
cs
:
&
Config
,
fs
:
buf2
}
f
.
format
(
*
v
)
s
=
buf2
.
String
()
want
=
"<invalid>"
if
s
!=
want
{
t
.
Errorf
(
"InvalidReflectValue #%d got: %s want: %s"
,
i
,
s
,
want
)
}
}
// changeKind uses unsafe to intentionally change the kind of a reflect.Value to
// the maximum kind value which does not exist. This is needed to test the
// fallback code which punts to the standard fmt library for new types that
// might get added to the language.
func
changeKind
(
v
*
reflect
.
Value
,
readOnly
bool
)
{
rvf
:=
(
*
uintptr
)(
unsafe
.
Pointer
(
uintptr
(
unsafe
.
Pointer
(
v
))
+
offsetFlag
))
*
rvf
=
*
rvf
|
((
1
<<
flagKindWidth
-
1
)
<<
flagKindShift
)
if
readOnly
{
*
rvf
|=
flagRO
}
else
{
*
rvf
&=
^
uintptr
(
flagRO
)
}
}
// TestAddedReflectValue tests functionaly of the dump and formatter code which
// falls back to the standard fmt library for new types that might get added to
// the language.
func
TestAddedReflectValue
(
t
*
testing
.
T
)
{
i
:=
1
// Dump using a reflect.Value that is exported.
v
:=
reflect
.
ValueOf
(
int8
(
5
))
changeKind
(
&
v
,
false
)
buf
:=
new
(
bytes
.
Buffer
)
d
:=
dumpState
{
w
:
buf
,
cs
:
&
Config
}
d
.
dump
(
v
)
s
:=
buf
.
String
()
want
:=
"(int8) 5"
if
s
!=
want
{
t
.
Errorf
(
"TestAddedReflectValue #%d
\n
got: %s want: %s"
,
i
,
s
,
want
)
}
i
++
// Dump using a reflect.Value that is not exported.
changeKind
(
&
v
,
true
)
buf
.
Reset
()
d
.
dump
(
v
)
s
=
buf
.
String
()
want
=
"(int8) <int8 Value>"
if
s
!=
want
{
t
.
Errorf
(
"TestAddedReflectValue #%d
\n
got: %s want: %s"
,
i
,
s
,
want
)
}
i
++
// Formatter using a reflect.Value that is exported.
changeKind
(
&
v
,
false
)
buf2
:=
new
(
dummyFmtState
)
f
:=
formatState
{
value
:
v
,
cs
:
&
Config
,
fs
:
buf2
}
f
.
format
(
v
)
s
=
buf2
.
String
()
want
=
"5"
if
s
!=
want
{
t
.
Errorf
(
"TestAddedReflectValue #%d got: %s want: %s"
,
i
,
s
,
want
)
}
i
++
// Formatter using a reflect.Value that is not exported.
changeKind
(
&
v
,
true
)
buf2
.
Reset
()
f
=
formatState
{
value
:
v
,
cs
:
&
Config
,
fs
:
buf2
}
f
.
format
(
v
)
s
=
buf2
.
String
()
want
=
"<int8 Value>"
if
s
!=
want
{
t
.
Errorf
(
"TestAddedReflectValue #%d got: %s want: %s"
,
i
,
s
,
want
)
}
}
// SortValues makes the internal sortValues function available to the test
// package.
func
SortValues
(
values
[]
reflect
.
Value
,
cs
*
ConfigState
)
{
sortValues
(
values
,
cs
)
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package
spew
import
(
"fmt"
"io"
)
// Errorf is a wrapper for fmt.Errorf that treats each argument as if it were
// passed with a default Formatter interface returned by 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, spew.NewFormatter(a), spew.NewFormatter(b))
func
Errorf
(
format
string
,
a
...
interface
{})
(
err
error
)
{
return
fmt
.
Errorf
(
format
,
convertArgs
(
a
)
...
)
}
// Fprint is a wrapper for fmt.Fprint that treats each argument as if it were
// passed with a default Formatter interface returned by 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, spew.NewFormatter(a), spew.NewFormatter(b))
func
Fprint
(
w
io
.
Writer
,
a
...
interface
{})
(
n
int
,
err
error
)
{
return
fmt
.
Fprint
(
w
,
convertArgs
(
a
)
...
)
}
// Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were
// passed with a default Formatter interface returned by 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, spew.NewFormatter(a), spew.NewFormatter(b))
func
Fprintf
(
w
io
.
Writer
,
format
string
,
a
...
interface
{})
(
n
int
,
err
error
)
{
return
fmt
.
Fprintf
(
w
,
format
,
convertArgs
(
a
)
...
)
}
// Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it
// passed with a default Formatter interface returned by NewFormatter. See
// NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b))
func
Fprintln
(
w
io
.
Writer
,
a
...
interface
{})
(
n
int
,
err
error
)
{
return
fmt
.
Fprintln
(
w
,
convertArgs
(
a
)
...
)
}
// Print is a wrapper for fmt.Print that treats each argument as if it were
// passed with a default Formatter interface returned by 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(spew.NewFormatter(a), spew.NewFormatter(b))
func
Print
(
a
...
interface
{})
(
n
int
,
err
error
)
{
return
fmt
.
Print
(
convertArgs
(
a
)
...
)
}
// Printf is a wrapper for fmt.Printf that treats each argument as if it were
// passed with a default Formatter interface returned by 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, spew.NewFormatter(a), spew.NewFormatter(b))
func
Printf
(
format
string
,
a
...
interface
{})
(
n
int
,
err
error
)
{
return
fmt
.
Printf
(
format
,
convertArgs
(
a
)
...
)
}
// Println is a wrapper for fmt.Println that treats each argument as if it were
// passed with a default Formatter interface returned by 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(spew.NewFormatter(a), spew.NewFormatter(b))
func
Println
(
a
...
interface
{})
(
n
int
,
err
error
)
{
return
fmt
.
Println
(
convertArgs
(
a
)
...
)
}
// Sprint is a wrapper for fmt.Sprint that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b))
func
Sprint
(
a
...
interface
{})
string
{
return
fmt
.
Sprint
(
convertArgs
(
a
)
...
)
}
// Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were
// passed with a default Formatter interface returned by NewFormatter. It
// returns the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b))
func
Sprintf
(
format
string
,
a
...
interface
{})
string
{
return
fmt
.
Sprintf
(
format
,
convertArgs
(
a
)
...
)
}
// Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it
// were passed with a default Formatter interface returned by NewFormatter. It
// returns the resulting string. See NewFormatter for formatting details.
//
// This function is shorthand for the following syntax:
//
// fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b))
func
Sprintln
(
a
...
interface
{})
string
{
return
fmt
.
Sprintln
(
convertArgs
(
a
)
...
)
}
// convertArgs accepts a slice of arguments and returns a slice of the same
// length with each argument converted to a default spew Formatter interface.
func
convertArgs
(
args
[]
interface
{})
(
formatters
[]
interface
{})
{
formatters
=
make
([]
interface
{},
len
(
args
))
for
index
,
arg
:=
range
args
{
formatters
[
index
]
=
NewFormatter
(
arg
)
}
return
formatters
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/spew_test.go
0 → 100644
View file @
7b933418
/*
* Copyright (c) 2013 Dave Collins <dave@davec.name>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
package
spew_test
import
(
"bytes"
"fmt"
"github.com/davecgh/go-spew/spew"
"io/ioutil"
"os"
"testing"
)
// spewFunc is used to identify which public function of the spew package or
// ConfigState a test applies to.
type
spewFunc
int
const
(
fCSFdump
spewFunc
=
iota
fCSFprint
fCSFprintf
fCSFprintln
fCSPrint
fCSPrintln
fCSSdump
fCSSprint
fCSSprintf
fCSSprintln
fCSErrorf
fCSNewFormatter
fErrorf
fFprint
fFprintln
fPrint
fPrintln
fSdump
fSprint
fSprintf
fSprintln
)
// Map of spewFunc values to names for pretty printing.
var
spewFuncStrings
=
map
[
spewFunc
]
string
{
fCSFdump
:
"ConfigState.Fdump"
,
fCSFprint
:
"ConfigState.Fprint"
,
fCSFprintf
:
"ConfigState.Fprintf"
,
fCSFprintln
:
"ConfigState.Fprintln"
,
fCSSdump
:
"ConfigState.Sdump"
,
fCSPrint
:
"ConfigState.Print"
,
fCSPrintln
:
"ConfigState.Println"
,
fCSSprint
:
"ConfigState.Sprint"
,
fCSSprintf
:
"ConfigState.Sprintf"
,
fCSSprintln
:
"ConfigState.Sprintln"
,
fCSErrorf
:
"ConfigState.Errorf"
,
fCSNewFormatter
:
"ConfigState.NewFormatter"
,
fErrorf
:
"spew.Errorf"
,
fFprint
:
"spew.Fprint"
,
fFprintln
:
"spew.Fprintln"
,
fPrint
:
"spew.Print"
,
fPrintln
:
"spew.Println"
,
fSdump
:
"spew.Sdump"
,
fSprint
:
"spew.Sprint"
,
fSprintf
:
"spew.Sprintf"
,
fSprintln
:
"spew.Sprintln"
,
}
func
(
f
spewFunc
)
String
()
string
{
if
s
,
ok
:=
spewFuncStrings
[
f
];
ok
{
return
s
}
return
fmt
.
Sprintf
(
"Unknown spewFunc (%d)"
,
int
(
f
))
}
// spewTest is used to describe a test to be performed against the public
// functions of the spew package or ConfigState.
type
spewTest
struct
{
cs
*
spew
.
ConfigState
f
spewFunc
format
string
in
interface
{}
want
string
}
// spewTests houses the tests to be performed against the public functions of
// 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
// redirStdout is a helper function to return the standard output from f as a
// byte slice.
func
redirStdout
(
f
func
())
([]
byte
,
error
)
{
tempFile
,
err
:=
ioutil
.
TempFile
(
""
,
"ss-test"
)
if
err
!=
nil
{
return
nil
,
err
}
fileName
:=
tempFile
.
Name
()
defer
os
.
Remove
(
fileName
)
// Ignore error
origStdout
:=
os
.
Stdout
os
.
Stdout
=
tempFile
f
()
os
.
Stdout
=
origStdout
tempFile
.
Close
()
return
ioutil
.
ReadFile
(
fileName
)
}
func
initSpewTests
()
{
// Config states with various settings.
scsDefault
:=
spew
.
NewDefaultConfig
()
scsNoMethods
:=
&
spew
.
ConfigState
{
Indent
:
" "
,
DisableMethods
:
true
}
scsNoPmethods
:=
&
spew
.
ConfigState
{
Indent
:
" "
,
DisablePointerMethods
:
true
}
scsMaxDepth
:=
&
spew
.
ConfigState
{
Indent
:
" "
,
MaxDepth
:
1
}
scsContinue
:=
&
spew
.
ConfigState
{
Indent
:
" "
,
ContinueOnMethod
:
true
}
// Variables for tests on types which implement Stringer interface with and
// without a pointer receiver.
ts
:=
stringer
(
"test"
)
tps
:=
pstringer
(
"test"
)
// depthTester is used to test max depth handling for structs, array, slices
// and maps.
type
depthTester
struct
{
ic
indirCir1
arr
[
1
]
string
slice
[]
string
m
map
[
string
]
int
}
dt
:=
depthTester
{
indirCir1
{
nil
},
[
1
]
string
{
"arr"
},
[]
string
{
"slice"
},
map
[
string
]
int
{
"one"
:
1
}}
// Variable for tests on types which implement error interface.
te
:=
customError
(
10
)
spewTests
=
[]
spewTest
{
{
scsDefault
,
fCSFdump
,
""
,
int8
(
127
),
"(int8) 127
\n
"
},
{
scsDefault
,
fCSFprint
,
""
,
int16
(
32767
),
"32767"
},
{
scsDefault
,
fCSFprintf
,
"%v"
,
int32
(
2147483647
),
"2147483647"
},
{
scsDefault
,
fCSFprintln
,
""
,
int
(
2147483647
),
"2147483647
\n
"
},
{
scsDefault
,
fCSPrint
,
""
,
int64
(
9223372036854775807
),
"9223372036854775807"
},
{
scsDefault
,
fCSPrintln
,
""
,
uint8
(
255
),
"255
\n
"
},
{
scsDefault
,
fCSSdump
,
""
,
uint8
(
64
),
"(uint8) 64
\n
"
},
{
scsDefault
,
fCSSprint
,
""
,
complex
(
1
,
2
),
"(1+2i)"
},
{
scsDefault
,
fCSSprintf
,
"%v"
,
complex
(
float32
(
3
),
4
),
"(3+4i)"
},
{
scsDefault
,
fCSSprintln
,
""
,
complex
(
float64
(
5
),
6
),
"(5+6i)
\n
"
},
{
scsDefault
,
fCSErrorf
,
"%#v"
,
uint16
(
65535
),
"(uint16)65535"
},
{
scsDefault
,
fCSNewFormatter
,
"%v"
,
uint32
(
4294967295
),
"4294967295"
},
{
scsDefault
,
fErrorf
,
"%v"
,
uint64
(
18446744073709551615
),
"18446744073709551615"
},
{
scsDefault
,
fFprint
,
""
,
float32
(
3.14
),
"3.14"
},
{
scsDefault
,
fFprintln
,
""
,
float64
(
6.28
),
"6.28
\n
"
},
{
scsDefault
,
fPrint
,
""
,
true
,
"true"
},
{
scsDefault
,
fPrintln
,
""
,
false
,
"false
\n
"
},
{
scsDefault
,
fSdump
,
""
,
complex
(
-
10
,
-
20
),
"(complex128) (-10-20i)
\n
"
},
{
scsDefault
,
fSprint
,
""
,
complex
(
-
1
,
-
2
),
"(-1-2i)"
},
{
scsDefault
,
fSprintf
,
"%v"
,
complex
(
float32
(
-
3
),
-
4
),
"(-3-4i)"
},
{
scsDefault
,
fSprintln
,
""
,
complex
(
float64
(
-
5
),
-
6
),
"(-5-6i)
\n
"
},
{
scsNoMethods
,
fCSFprint
,
""
,
ts
,
"test"
},
{
scsNoMethods
,
fCSFprint
,
""
,
&
ts
,
"<*>test"
},
{
scsNoMethods
,
fCSFprint
,
""
,
tps
,
"test"
},
{
scsNoMethods
,
fCSFprint
,
""
,
&
tps
,
"<*>test"
},
{
scsNoPmethods
,
fCSFprint
,
""
,
ts
,
"stringer test"
},
{
scsNoPmethods
,
fCSFprint
,
""
,
&
ts
,
"<*>stringer test"
},
{
scsNoPmethods
,
fCSFprint
,
""
,
tps
,
"test"
},
{
scsNoPmethods
,
fCSFprint
,
""
,
&
tps
,
"<*>stringer test"
},
{
scsMaxDepth
,
fCSFprint
,
""
,
dt
,
"{{<max>} [<max>] [<max>] map[<max>]}"
},
{
scsMaxDepth
,
fCSFdump
,
""
,
dt
,
"(spew_test.depthTester) {
\n
"
+
" ic: (spew_test.indirCir1) {
\n
<max depth reached>
\n
},
\n
"
+
" arr: ([1]string) (len=1 cap=1) {
\n
<max depth reached>
\n
},
\n
"
+
" slice: ([]string) (len=1 cap=1) {
\n
<max depth reached>
\n
},
\n
"
+
" m: (map[string]int) (len=1) {
\n
<max depth reached>
\n
}
\n
}
\n
"
},
{
scsContinue
,
fCSFprint
,
""
,
ts
,
"(stringer test) test"
},
{
scsContinue
,
fCSFdump
,
""
,
ts
,
"(spew_test.stringer) "
+
"(len=4) (stringer test)
\"
test
\"\n
"
},
{
scsContinue
,
fCSFprint
,
""
,
te
,
"(error: 10) 10"
},
{
scsContinue
,
fCSFdump
,
""
,
te
,
"(spew_test.customError) "
+
"(error: 10) 10
\n
"
},
}
}
// TestSpew executes all of the tests described by spewTests.
func
TestSpew
(
t
*
testing
.
T
)
{
initSpewTests
()
t
.
Logf
(
"Running %d tests"
,
len
(
spewTests
))
for
i
,
test
:=
range
spewTests
{
buf
:=
new
(
bytes
.
Buffer
)
switch
test
.
f
{
case
fCSFdump
:
test
.
cs
.
Fdump
(
buf
,
test
.
in
)
case
fCSFprint
:
test
.
cs
.
Fprint
(
buf
,
test
.
in
)
case
fCSFprintf
:
test
.
cs
.
Fprintf
(
buf
,
test
.
format
,
test
.
in
)
case
fCSFprintln
:
test
.
cs
.
Fprintln
(
buf
,
test
.
in
)
case
fCSPrint
:
b
,
err
:=
redirStdout
(
func
()
{
test
.
cs
.
Print
(
test
.
in
)
})
if
err
!=
nil
{
t
.
Errorf
(
"%v #%d %v"
,
test
.
f
,
i
,
err
)
continue
}
buf
.
Write
(
b
)
case
fCSPrintln
:
b
,
err
:=
redirStdout
(
func
()
{
test
.
cs
.
Println
(
test
.
in
)
})
if
err
!=
nil
{
t
.
Errorf
(
"%v #%d %v"
,
test
.
f
,
i
,
err
)
continue
}
buf
.
Write
(
b
)
case
fCSSdump
:
str
:=
test
.
cs
.
Sdump
(
test
.
in
)
buf
.
WriteString
(
str
)
case
fCSSprint
:
str
:=
test
.
cs
.
Sprint
(
test
.
in
)
buf
.
WriteString
(
str
)
case
fCSSprintf
:
str
:=
test
.
cs
.
Sprintf
(
test
.
format
,
test
.
in
)
buf
.
WriteString
(
str
)
case
fCSSprintln
:
str
:=
test
.
cs
.
Sprintln
(
test
.
in
)
buf
.
WriteString
(
str
)
case
fCSErrorf
:
err
:=
test
.
cs
.
Errorf
(
test
.
format
,
test
.
in
)
buf
.
WriteString
(
err
.
Error
())
case
fCSNewFormatter
:
fmt
.
Fprintf
(
buf
,
test
.
format
,
test
.
cs
.
NewFormatter
(
test
.
in
))
case
fErrorf
:
err
:=
spew
.
Errorf
(
test
.
format
,
test
.
in
)
buf
.
WriteString
(
err
.
Error
())
case
fFprint
:
spew
.
Fprint
(
buf
,
test
.
in
)
case
fFprintln
:
spew
.
Fprintln
(
buf
,
test
.
in
)
case
fPrint
:
b
,
err
:=
redirStdout
(
func
()
{
spew
.
Print
(
test
.
in
)
})
if
err
!=
nil
{
t
.
Errorf
(
"%v #%d %v"
,
test
.
f
,
i
,
err
)
continue
}
buf
.
Write
(
b
)
case
fPrintln
:
b
,
err
:=
redirStdout
(
func
()
{
spew
.
Println
(
test
.
in
)
})
if
err
!=
nil
{
t
.
Errorf
(
"%v #%d %v"
,
test
.
f
,
i
,
err
)
continue
}
buf
.
Write
(
b
)
case
fSdump
:
str
:=
spew
.
Sdump
(
test
.
in
)
buf
.
WriteString
(
str
)
case
fSprint
:
str
:=
spew
.
Sprint
(
test
.
in
)
buf
.
WriteString
(
str
)
case
fSprintf
:
str
:=
spew
.
Sprintf
(
test
.
format
,
test
.
in
)
buf
.
WriteString
(
str
)
case
fSprintln
:
str
:=
spew
.
Sprintln
(
test
.
in
)
buf
.
WriteString
(
str
)
default
:
t
.
Errorf
(
"%v #%d unrecognized function"
,
test
.
f
,
i
)
continue
}
s
:=
buf
.
String
()
if
test
.
want
!=
s
{
t
.
Errorf
(
"ConfigState #%d
\n
got: %s want: %s"
,
i
,
s
,
test
.
want
)
continue
}
}
}
Godeps/_workspace/src/github.com/davecgh/go-spew/spew/testdata/dumpcgo.go
0 → 100644
View file @
7b933418
// Copyright (c) 2013 Dave Collins <dave@davec.name>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// NOTE: Due to the following build constraints, this file will only be compiled
// when both cgo is supported and "-tags testcgo" is added to the go test
// command line. This code should really only be in the dumpcgo_test.go file,
// but unfortunately Go will not allow cgo in test files, so this is a
// workaround to allow cgo types to be tested. This configuration is used
// because spew itself does not require cgo to run even though it does handle
// certain cgo types specially. Rather than forcing all clients to require cgo
// and an external C compiler just to run the tests, this scheme makes them
// optional.
// +build cgo,testcgo
package
testdata
/*
#include <stdint.h>
typedef unsigned char custom_uchar_t;
char *ncp = 0;
char *cp = "test";
char ca[6] = {'t', 'e', 's', 't', '2', '\0'};
unsigned char uca[6] = {'t', 'e', 's', 't', '3', '\0'};
signed char sca[6] = {'t', 'e', 's', 't', '4', '\0'};
uint8_t ui8ta[6] = {'t', 'e', 's', 't', '5', '\0'};
custom_uchar_t tuca[6] = {'t', 'e', 's', 't', '6', '\0'};
*/
import
"C"
// GetCgoNullCharPointer returns a null char pointer via cgo. This is only
// used for tests.
func
GetCgoNullCharPointer
()
interface
{}
{
return
C
.
ncp
}
// GetCgoCharPointer returns a char pointer via cgo. This is only used for
// tests.
func
GetCgoCharPointer
()
interface
{}
{
return
C
.
cp
}
// GetCgoCharArray returns a char array via cgo and the array's len and cap.
// This is only used for tests.
func
GetCgoCharArray
()
(
interface
{},
int
,
int
)
{
return
C
.
ca
,
len
(
C
.
ca
),
cap
(
C
.
ca
)
}
// GetCgoUnsignedCharArray returns an unsigned char array via cgo and the
// array's len and cap. This is only used for tests.
func
GetCgoUnsignedCharArray
()
(
interface
{},
int
,
int
)
{
return
C
.
uca
,
len
(
C
.
uca
),
cap
(
C
.
uca
)
}
// GetCgoSignedCharArray returns a signed char array via cgo and the array's len
// and cap. This is only used for tests.
func
GetCgoSignedCharArray
()
(
interface
{},
int
,
int
)
{
return
C
.
sca
,
len
(
C
.
sca
),
cap
(
C
.
sca
)
}
// GetCgoUint8tArray returns a uint8_t array via cgo and the array's len and
// cap. This is only used for tests.
func
GetCgoUint8tArray
()
(
interface
{},
int
,
int
)
{
return
C
.
ui8ta
,
len
(
C
.
ui8ta
),
cap
(
C
.
ui8ta
)
}
// GetCgoTypdefedUnsignedCharArray returns a typedefed unsigned char array via
// cgo and the array's len and cap. This is only used for tests.
func
GetCgoTypdefedUnsignedCharArray
()
(
interface
{},
int
,
int
)
{
return
C
.
tuca
,
len
(
C
.
tuca
),
cap
(
C
.
tuca
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment