You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

156 lines
3.1 KiB

преди 10 години
преди 10 години
преди 11 години
преди 11 години
преди 10 години
преди 10 години
преди 10 години
преди 10 години
преди 13 години
преди 10 години
  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. ).