Przeglądaj źródła

Implement PropEr tests for JSON parsing

Big thanks to Dmitry Groshev [1] for help getting PropEr tests into
Jiffy. These generate valid EJSON to check parsing as well as check
that random inputs don't cause segfaults or other nasty effects.

Future improvements would be to write a JSON generator as well as a
version that introduces known errors into the binary for checking known
parsing errors as well.

[1] https://github.com/si14

Fixes: #10
pull/11/head
Paul J. Davis 13 lat temu
rodzic
commit
ffa2fafa28
4 zmienionych plików z 178 dodań i 5 usunięć
  1. +3
    -1
      .gitignore
  2. +23
    -4
      Makefile
  3. +14
    -0
      rebar.config
  4. +138
    -0
      test/jiffy_tests.erl

+ 3
- 1
.gitignore Wyświetl plik

@ -1,4 +1,6 @@
*.app
*.beam *.beam
*.o *.o
*.so *.so
ebin/jiffy.app
.eunit
deps

+ 23
- 4
Makefile Wyświetl plik

@ -1,11 +1,30 @@
all: build all: build
%.beam: %.erl
erlc -o test/ $<
clean:
./rebar clean
rm -rf logs
rm -rf .eunit
deps: ./deps/
./rebar get-deps update-deps
build: c_src/decoder.c
build: deps
./rebar compile ./rebar compile
check: test/etap.beam test/util.beam
etap: test/etap.beam test/util.beam
prove test/*.t prove test/*.t
eunit:
./rebar eunit skip_deps=true
check: etap eunit
%.beam: %.erl
erlc -o test/ $<

+ 14
- 0
rebar.config Wyświetl plik

@ -1,3 +1,8 @@
{deps, [
{proper, ".*", {git, "https://github.com/manopapad/proper.git", "master"}}
]}.
{port_sources, ["c_src/*.c"]}. {port_sources, ["c_src/*.c"]}.
{so_name, "jiffy.so"}. {so_name, "jiffy.so"}.
{port_envs, [ {port_envs, [
@ -15,3 +20,12 @@
{"darwin10.*-32$", "CXXFLAGS", "-m32"}, {"darwin10.*-32$", "CXXFLAGS", "-m32"},
{"darwin10.*-32$", "LDFLAGS", "-arch i386"} {"darwin10.*-32$", "LDFLAGS", "-arch i386"}
]}. ]}.
{eunit_opts, [
verbose,
{report, {
eunit_surefire, [{dir,"."}]
}}
]}.

+ 138
- 0
test/jiffy_tests.erl Wyświetl plik

@ -0,0 +1,138 @@
% This file is part of Jiffy released under the MIT license.
% See the LICENSE file for more information.
-module(jiffy_tests).
-include_lib("proper/include/proper.hrl").
-include_lib("eunit/include/eunit.hrl").
proper_test_() ->
PropErOpts = [
{to_file, user},
{max_size, 60},
{numtests, 1000}
],
{timeout, 3600, ?_assertEqual([], proper:module(jiffy_tests, PropErOpts))}.
prop_encode_decode() ->
?FORALL(Data, json(),
begin
%io:format(standard_error, "Data: ~p~n", [Data]),
ExpData = conv_keys(Data),
ExpData == jiffy:decode(jiffy:encode(Data))
end
).
prop_encode_not_crash() ->
?FORALL(Data, any(), begin catch jiffy:encode(Data), true end).
prop_decode_not_crash_bin() ->
?FORALL(Data, binary(), begin catch jiffy:decode(Data), true end).
prop_decode_not_crash_any() ->
?FORALL(Data, any(), begin catch jiffy:decode(Data), true end).
% JSON Generation
json_null() ->
null.
json_boolean() ->
oneof([true, false]).
json_number() ->
oneof([integer(), float()]).
json_string() ->
escaped_utf8_bin().
json_key() ->
oneof([json_string(), escaped_atom()]).
json_list(S) when S =< 0 ->
[];
json_list(S) ->
?LETSHRINK(
[ListSize],
[integer(0, S)],
vector(ListSize, json_text(S - ListSize))
).
json_object(S) when S =< 0 ->
{[]};
json_object(S) ->
?LETSHRINK(
[ObjectSize],
[integer(0, S)],
{vector(ObjectSize, {json_key(), json_text(S - ObjectSize)})}
).
json_value() ->
oneof([
json_null(),
json_boolean(),
json_string(),
json_number()
]).
json_text(S) when S > 0 ->
?LAZY(oneof([
json_list(S),
json_object(S)
]));
json_text(_) ->
json_value().
json() ->
?SIZED(S, json_text(S)).
escaped_atom() ->
?LET(A, atom(),
unicode:characters_to_binary(atom_to_list(A), unicode, utf8)
).
escaped_utf8_bin() ->
?SUCHTHAT(Bin,
?LET(S, ?SUCHTHAT(L, list(escaped_char()), L /= []),
unicode:characters_to_binary(S, unicode, utf8)),
is_binary(Bin)
).
escaped_char() ->
?LET(C, char(),
case C of
$" -> "\\\"";
C -> C
end
).
% Atoms get munged to binaries in the round trip.
conv_keys({Props}) ->
{lists:map(fun({K, V}) -> {conv_key(K), conv_keys(V)} end, Props)};
conv_keys(Vals) when is_list(Vals) ->
lists:map(fun(V) -> conv_keys(V) end, Vals);
conv_keys(Other) ->
Other.
conv_key(K) when is_atom(K) ->
list_to_binary(atom_to_list(K));
conv_key(K) ->
K.

Ładowanie…
Anuluj
Zapisz