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.

164 lines
3.3 KiB

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