Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

156 wiersze
3.1 KiB

  1. % This file is part of Jiffy released under the MIT license.
  2. % See the LICENSE file for more information.
  3. -module(jiffy_11_proper_tests).
  4. -include_lib("triq/include/triq.hrl").
  5. -include_lib("eunit/include/eunit.hrl").
  6. -include("jiffy_util.hrl").
  7. run(Name) ->
  8. {msg("~s", [Name]), [
  9. {timeout, 300, ?_assert(triq:check(?MODULE:Name(), 10))}
  10. ]}.
  11. proper_encode_decode_test_() ->
  12. [
  13. run(prop_enc_dec),
  14. run(prop_enc_dec_pretty),
  15. run(prop_enc_no_crash),
  16. run(prop_dec_no_crash_bin),
  17. run(prop_dec_no_crash_any)
  18. ].
  19. prop_enc_dec() ->
  20. ?FORALL(Data, json(),
  21. begin
  22. %io:format(standard_error, "Data: ~p~n", [Data]),
  23. Data == jiffy:decode(jiffy:encode(Data))
  24. end
  25. ).
  26. -ifndef(JIFFY_NO_MAPS).
  27. to_map_ejson({Props}) ->
  28. NewProps = [{K, to_map_ejson(V)} || {K, V} <- Props],
  29. maps:from_list(NewProps);
  30. to_map_ejson(Vals) when is_list(Vals) ->
  31. [to_map_ejson(V) || V <- Vals];
  32. to_map_ejson(Val) ->
  33. Val.
  34. prop_map_enc_dec() ->
  35. ?FORALL(Data, json(),
  36. begin
  37. MapData = to_map_ejson(Data),
  38. MapData == jiffy:decode(jiffy:encode(MapData), [return_maps])
  39. end
  40. ).
  41. -endif.
  42. prop_enc_dec_pretty() ->
  43. ?FORALL(Data, json(),
  44. begin
  45. Data == jiffy:decode(jiffy:encode(Data, [pretty]))
  46. end
  47. ).
  48. prop_enc_no_crash() ->
  49. ?FORALL(Data, any(), begin catch jiffy:encode(Data), true end).
  50. prop_dec_no_crash_bin() ->
  51. ?FORALL(Data, binary(), begin catch jiffy:decode(Data), true end).
  52. prop_dec_no_crash_any() ->
  53. ?FORALL(Data, any(), begin catch jiffy:decode(Data), true end).
  54. % JSON Generation
  55. json_null() ->
  56. null.
  57. json_boolean() ->
  58. oneof([true, false]).
  59. json_number() ->
  60. oneof([int(), real()]).
  61. json_string() ->
  62. escaped_utf8_bin().
  63. json_list(S) when S =< 0 ->
  64. [];
  65. json_list(S) ->
  66. ?LETSHRINK(
  67. [ListSize],
  68. [int(0, S)],
  69. vector(ListSize, json_text(S - ListSize))
  70. ).
  71. json_object(S) when S =< 0 ->
  72. {[]};
  73. json_object(S) ->
  74. ?LETSHRINK(
  75. [ObjectSize],
  76. [int(0, S)],
  77. {vector(ObjectSize, {json_string(), json_text(S - ObjectSize)})}
  78. ).
  79. json_value() ->
  80. oneof([
  81. json_null(),
  82. json_boolean(),
  83. json_string(),
  84. json_number()
  85. ]).
  86. json_text(S) when S > 0 ->
  87. ?DELAY(oneof([
  88. json_list(S),
  89. json_object(S)
  90. ]));
  91. json_text(_) ->
  92. json_value().
  93. json() ->
  94. ?SIZED(S, json_text(S)).
  95. %% XXX: Add generators
  96. %
  97. % We should add generators that generate JSON binaries directly
  98. % so we can test things that aren't produced by the encoder.
  99. %
  100. % We should also have a version of the JSON generator that inserts
  101. % errors into the JSON that we can test for.
  102. escaped_utf8_bin() ->
  103. ?SUCHTHAT(Bin,
  104. ?LET(S, ?SUCHTHAT(L, list(escaped_char()), L /= []),
  105. unicode:characters_to_binary(S, unicode, utf8)),
  106. is_binary(Bin)
  107. ).
  108. escaped_char() ->
  109. ?LET(C, unicode_char(),
  110. case C of
  111. $" -> "\\\"";
  112. C when C == 65534 -> 65533;
  113. C when C == 65535 -> 65533;
  114. C when C > 1114111 -> 1114111;
  115. C -> C
  116. end
  117. ).