jsone_encode_tests.erl 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. %% Copyright (c) 2013-2014, Takeru Ohta <phjgt308@gmail.com>
  2. %% coding: latin-1
  3. -module(jsone_encode_tests).
  4. -include_lib("eunit/include/eunit.hrl").
  5. -ifdef('NO_MAP_TYPE').
  6. -define(OBJ0, {[]}).
  7. -define(OBJ1(K, V), {[{K, V}]}).
  8. -define(OBJ2(K1, V1, K2, V2), {[{K1, V1}, {K2, V2}]}).
  9. -else.
  10. -define(OBJ0, #{}).
  11. -define(OBJ1(K, V), #{K => V}).
  12. -define(OBJ2(K1, V1, K2, V2), #{K1 => V1, K2 => V2}).
  13. -endif.
  14. encode_test_() ->
  15. [
  16. %% Symbols
  17. {"false",
  18. fun () ->
  19. ?assertEqual({ok, <<"false">>}, jsone_encode:encode(false))
  20. end},
  21. {"true",
  22. fun () ->
  23. ?assertEqual({ok, <<"true">>}, jsone_encode:encode(true))
  24. end},
  25. {"null",
  26. fun () ->
  27. ?assertEqual({ok, <<"null">>}, jsone_encode:encode(null))
  28. end},
  29. %% Numbers: Integer
  30. {"zero",
  31. fun () ->
  32. ?assertEqual({ok, <<"0">>}, jsone_encode:encode(0))
  33. end},
  34. {"positive integer",
  35. fun () ->
  36. ?assertEqual({ok, <<"1">>}, jsone_encode:encode(1))
  37. end},
  38. {"negative integer",
  39. fun () ->
  40. ?assertEqual({ok, <<"-1">>}, jsone_encode:encode(-1))
  41. end},
  42. {"large number",
  43. fun () ->
  44. ?assertEqual({ok, <<"11111111111111111111111111111111111111111111111111111111111111111111111">>},
  45. jsone_encode:encode(11111111111111111111111111111111111111111111111111111111111111111111111))
  46. end},
  47. %% Numbers: Float",
  48. {"float",
  49. fun () ->
  50. Input = 1.234,
  51. ?assertMatch({ok, _}, jsone_encode:encode(Input)),
  52. ?assertEqual(Input, binary_to_float(element(2, jsone_encode:encode(Input))))
  53. end},
  54. {"float_format option",
  55. fun () ->
  56. Input = 1.23,
  57. ?assertEqual({ok, <<"1.22999999999999998224e+00">>}, jsone_encode:encode(Input)),
  58. ?assertEqual({ok, <<"1.2300e+00">>}, jsone_encode:encode(Input, [{float_format, [{scientific, 4}]}])),
  59. ?assertEqual({ok, <<"1.2e+00">>}, jsone_encode:encode(Input, [{float_format, [{scientific, 1}]}])),
  60. ?assertEqual({ok, <<"1.2300">>}, jsone_encode:encode(Input, [{float_format, [{decimals, 4}]}])),
  61. ?assertEqual({ok, <<"1.23">>}, jsone_encode:encode(Input, [{float_format, [{decimals, 4}, compact]}]))
  62. end},
  63. %% Strings
  64. {"simple string",
  65. fun () ->
  66. ?assertEqual({ok, <<"\"abc\"">>}, jsone_encode:encode(<<"abc">>))
  67. end},
  68. {"atom is regarded as string",
  69. fun () ->
  70. ?assertEqual({ok, <<"\"abc\"">>}, jsone_encode:encode(abc))
  71. end},
  72. {"string: contains escaped characters",
  73. fun () ->
  74. Input = <<"\"\/\\\b\f\n\r\t">>,
  75. Expected = list_to_binary([$", [[$\\, C] || C <- [$", $/, $\\, $b, $f, $n, $r, $t]], $"]),
  76. ?assertEqual({ok, Expected}, jsone_encode:encode(Input)),
  77. ?assertEqual({ok, Expected}, jsone_encode:encode(Input, [native_utf8]))
  78. end},
  79. {"string: contains control characters",
  80. fun () ->
  81. Ctrls = lists:seq(16#00, 16#1F) -- [$\b, $\f, $\n, $\r, $\t],
  82. Input = list_to_binary(Ctrls),
  83. Expected = list_to_binary([$", [io_lib:format("\\u00~2.16.0b", [C]) || C <- Ctrls], $"]),
  84. ?assertEqual({ok, Expected}, jsone_encode:encode(Input)),
  85. ?assertEqual({ok, Expected}, jsone_encode:encode(Input, [native_utf8]))
  86. end},
  87. {"string: contains multi-byte (UTF-8 encoded) characters",
  88. fun () ->
  89. %% japanese
  90. Input1 = <<"あいうえお">>, % assumed that the encoding of this file is UTF-8
  91. Expected1 = <<"\"\\u3042\\u3044\\u3046\\u3048\\u304a\"">>,
  92. ?assertEqual({ok, Expected1}, jsone_encode:encode(Input1)),
  93. Expected12 = <<$", Input1/binary, $">>,
  94. ?assertEqual({ok, Expected12}, jsone_encode:encode(Input1, [native_utf8])),
  95. %% other multi-byte characters
  96. Input2 = <<"۝۞ႮႯ">>,
  97. Expected2 = <<"\"\\u06dd\\u06de\\u10ae\\u10af\"">>,
  98. ?assertEqual({ok, Expected2}, jsone_encode:encode(Input2)),
  99. Expected22 = <<$", Input2/binary, $">>,
  100. ?assertEqual({ok, Expected22}, jsone_encode:encode(Input2, [native_utf8]))
  101. end},
  102. {"string: containts surrogate pairs",
  103. fun () ->
  104. Input = <<"𢁉𢂚𢃼">>,
  105. Expected = <<"\"\\ud848\\udc49\\ud848\\udc9a\\ud848\\udcfc\"">>,
  106. ?assertEqual({ok, Expected}, jsone_encode:encode(Input))
  107. end},
  108. %% Strings variant: Datetimes
  109. {"datetime: iso8601: utc",
  110. fun () ->
  111. ?assertEqual({ok, <<"\"2015-06-25T14:57:25Z\"">>}, jsone_encode:encode({{2015,6,25},{14,57,25}})),
  112. ?assertEqual({ok, <<"\"2015-06-25T14:57:25Z\"">>}, jsone_encode:encode({{2015,6,25},{14,57,25}}, [{datetime_format, iso8601}])),
  113. ?assertEqual({ok, <<"\"2015-06-25T14:57:25Z\"">>}, jsone_encode:encode({{2015,6,25},{14,57,25}}, [{datetime_format, {iso8601, utc}}]))
  114. end},
  115. {"datetime: iso8601: local",
  116. fun () ->
  117. ?assertMatch({ok, <<"\"2015-06-25T14:57:25",_:6/binary,"\"">>}, jsone_encode:encode({{2015,6,25},{14,57,25}}, [{datetime_format, {iso8601, local}}]))
  118. end},
  119. {"datetime: iso8601: timezone",
  120. fun () ->
  121. ?assertEqual({ok, <<"\"2015-06-25T14:57:25Z\"">>}, jsone_encode:encode({{2015,6,25},{14,57,25}}, [{datetime_format, {iso8601, 0}}])),
  122. ?assertEqual({ok, <<"\"2015-06-25T14:57:25+00:01\"">>}, jsone_encode:encode({{2015,6,25},{14,57,25}}, [{datetime_format, {iso8601, 60}}])),
  123. ?assertEqual({ok, <<"\"2015-06-25T14:57:25-00:01\"">>}, jsone_encode:encode({{2015,6,25},{14,57,25}}, [{datetime_format, {iso8601, -60}}]))
  124. end},
  125. %% Arrays
  126. {"simple array",
  127. fun () ->
  128. Input = [1, 2, 3],
  129. Expected = <<"[1,2,3]">>,
  130. ?assertEqual({ok, Expected}, jsone_encode:encode(Input))
  131. end},
  132. {"empty array",
  133. fun () ->
  134. Input = [],
  135. Expected = <<"[]">>,
  136. ?assertEqual({ok, Expected}, jsone_encode:encode(Input))
  137. end},
  138. %% Objects
  139. {"simple object",
  140. fun () ->
  141. Input1 = {[{<<"key">>, <<"value">>}, {<<"1">>, 2}]},
  142. Input2 = [{<<"key">>, <<"value">>}, {<<"1">>, 2}],
  143. Expected = <<"{\"key\":\"value\",\"1\":2}">>,
  144. ?assertEqual({ok, Expected}, jsone_encode:encode(Input1)),
  145. ?assertEqual({ok, Expected}, jsone_encode:encode(Input2))
  146. end},
  147. {"empty object",
  148. fun () ->
  149. Input1 = {[]},
  150. Input2 = [{}],
  151. Expected = <<"{}">>,
  152. ?assertEqual({ok, Expected}, jsone_encode:encode(Input1)),
  153. ?assertEqual({ok, Expected}, jsone_encode:encode(Input2))
  154. end},
  155. {"simple object: map",
  156. fun () ->
  157. Input = ?OBJ2(<<"1">>, 2, <<"key">>, <<"value">>),
  158. Expected = <<"{\"1\":2,\"key\":\"value\"}">>,
  159. ?assertEqual({ok, Expected}, jsone_encode:encode(Input))
  160. end},
  161. {"empty object: map",
  162. fun () ->
  163. Input = ?OBJ0,
  164. Expected = <<"{}">>,
  165. ?assertEqual({ok, Expected}, jsone_encode:encode(Input))
  166. end},
  167. {"atom key is allowed",
  168. fun () ->
  169. Expected = <<"{\"key\":2}">>,
  170. ?assertEqual({ok, Expected}, jsone_encode:encode({[{key, 2}]}))
  171. end},
  172. {"object_key_type option",
  173. fun () ->
  174. %% key: atom
  175. ?assertEqual({ok, <<"{\"a\":2}">>}, jsone_encode:encode(?OBJ1(a, 2), [{object_key_type, string}])), % OK
  176. ?assertEqual({ok, <<"{\"a\":2}">>}, jsone_encode:encode(?OBJ1(a, 2), [{object_key_type, scalar}])), % OK
  177. ?assertEqual({ok, <<"{\"a\":2}">>}, jsone_encode:encode(?OBJ1(a, 2), [{object_key_type, value}])), % OK
  178. %% key: number
  179. ?assertMatch({error, {badarg, _}}, jsone_encode:encode(?OBJ1(1, 2), [{object_key_type, string}])), % NG
  180. ?assertEqual({ok, <<"{\"1\":2}">>}, jsone_encode:encode(?OBJ1(1, 2), [{object_key_type, scalar}])), % OK
  181. ?assertEqual({ok, <<"{\"1\":2}">>}, jsone_encode:encode(?OBJ1(1, 2), [{object_key_type, value}])), % OK
  182. %% key: datetime
  183. ?assertMatch({error, {badarg, _}}, jsone_encode:encode(?OBJ1({{2000,1,1}, {0,0,0}}, 2), [{object_key_type, string}])), % NG
  184. ?assertEqual({ok, <<"{\"2000-01-01T00:00:00Z\":2}">>}, jsone_encode:encode(?OBJ1({{2000,1,1}, {0,0,0}}, 2), [{object_key_type, scalar}])), % OK
  185. ?assertEqual({ok, <<"{\"2000-01-01T00:00:00Z\":2}">>}, jsone_encode:encode(?OBJ1({{2000,1,1}, {0,0,0}}, 2), [{object_key_type, value}])), % OK
  186. %% key: array
  187. ?assertMatch({error, {badarg, _}}, jsone_encode:encode(?OBJ1([1], 2), [{object_key_type, string}])), % NG
  188. ?assertMatch({error, {badarg, _}}, jsone_encode:encode(?OBJ1([1], 2), [{object_key_type, scalar}])), % NG
  189. ?assertEqual({ok, <<"{\"[1]\":2}">>}, jsone_encode:encode(?OBJ1([1], 2), [{object_key_type, value}])), % OK
  190. %% key: object
  191. ?assertMatch({error, {badarg, _}}, jsone_encode:encode(?OBJ1(?OBJ0, 2), [{object_key_type, string}])), % NG
  192. ?assertMatch({error, {badarg, _}}, jsone_encode:encode(?OBJ1(?OBJ0, 2), [{object_key_type, scalar}])), % NG
  193. ?assertEqual({ok, <<"{\"{}\":2}">>}, jsone_encode:encode(?OBJ1(?OBJ0, 2), [{object_key_type, value}])) % OK
  194. end},
  195. {"non binary object member key is disallowed",
  196. fun () ->
  197. ?assertMatch({error, {badarg, _}}, jsone_encode:encode({[{1, 2}]})),
  198. ?assertMatch({error, {badarg, _}}, jsone_encode:encode({[{"1", 2}]}))
  199. end},
  200. %% Pretty Print
  201. {"space",
  202. fun () ->
  203. ?assertEqual({ok, <<"[1, 2, 3]">>}, jsone_encode:encode([1,2,3], [{space, 1}])),
  204. ?assertEqual({ok, <<"[1, 2, 3]">>}, jsone_encode:encode([1,2,3], [{space, 2}])),
  205. ?assertEqual({ok, <<"{\"a\": 1, \"b\": 2}">>}, jsone_encode:encode(?OBJ2(a, 1, b, 2), [{space, 1}])),
  206. ?assertEqual({ok, <<"{\"a\": 1, \"b\": 2}">>}, jsone_encode:encode(?OBJ2(a, 1, b, 2), [{space, 2}]))
  207. end},
  208. {"indent",
  209. fun () ->
  210. ?assertEqual({ok, <<"[\n 1,\n 2,\n 3\n]">>}, jsone_encode:encode([1,2,3], [{indent, 1}])),
  211. ?assertEqual({ok, <<"[\n 1,\n 2,\n 3\n]">>}, jsone_encode:encode([1,2,3], [{indent, 2}])),
  212. ?assertEqual({ok, <<"{\n \"a\":1,\n \"b\":2\n}">>}, jsone_encode:encode(?OBJ2(a, 1, b, 2), [{indent, 1}])),
  213. ?assertEqual({ok, <<"{\n \"a\":1,\n \"b\":2\n}">>}, jsone_encode:encode(?OBJ2(a, 1, b, 2), [{indent, 2}]))
  214. end},
  215. {"indent+space",
  216. fun () ->
  217. ?assertEqual({ok, <<"[\n 1,\n 2,\n 3\n]">>}, jsone_encode:encode([1,2,3], [{indent, 1}, {space, 1}])),
  218. ?assertEqual({ok, <<"[\n 1,\n 2,\n 3\n]">>}, jsone_encode:encode([1,2,3], [{indent, 2}, {space, 2}])),
  219. ?assertEqual({ok, <<"{\n \"a\": 1,\n \"b\": 2\n}">>}, jsone_encode:encode(?OBJ2(a, 1, b, 2), [{indent, 1}, {space, 1}])),
  220. ?assertEqual({ok, <<"{\n \"a\": 1,\n \"b\": 2\n}">>}, jsone_encode:encode(?OBJ2(a, 1, b, 2), [{indent, 2}, {space, 2}]))
  221. end},
  222. %% Others
  223. {"compound data",
  224. fun () ->
  225. Input = [true, {[{<<"1">>, 2}, {<<"array">>, [[[[1]]], {[{<<"ab">>, <<"cd">>}]}, false]}]}, null],
  226. Expected = <<"[true,{\"1\":2,\"array\":[[[[1]]],{\"ab\":\"cd\"},false]},null]">>,
  227. ?assertEqual({ok, Expected}, jsone_encode:encode(Input)),
  228. PpExpected = <<"[\n true,\n {\n \"1\": 2,\n \"array\": [\n [\n [\n [\n 1\n ]\n ]\n ],\n {\n \"ab\": \"cd\"\n },\n false\n ]\n },\n null\n]">>,
  229. ?assertEqual({ok, PpExpected}, jsone_encode:encode(Input, [{indent, 1}, {space, 1}]))
  230. end},
  231. {"invalid value",
  232. fun () ->
  233. ?assertMatch({error, {badarg, _}}, jsone_encode:encode(self()))
  234. end},
  235. {"wrong option",
  236. fun () ->
  237. ?assertError(badarg, jsone_encode:encode(1, [{no_such_option, hoge}]))
  238. end}
  239. ].