Переглянути джерело

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 роки тому
джерело
коміт
ffa2fafa28
4 змінених файлів з 178 додано та 5 видалено
  1. +3
    -1
      .gitignore
  2. +23
    -4
      Makefile
  3. +14
    -0
      rebar.config
  4. +138
    -0
      test/jiffy_tests.erl

+ 3
- 1
.gitignore Переглянути файл

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

+ 23
- 4
Makefile Переглянути файл

@ -1,11 +1,30 @@
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
check: test/etap.beam test/util.beam
etap: test/etap.beam test/util.beam
prove test/*.t
eunit:
./rebar eunit skip_deps=true
check: etap eunit
%.beam: %.erl
erlc -o test/ $<

+ 14
- 0
rebar.config Переглянути файл

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

+ 138
- 0
test/jiffy_tests.erl Переглянути файл

@ -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.

Завантаження…
Відмінити
Зберегти