summaryrefslogtreecommitdiff
path: root/spew
diff options
context:
space:
mode:
Diffstat (limited to 'spew')
-rw-r--r--spew/internal_test.go76
1 files changed, 76 insertions, 0 deletions
diff --git a/spew/internal_test.go b/spew/internal_test.go
index 7a872e4..05bab97 100644
--- a/spew/internal_test.go
+++ b/spew/internal_test.go
@@ -26,6 +26,7 @@ import (
"bytes"
"reflect"
"testing"
+ "unsafe"
)
// dummyFmtState implements a fake fmt.State to use for testing invalid
@@ -79,3 +80,78 @@ func TestInvalidReflectValue(t *testing.T) {
t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want)
}
}
+
+// flagRO, flagKindShift and flagKindWidth indicate various bit flags that the
+// reflect package uses internally to track kind and state information.
+const flagRO = 1 << 0
+const flagKindShift = 4
+const flagKindWidth = 5
+
+// 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)) +
+ unsafe.Offsetof(reflectValue.flag)))
+ *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)
+ }
+}