|
|
- % This file is part of Jiffy released under the MIT license.
- % See the LICENSE file for more information.
-
- -module(jiffy_11_property_tests).
-
- -ifdef(HAVE_EQC).
-
-
- -compile(export_all).
-
-
- -include_lib("eqc/include/eqc.hrl").
- -include_lib("eunit/include/eunit.hrl").
- -include("jiffy_util.hrl").
-
-
- property_test_() ->
- [
- run(prop_enc_dec),
- run(prop_enc_dec_pretty),
- run(prop_dec_trailer),
- run(prop_enc_no_crash),
- run(prop_dec_no_crash_bin),
- run(prop_dec_no_crash_any)
- ] ++ map_props().
-
-
- -ifndef(JIFFY_NO_MAPS).
- map_props() ->
- [
- run(prop_map_enc_dec)
- ].
- -else.
- map_props() ->
- [].
- -endif.
-
-
- prop_enc_dec() ->
- ?FORALL(Data, json(), begin
- Data == jiffy:decode(jiffy:encode(Data))
- end).
-
-
- prop_dec_trailer() ->
- ?FORALL({T1, Comb, T2}, {json(), combiner(), json()},
- begin
- B1 = iolist_to_binary(jiffy:encode(T1)),
- B2 = iolist_to_binary(jiffy:encode(T2)),
- Bin = <<B1/binary, Comb/binary, B2/binary>>,
- {has_trailer, T1, Rest} = jiffy:decode(Bin, [return_trailer]),
- T2 = jiffy:decode(Rest),
- true
- end
- ).
-
-
- prop_enc_dec_pretty() ->
- ?FORALL(Data, json(),
- begin
- Data == jiffy:decode(jiffy:encode(Data, [pretty]))
- end
- ).
-
-
- -ifndef(JIFFY_NO_MAPS).
- prop_map_enc_dec() ->
- ?FORALL(Data, json(),
- begin
- MapData = to_map_ejson(Data),
- MapData == jiffy:decode(jiffy:encode(MapData), [return_maps])
- end
- ).
- -endif.
-
-
- prop_enc_no_crash() ->
- ?FORALL(Data, any(), begin catch jiffy:encode(Data), true end).
-
-
- prop_dec_no_crash_any() ->
- ?FORALL(Data, any(), begin catch jiffy:decode(Data), true end).
-
-
- prop_dec_no_crash_bin() ->
- ?FORALL(Data, binary(), begin catch jiffy:decode(Data), true end).
-
-
- opts() ->
- [
- {numtests, [1000]}
- ].
-
-
- apply_opts(Prop) ->
- apply_opts(Prop, opts()).
-
-
- apply_opts(Prop, []) ->
- Prop;
-
- apply_opts(Prop, [{Name, Args} | Rest]) ->
- NewProp = erlang:apply(eqc, Name, Args ++ [Prop]),
- apply_opts(NewProp, Rest).
-
-
- log(F, A) ->
- io:format(standard_error, F, A).
-
-
- run(Name) ->
- Prop = apply_opts(?MODULE:Name()),
- {msg("~s", [Name]), [
- {timeout, 300, ?_assert(eqc:quickcheck(Prop))}
- ]}.
-
-
- -ifndef(JIFFY_NO_MAPS).
- to_map_ejson({Props}) ->
- NewProps = [{K, to_map_ejson(V)} || {K, V} <- Props],
- maps:from_list(NewProps);
- to_map_ejson(Vals) when is_list(Vals) ->
- [to_map_ejson(V) || V <- Vals];
- to_map_ejson(Val) ->
- Val.
- -endif.
-
-
- % Random any term generation
-
- any() ->
- ?SIZED(Size, any(Size)).
-
-
- any(0) ->
- any_value();
-
- any(S) ->
- oneof(any_value_types() ++ [
- ?LAZY(any_list(S)),
- ?LAZY(any_tuple(S))
- ]).
-
-
- any_value() ->
- oneof(any_value_types()).
-
-
- any_value_types() ->
- [
- largeint(),
- int(),
- real(),
- atom(),
- binary()
- ].
-
-
- any_list(0) ->
- [];
-
- any_list(Size) ->
- ListSize = Size div 5,
- vector(ListSize, any(Size div 2)).
-
-
- any_tuple(0) ->
- {};
-
- any_tuple(Size) ->
- ?LET(L, any_list(Size), list_to_tuple(L)).
-
-
- % JSON Generation
-
- json() ->
- ?SIZED(Size, json(Size)).
-
-
- json(0) ->
- oneof([
- json_null(),
- json_true(),
- json_false(),
- json_number(),
- json_string()
- ]);
-
- json(Size) ->
- frequency([
- {1, json_null()},
- {1, json_true()},
- {1, json_false()},
- {1, json_number()},
- {1, json_string()},
- {5, ?LAZY(json_array(Size))},
- {5, ?LAZY(json_object(Size))}
- ]).
-
-
- json_null() ->
- null.
-
-
- json_true() ->
- true.
-
-
- json_false() ->
- false.
-
-
- json_number() ->
- oneof([largeint(), int(), real()]).
-
-
- json_string() ->
- utf8().
-
-
- json_array(0) ->
- [];
-
- json_array(Size) ->
- ArrSize = Size div 5,
- vector(ArrSize, json(Size div 2)).
-
-
- json_object(0) ->
- {[]};
- json_object(Size) ->
- ObjSize = Size div 5,
- {vector(ObjSize, {json_string(), json(Size div 2)})}.
-
-
- combiner() ->
- ?SIZED(
- Size,
- ?LET(
- L,
- vector((Size div 4) + 1, oneof([$\r, $\n, $\t, $\s])),
- list_to_binary(L)
- )
- ).
-
-
- atom() ->
- ?LET(L, ?SIZED(Size, vector(Size rem 254, char())), list_to_atom(L)).
-
-
-
- %% XXX: Add generators
- %
- % We should add generators that generate JSON binaries directly
- % so we can test things that aren't produced by the encoder.
- %
- % We should also have a version of the JSON generator that inserts
- % errors into the JSON that we can test for.
-
-
- -endif.
|