internalunsafe_test.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright (c) 2013-2016 Dave Collins <dave@davec.name>
  2. // Permission to use, copy, modify, and distribute this software for any
  3. // purpose with or without fee is hereby granted, provided that the above
  4. // copyright notice and this permission notice appear in all copies.
  5. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  6. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  7. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  8. // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  9. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  10. // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  11. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  12. // NOTE: Due to the following build constraints, this file will only be compiled
  13. // when the code is not running on Google App Engine, compiled by GopherJS, and
  14. // "-tags safe" is not added to the go build command line. The "disableunsafe"
  15. // tag is deprecated and thus should not be used.
  16. // +build !js,!appengine,!safe,!disableunsafe
  17. /*
  18. This test file is part of the spew package rather than than the spew_test
  19. package because it needs access to internals to properly test certain cases
  20. which are not possible via the public interface since they should never happen.
  21. */
  22. package spew
  23. import (
  24. "bytes"
  25. "reflect"
  26. "testing"
  27. "unsafe"
  28. )
  29. // changeKind uses unsafe to intentionally change the kind of a reflect.Value to
  30. // the maximum kind value which does not exist. This is needed to test the
  31. // fallback code which punts to the standard fmt library for new types that
  32. // might get added to the language.
  33. func changeKind(v *reflect.Value, readOnly bool) {
  34. rvf := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + offsetFlag))
  35. *rvf = *rvf | ((1<<flagKindWidth - 1) << flagKindShift)
  36. if readOnly {
  37. *rvf |= flagRO
  38. } else {
  39. *rvf &= ^uintptr(flagRO)
  40. }
  41. }
  42. // TestAddedReflectValue tests functionaly of the dump and formatter code which
  43. // falls back to the standard fmt library for new types that might get added to
  44. // the language.
  45. func TestAddedReflectValue(t *testing.T) {
  46. i := 1
  47. // Dump using a reflect.Value that is exported.
  48. v := reflect.ValueOf(int8(5))
  49. changeKind(&v, false)
  50. buf := new(bytes.Buffer)
  51. d := dumpState{w: buf, cs: &Config}
  52. d.dump(v)
  53. s := buf.String()
  54. want := "(int8) 5"
  55. if s != want {
  56. t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
  57. }
  58. i++
  59. // Dump using a reflect.Value that is not exported.
  60. changeKind(&v, true)
  61. buf.Reset()
  62. d.dump(v)
  63. s = buf.String()
  64. want = "(int8) <int8 Value>"
  65. if s != want {
  66. t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want)
  67. }
  68. i++
  69. // Formatter using a reflect.Value that is exported.
  70. changeKind(&v, false)
  71. buf2 := new(dummyFmtState)
  72. f := formatState{value: v, cs: &Config, fs: buf2}
  73. f.format(v)
  74. s = buf2.String()
  75. want = "5"
  76. if s != want {
  77. t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
  78. }
  79. i++
  80. // Formatter using a reflect.Value that is not exported.
  81. changeKind(&v, true)
  82. buf2.Reset()
  83. f = formatState{value: v, cs: &Config, fs: buf2}
  84. f.format(v)
  85. s = buf2.String()
  86. want = "<int8 Value>"
  87. if s != want {
  88. t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want)
  89. }
  90. }