Skip to content

Commit

Permalink
Merge pull request #11 from basho/fix-rebar3-and-prop
Browse files Browse the repository at this point in the history
Update rebar and explain property failure
  • Loading branch information
martinsumner authored May 11, 2020
2 parents 34b5f71 + 09f3d5a commit 291533d
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 48 deletions.
5 changes: 3 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ compile:
clean:
$(REBAR) clean

cover: test
cover:
$(REBAR) eunit --cover
$(REBAR) cover

test: compile
$(REBAR) as test do eunit
$(REBAR) eunit

dialyzer:
$(REBAR) dialyzer
Expand Down
104 changes: 59 additions & 45 deletions eqc/pbkdf2_eqc.erl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
-module(pbkdf2_eqc).

%% Compile C code and compare C code execution with Erlang code.

-export([prop_equivalent/0]).

-include_lib("eqc/include/eqc.hrl").
Expand All @@ -9,60 +11,72 @@
eqc:on_output(fun(Str, Args) -> io:format(user, Str, Args) end, P)).

eqc_test_() ->
{timeout, 30,
[
{timeout, 30, ?_assertEqual(true, eqc:quickcheck(eqc:testing_time(14, ?QC_OUT(prop_equivalent()))))}
]
}.
{timeout, 30,
[
{timeout, 30, ?_assertEqual(true, eqc:quickcheck(eqc:testing_time(14, ?QC_OUT(prop_equivalent()))))}
]
}.

prop_equivalent() ->
%% try to compile the openssl port we need to compare the erlang version against:
case code:lib_dir(erl_interface) of
{error, Reason} ->
{error, Reason};
EIDir ->
%% we assume the ebin of this file is in .eunit, where rebar puts it
PortSrcDir = "eqc",
%% yeeehaw
[] = os:cmd("gcc -Wno-format -Wno-pointer-sign -Wno-implicit-function-declaration "++PortSrcDir++"/pbkdf2-port.c -o pbkdf2-port -I"++EIDir++"/include -L"++EIDir++"/lib -lei -lssl -lcrypto"),
?FORALL({Password, Salt, Iterations, KeySize}, {gen_print_bin(), gen_salt(), gen_iterations(), gen_keysize()},
begin
Port = open_port({spawn, "./pbkdf2-port"}, [{packet, 4}]),
Hash = sha, %% only hash openssl supports for PBKDF2 is SHA1 :(
{ok, Bin} = pbkdf2:pbkdf2(Hash, Password, Salt, Iterations, KeySize),
Result = pbkdf2:to_hex(Bin),
port_command(Port, term_to_binary({Hash, Password, Salt, Iterations, KeySize})),
Expected = receive
{Port, {data, E}} ->
list_to_binary(E)
after
5000 ->
timeout
end,
port_close(Port),
?WHENFAIL(begin
io:format(user, "Password ~p~n", [Password]),
io:format(user, "Salt ~p~n", [Salt]),
io:format(user, "Iterations ~p~n", [Iterations]),
io:format(user, "KeySize ~p~n", [KeySize]),
io:format(user, "Expected ~p~n", [Expected]),
io:format(user, "Result ~p~n", [Result])
end,
Expected == Result)
end)
end.
?SETUP(fun() ->
ok = compile_c_code(),
fun(_) -> ok end
end,
?FORALL({Password, Salt, Iterations, KeySize}, {gen_print_bin(), gen_salt(), gen_iterations(), gen_keysize()},
begin
Port = open_port({spawn, "./pbkdf2-port"}, [{packet, 4}]),
Hash = sha, %% only hash openssl supports for PBKDF2 is SHA1 :(
{ok, Bin} = pbkdf2:pbkdf2(Hash, Password, Salt, Iterations, KeySize),
Result = pbkdf2:to_hex(Bin),
port_command(Port, term_to_binary({Hash, Password, Salt, Iterations, KeySize})),
Expected = receive
{Port, {data, E}} ->
list_to_binary(E)
after
5000 ->
timeout
end,
port_close(Port),
?WHENFAIL(begin
io:format(user, "Password ~p~n", [Password]),
io:format(user, "Salt ~p~n", [Salt]),
io:format(user, "Iterations ~p~n", [Iterations]),
io:format(user, "KeySize ~p~n", [KeySize]),
io:format(user, "Expected ~p~n", [Expected]),
io:format(user, "Result ~p~n", [Result])
end,
Expected == Result)
end)).

compile_c_code() ->
%% try to compile the openssl port we need to compare the erlang version against:
case code:lib_dir(erl_interface) of
{error, Reason} ->
{error, Reason};
EIDir ->
%% EIDir is the erl_interface dir which contains lib and include for erl_interface C code
PortSrcDir = "./eqc",
%% yeeehaw
case os:cmd("gcc -Wno-format -Wno-pointer-sign -Wno-implicit-function-declaration "++PortSrcDir++"/pbkdf2-port.c -o pbkdf2-port -I"++EIDir++"/include -L"++EIDir++"/lib -lei -lssl -lcrypto") of
[] ->
ok;
Error ->
%% We need access to include files like openssl/evp.h
{error, {compiling_c_code, Error}}
end
end.

gen_print_str() ->
?LET(Xs, list(char()), [X || X <- Xs, io_lib:printable_list([X]), X /= $~, X < 255]).
?LET(Xs, list(char()), [X || X <- Xs, io_lib:printable_list([X]), X /= $~, X < 255]).

gen_print_bin() ->
?SUCHTHAT(B, ?LET(Xs, gen_print_str(), list_to_binary(Xs)), B/= <<>>).
?SUCHTHAT(B, ?LET(Xs, gen_print_str(), list_to_binary(Xs)), B/= <<>>).

gen_salt() ->
?SUCHTHAT(S, binary(), S /= <<>>).
?SUCHTHAT(S, binary(), S /= <<>>).

gen_keysize() ->
?LET(Xs, nat(), Xs+5).
?LET(Xs, nat(), Xs+5).

gen_iterations() ->
?LET(X, ?SUCHTHAT(I, nat(), I > 0), X*X).
?LET(X, ?SUCHTHAT(I, nat(), I > 0), X*X).
2 changes: 1 addition & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{cover_enabled, true}.

{plugins, [{rebar3_eqc, {git, "https://github.com/Vagabond/rebar3-eqc-plugin", {branch, "master"}}}]}.
{plugins, [{eqc_rebar, {git, "https://github.com/Quviq/eqc-rebar", {branch, "master"}}}]}.

{xref_checks,[undefined_function_calls,undefined_functions,locals_not_used,
deprecated_function_calls, deprecated_functions]}.
Binary file modified rebar3
Binary file not shown.

0 comments on commit 291533d

Please sign in to comment.