json_test.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. /*
  2. Copyright 2015 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package json
  14. import (
  15. "fmt"
  16. "math"
  17. "reflect"
  18. "strconv"
  19. "strings"
  20. "testing"
  21. )
  22. func TestEvaluateTypes(t *testing.T) {
  23. testCases := []struct {
  24. In string
  25. Data interface{}
  26. Out string
  27. Err bool
  28. }{
  29. // Invalid syntaxes
  30. {
  31. In: `x`,
  32. Err: true,
  33. },
  34. {
  35. In: ``,
  36. Err: true,
  37. },
  38. // Null
  39. {
  40. In: `null`,
  41. Data: nil,
  42. Out: `null`,
  43. },
  44. // Booleans
  45. {
  46. In: `true`,
  47. Data: true,
  48. Out: `true`,
  49. },
  50. {
  51. In: `false`,
  52. Data: false,
  53. Out: `false`,
  54. },
  55. // Integers
  56. {
  57. In: `0`,
  58. Data: int64(0),
  59. Out: `0`,
  60. },
  61. {
  62. In: `-0`,
  63. Data: int64(-0),
  64. Out: `0`,
  65. },
  66. {
  67. In: `1`,
  68. Data: int64(1),
  69. Out: `1`,
  70. },
  71. {
  72. In: `2147483647`,
  73. Data: int64(math.MaxInt32),
  74. Out: `2147483647`,
  75. },
  76. {
  77. In: `-2147483648`,
  78. Data: int64(math.MinInt32),
  79. Out: `-2147483648`,
  80. },
  81. {
  82. In: `9223372036854775807`,
  83. Data: int64(math.MaxInt64),
  84. Out: `9223372036854775807`,
  85. },
  86. {
  87. In: `-9223372036854775808`,
  88. Data: int64(math.MinInt64),
  89. Out: `-9223372036854775808`,
  90. },
  91. // Int overflow
  92. {
  93. In: `9223372036854775808`, // MaxInt64 + 1
  94. Data: float64(9223372036854775808),
  95. Out: strconv.FormatFloat(9223372036854775808, 'g', -1, 64),
  96. },
  97. {
  98. In: `-9223372036854775809`, // MinInt64 - 1
  99. Data: float64(math.MinInt64),
  100. Out: strconv.FormatFloat(-9223372036854775809, 'g', -1, 64),
  101. },
  102. // Floats
  103. {
  104. In: `0.0`,
  105. Data: float64(0),
  106. Out: `0`,
  107. },
  108. {
  109. In: `-0.0`,
  110. Data: float64(-0.0),
  111. Out: `-0`,
  112. },
  113. {
  114. In: `0.5`,
  115. Data: float64(0.5),
  116. Out: `0.5`,
  117. },
  118. {
  119. In: `1e3`,
  120. Data: float64(1e3),
  121. Out: `1000`,
  122. },
  123. {
  124. In: `1.5`,
  125. Data: float64(1.5),
  126. Out: `1.5`,
  127. },
  128. {
  129. In: `-0.3`,
  130. Data: float64(-.3),
  131. Out: `-0.3`,
  132. },
  133. {
  134. // Largest representable float32
  135. In: `3.40282346638528859811704183484516925440e+38`,
  136. Data: float64(math.MaxFloat32),
  137. Out: strconv.FormatFloat(math.MaxFloat32, 'g', -1, 64),
  138. },
  139. {
  140. // Smallest float32 without losing precision
  141. In: `1.175494351e-38`,
  142. Data: float64(1.175494351e-38),
  143. Out: `1.175494351e-38`,
  144. },
  145. {
  146. // float32 closest to zero
  147. In: `1.401298464324817070923729583289916131280e-45`,
  148. Data: float64(math.SmallestNonzeroFloat32),
  149. Out: strconv.FormatFloat(math.SmallestNonzeroFloat32, 'g', -1, 64),
  150. },
  151. {
  152. // Largest representable float64
  153. In: `1.797693134862315708145274237317043567981e+308`,
  154. Data: float64(math.MaxFloat64),
  155. Out: strconv.FormatFloat(math.MaxFloat64, 'g', -1, 64),
  156. },
  157. {
  158. // Closest to zero without losing precision
  159. In: `2.2250738585072014e-308`,
  160. Data: float64(2.2250738585072014e-308),
  161. Out: `2.2250738585072014e-308`,
  162. },
  163. {
  164. // float64 closest to zero
  165. In: `4.940656458412465441765687928682213723651e-324`,
  166. Data: float64(math.SmallestNonzeroFloat64),
  167. Out: strconv.FormatFloat(math.SmallestNonzeroFloat64, 'g', -1, 64),
  168. },
  169. {
  170. // math.MaxFloat64 + 2 overflow
  171. In: `1.7976931348623159e+308`,
  172. Err: true,
  173. },
  174. // Strings
  175. {
  176. In: `""`,
  177. Data: string(""),
  178. Out: `""`,
  179. },
  180. {
  181. In: `"0"`,
  182. Data: string("0"),
  183. Out: `"0"`,
  184. },
  185. {
  186. In: `"A"`,
  187. Data: string("A"),
  188. Out: `"A"`,
  189. },
  190. {
  191. In: `"Iñtërnâtiônàlizætiøn"`,
  192. Data: string("Iñtërnâtiônàlizætiøn"),
  193. Out: `"Iñtërnâtiônàlizætiøn"`,
  194. },
  195. // Arrays
  196. {
  197. In: `[]`,
  198. Data: []interface{}{},
  199. Out: `[]`,
  200. },
  201. {
  202. In: `[` + strings.Join([]string{
  203. `null`,
  204. `true`,
  205. `false`,
  206. `0`,
  207. `9223372036854775807`,
  208. `0.0`,
  209. `0.5`,
  210. `1.0`,
  211. `1.797693134862315708145274237317043567981e+308`,
  212. `"0"`,
  213. `"A"`,
  214. `"Iñtërnâtiônàlizætiøn"`,
  215. `[null,true,1,1.0,1.5]`,
  216. `{"boolkey":true,"floatkey":1.0,"intkey":1,"nullkey":null}`,
  217. }, ",") + `]`,
  218. Data: []interface{}{
  219. nil,
  220. true,
  221. false,
  222. int64(0),
  223. int64(math.MaxInt64),
  224. float64(0.0),
  225. float64(0.5),
  226. float64(1.0),
  227. float64(math.MaxFloat64),
  228. string("0"),
  229. string("A"),
  230. string("Iñtërnâtiônàlizætiøn"),
  231. []interface{}{nil, true, int64(1), float64(1.0), float64(1.5)},
  232. map[string]interface{}{"nullkey": nil, "boolkey": true, "intkey": int64(1), "floatkey": float64(1.0)},
  233. },
  234. Out: `[` + strings.Join([]string{
  235. `null`,
  236. `true`,
  237. `false`,
  238. `0`,
  239. `9223372036854775807`,
  240. `0`,
  241. `0.5`,
  242. `1`,
  243. strconv.FormatFloat(math.MaxFloat64, 'g', -1, 64),
  244. `"0"`,
  245. `"A"`,
  246. `"Iñtërnâtiônàlizætiøn"`,
  247. `[null,true,1,1,1.5]`,
  248. `{"boolkey":true,"floatkey":1,"intkey":1,"nullkey":null}`, // gets alphabetized by Marshal
  249. }, ",") + `]`,
  250. },
  251. // Maps
  252. {
  253. In: `{}`,
  254. Data: map[string]interface{}{},
  255. Out: `{}`,
  256. },
  257. {
  258. In: `{"boolkey":true,"floatkey":1.0,"intkey":1,"nullkey":null}`,
  259. Data: map[string]interface{}{"nullkey": nil, "boolkey": true, "intkey": int64(1), "floatkey": float64(1.0)},
  260. Out: `{"boolkey":true,"floatkey":1,"intkey":1,"nullkey":null}`, // gets alphabetized by Marshal
  261. },
  262. }
  263. for _, tc := range testCases {
  264. inputJSON := fmt.Sprintf(`{"data":%s}`, tc.In)
  265. expectedJSON := fmt.Sprintf(`{"data":%s}`, tc.Out)
  266. m := map[string]interface{}{}
  267. err := Unmarshal([]byte(inputJSON), &m)
  268. if tc.Err && err != nil {
  269. // Expected error
  270. continue
  271. }
  272. if err != nil {
  273. t.Errorf("%s: error decoding: %v", tc.In, err)
  274. continue
  275. }
  276. if tc.Err {
  277. t.Errorf("%s: expected error, got none", tc.In)
  278. continue
  279. }
  280. data, ok := m["data"]
  281. if !ok {
  282. t.Errorf("%s: decoded object missing data key: %#v", tc.In, m)
  283. continue
  284. }
  285. if !reflect.DeepEqual(tc.Data, data) {
  286. t.Errorf("%s: expected\n\t%#v (%v), got\n\t%#v (%v)", tc.In, tc.Data, reflect.TypeOf(tc.Data), data, reflect.TypeOf(data))
  287. continue
  288. }
  289. outputJSON, err := Marshal(m)
  290. if err != nil {
  291. t.Errorf("%s: error encoding: %v", tc.In, err)
  292. continue
  293. }
  294. if expectedJSON != string(outputJSON) {
  295. t.Errorf("%s: expected\n\t%s, got\n\t%s", tc.In, expectedJSON, string(outputJSON))
  296. continue
  297. }
  298. }
  299. }