reflect_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package jsonpointer
  2. import (
  3. "reflect"
  4. "testing"
  5. )
  6. type address struct {
  7. Street string `json:"street"`
  8. Zip string
  9. }
  10. type person struct {
  11. Name string `json:"name,omitempty"`
  12. Twitter string
  13. Aliases []string `json:"aliases"`
  14. Addresses []*address `json:"addresses"`
  15. NameTildeContained string `json:"name~contained"`
  16. NameSlashContained string `json:"name/contained"`
  17. AnActualArray [4]int
  18. NestedMap map[string]float64 `json:"nestedmap"`
  19. MapIntKey map[int]string
  20. MapUintKey map[uint]string
  21. MapFloatKey map[float64]string
  22. }
  23. var input = &person{
  24. Name: "marty",
  25. Twitter: "mschoch",
  26. Aliases: []string{
  27. "jabroni",
  28. "beer",
  29. },
  30. Addresses: []*address{
  31. &address{
  32. Street: "123 Sesame St.",
  33. Zip: "99099",
  34. },
  35. },
  36. NameTildeContained: "yessir",
  37. NameSlashContained: "nosir",
  38. AnActualArray: [4]int{0, 1, 2, 3},
  39. NestedMap: map[string]float64{
  40. "pi": 3.14,
  41. "back/saidhe": 2.71,
  42. "till~duh": 1.41,
  43. },
  44. MapIntKey: map[int]string{
  45. 1: "one",
  46. 2: "two",
  47. },
  48. MapUintKey: map[uint]string{
  49. 3: "three",
  50. 4: "four",
  51. },
  52. MapFloatKey: map[float64]string{
  53. 3.14: "pi",
  54. 4.15: "notpi",
  55. },
  56. }
  57. func benchReflect(b *testing.B, path string) {
  58. for i := 0; i < b.N; i++ {
  59. if Reflect(input, path) == nil {
  60. b.FailNow()
  61. }
  62. }
  63. }
  64. func BenchmarkReflectRoot(b *testing.B) {
  65. benchReflect(b, "")
  66. }
  67. func BenchmarkReflectToplevelExact(b *testing.B) {
  68. benchReflect(b, "/Twitter")
  69. }
  70. func BenchmarkReflectToplevelTagged(b *testing.B) {
  71. benchReflect(b, "/Name")
  72. }
  73. func BenchmarkReflectToplevelTaggedLower(b *testing.B) {
  74. benchReflect(b, "/name")
  75. }
  76. func BenchmarkReflectDeep(b *testing.B) {
  77. benchReflect(b, "/addresses/0/Zip")
  78. }
  79. func BenchmarkReflectSlash(b *testing.B) {
  80. benchReflect(b, "/name~1contained")
  81. }
  82. func BenchmarkReflectTilde(b *testing.B) {
  83. benchReflect(b, "/name~0contained")
  84. }
  85. func compareStringArrayIgnoringOrder(a, b []string) bool {
  86. if len(a) != len(b) {
  87. return false
  88. }
  89. tmp := make(map[string]bool, len(a))
  90. for _, av := range a {
  91. tmp[av] = true
  92. }
  93. for _, bv := range b {
  94. if tmp[bv] != true {
  95. return false
  96. }
  97. }
  98. return true
  99. }
  100. func TestReflectListPointers(t *testing.T) {
  101. pointers, err := ReflectListPointers(input)
  102. if err != nil {
  103. t.Fatal(err)
  104. }
  105. expect := []string{"", "/name", "/Twitter", "/aliases",
  106. "/aliases/0", "/aliases/1", "/addresses", "/addresses/0",
  107. "/addresses/0/street", "/addresses/0/Zip",
  108. "/name~0contained", "/name~1contained", "/AnActualArray",
  109. "/AnActualArray/0", "/AnActualArray/1", "/AnActualArray/2",
  110. "/AnActualArray/3", "/nestedmap", "/nestedmap/pi",
  111. "/nestedmap/back~1saidhe", "/nestedmap/till~0duh",
  112. "/MapIntKey", "/MapIntKey/1", "/MapIntKey/2", "/MapUintKey",
  113. "/MapUintKey/3", "/MapUintKey/4", "/MapFloatKey",
  114. "/MapFloatKey/3.14", "/MapFloatKey/4.15"}
  115. if !compareStringArrayIgnoringOrder(expect, pointers) {
  116. t.Fatalf("expected %#v, got %#v", expect, pointers)
  117. }
  118. }
  119. func TestReflectNonObjectOrSlice(t *testing.T) {
  120. got := Reflect(36, "/test")
  121. if got != nil {
  122. t.Errorf("expected nil, got %#v", got)
  123. }
  124. }
  125. type structThatCanBeUsedAsKey struct {
  126. name string
  127. domain string
  128. }
  129. func TestReflectMapThatWontWork(t *testing.T) {
  130. amapthatwontwork := map[structThatCanBeUsedAsKey]string{}
  131. akey := structThatCanBeUsedAsKey{name: "marty", domain: "couchbase"}
  132. amapthatwontwork[akey] = "verycontrived"
  133. got := Reflect(amapthatwontwork, "/anykey")
  134. if got != nil {
  135. t.Errorf("expected nil, got %#v", got)
  136. }
  137. }
  138. func TestReflect(t *testing.T) {
  139. tests := []struct {
  140. path string
  141. exp interface{}
  142. }{
  143. {
  144. path: "",
  145. exp: input,
  146. },
  147. {
  148. path: "/", exp: nil,
  149. },
  150. {
  151. path: "/name",
  152. exp: "marty",
  153. },
  154. {
  155. path: "/Name",
  156. exp: "marty",
  157. },
  158. {
  159. path: "/Twitter",
  160. exp: "mschoch",
  161. },
  162. {
  163. path: "/aliases/0",
  164. exp: "jabroni",
  165. },
  166. {
  167. path: "/Aliases/0",
  168. exp: "jabroni",
  169. },
  170. {
  171. path: "/addresses/0/street",
  172. exp: "123 Sesame St.",
  173. },
  174. {
  175. path: "/addresses/4/street",
  176. exp: nil,
  177. },
  178. {
  179. path: "/doesntexist",
  180. exp: nil,
  181. },
  182. {
  183. path: "/does/not/exit",
  184. exp: nil,
  185. },
  186. {
  187. path: "/doesntexist/7",
  188. exp: nil,
  189. },
  190. {
  191. path: "/name~0contained",
  192. exp: "yessir",
  193. },
  194. {
  195. path: "/name~1contained",
  196. exp: "nosir",
  197. },
  198. {
  199. path: "/AnActualArray/2",
  200. exp: 2,
  201. },
  202. {
  203. path: "/AnActualArray/5",
  204. exp: nil,
  205. },
  206. {
  207. path: "/nestedmap/pi",
  208. exp: 3.14,
  209. },
  210. {
  211. path: "/nestedmap/back~1saidhe",
  212. exp: 2.71,
  213. },
  214. {
  215. path: "/nestedmap/till~0duh",
  216. exp: 1.41,
  217. },
  218. {
  219. path: "/MapIntKey/1",
  220. exp: "one",
  221. },
  222. {
  223. path: "/MapUintKey/3",
  224. exp: "three",
  225. },
  226. {
  227. path: "/MapFloatKey/3.14",
  228. exp: "pi",
  229. },
  230. {
  231. path: "/MapFloatKey/4.0",
  232. exp: nil,
  233. },
  234. }
  235. for _, test := range tests {
  236. output := Reflect(input, test.path)
  237. if !reflect.DeepEqual(output, test.exp) {
  238. t.Errorf("Expected %#v for %q, got %#v", test.exp, test.path, output)
  239. }
  240. }
  241. }