Introduce iodata() in the EQC tests.

Introduce a type for iodata() in the EQC tests. Use this type throughout
the tests in order to make sure we can supply iodata() in all places where
we claim we can supply iodata().
This commit is contained in:
Jesper Louis Andersen 2014-12-17 08:36:49 +01:00
parent 797daa653b
commit b1ed21e71d

View File

@ -2,6 +2,50 @@
-include_lib("eqc/include/eqc.hrl"). -include_lib("eqc/include/eqc.hrl").
-compile(export_all). -compile(export_all).
non_byte_int() ->
oneof([
?LET(N, nat(), -(N+1)),
?LET(N, nat(), N+256)
]).
g_iolist() ->
?SIZED(Sz, g_iolist(Sz)).
g_iolist(0) ->
fault(
oneof([
elements([a,b,c]),
real(),
non_byte_int()
]),
return([]));
g_iolist(N) ->
fault(
oneof([
elements([a,b,c]),
real(),
non_byte_int()
]),
frequency([
{1, g_iolist(0)},
{N, ?LAZY(list(oneof([char(), binary(), g_iolist(N div 4)])))}
])).
g_iodata() ->
fault(
oneof([elements([a,b,c]), real()]),
oneof([binary(), g_iolist()])).
v_iolist([]) -> true;
v_iolist([B|Xs]) when is_binary(B) -> v_iolist(Xs);
v_iolist([C|Xs]) when is_integer(C), C >= 0, C < 256 -> v_iolist(Xs);
v_iolist([L|Xs]) when is_list(L) ->
v_iolist(L) andalso v_iolist(Xs);
v_iolist(_) -> false.
v_iodata(B) when is_binary(B) -> true;
v_iodata(Structure) -> v_iolist(Structure).
%% Generator for binaries of a given size with different properties and fault injection: %% Generator for binaries of a given size with different properties and fault injection:
g_binary(Sz) -> g_binary(Sz) ->
fault(g_binary_bad(Sz), g_binary_good(Sz)). fault(g_binary_bad(Sz), g_binary_good(Sz)).
@ -13,13 +57,15 @@ g_binary_bad(Sz) ->
frequency([ frequency([
{5, ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)}, {5, ?SUCHTHAT(B, binary(), byte_size(B) /= Sz)},
{1, elements([a, b])}, {1, elements([a, b])},
{1, int()} {1, int()},
{1, g_iodata()}
]). ]).
v_binary(Sz, N) when is_binary(N) -> v_binary(Sz, N) when is_binary(N) ->
byte_size(N) == Sz; byte_size(N) == Sz;
v_binary(_, _) -> false. v_binary(_, _) -> false.
%% Typical generators based on the binaries %% Typical generators based on the binaries
nonce() -> g_binary(enacl:box_nonce_size()). nonce() -> g_binary(enacl:box_nonce_size()).
nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N). nonce_valid(N) -> v_binary(enacl:box_nonce_size(), N).
@ -95,16 +141,16 @@ failure(_) -> false.
prop_box_correct() -> prop_box_correct() ->
?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}}, ?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}},
{binary(), {g_iodata(),
fault_rate(1, 40, nonce()), fault_rate(1, 40, nonce()),
fault_rate(1, 40, keypair()), fault_rate(1, 40, keypair()),
fault_rate(1, 40, keypair())}, fault_rate(1, 40, keypair())},
begin begin
case nonce_valid(Nonce) andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of case v_iodata(Msg) andalso nonce_valid(Nonce) andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK2, SK2) of
true -> true ->
CipherText = enacl:box(Msg, Nonce, PK2, SK1), CipherText = enacl:box(Msg, Nonce, PK2, SK1),
{ok, DecodedMsg} = enacl:box_open(CipherText, Nonce, PK1, SK2), {ok, DecodedMsg} = enacl:box_open(CipherText, Nonce, PK1, SK2),
equals(Msg, DecodedMsg); equals(iolist_to_binary(Msg), DecodedMsg);
false -> false ->
case box(Msg, Nonce, PK2, SK1) of case box(Msg, Nonce, PK2, SK1) of
badarg -> true; badarg -> true;
@ -115,12 +161,13 @@ prop_box_correct() ->
prop_box_failure_integrity() -> prop_box_failure_integrity() ->
?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}}, ?FORALL({Msg, Nonce, {PK1, SK1}, {PK2, SK2}},
{binary(), {g_iodata(),
fault_rate(1, 40, nonce()), fault_rate(1, 40, nonce()),
fault_rate(1, 40, keypair()), fault_rate(1, 40, keypair()),
fault_rate(1, 40, keypair())}, fault_rate(1, 40, keypair())},
begin begin
case nonce_valid(Nonce) case v_iodata(Msg)
andalso nonce_valid(Nonce)
andalso keypair_valid(PK1, SK1) andalso keypair_valid(PK1, SK1)
andalso keypair_valid(PK2, SK2) of andalso keypair_valid(PK2, SK2) of
true -> true ->
@ -128,7 +175,7 @@ prop_box_failure_integrity() ->
Err = enacl:box_open([<<"x">>, CipherText], Nonce, PK1, SK2), Err = enacl:box_open([<<"x">>, CipherText], Nonce, PK1, SK2),
equals(Err, {error, failed_verification}); equals(Err, {error, failed_verification});
false -> false ->
case box(Msg, Nonce, PK2, SK1) of case box(iolist_to_binary(Msg), Nonce, PK2, SK1) of
badarg -> true; badarg -> true;
Res -> Res ->
failure(box_open(Res, Nonce, PK1, SK2)) failure(box_open(Res, Nonce, PK1, SK2))
@ -182,9 +229,9 @@ sign_keypair_valid(KP) ->
sign_keypair_public_valid(KP) andalso sign_keypair_secret_valid(KP). sign_keypair_public_valid(KP) andalso sign_keypair_secret_valid(KP).
prop_sign() -> prop_sign() ->
?FORALL({Msg, KeyPair}, {binary(), fault_rate(1, 40, sign_keypair())}, ?FORALL({Msg, KeyPair}, {g_iodata(), fault_rate(1, 40, sign_keypair())},
begin begin
case sign_keypair_secret_valid(KeyPair) of case v_iodata(Msg) andalso sign_keypair_secret_valid(KeyPair) of
true -> true ->
#{ secret := Secret } = KeyPair, #{ secret := Secret } = KeyPair,
enacl:sign(Msg, Secret), enacl:sign(Msg, Secret),
@ -218,13 +265,13 @@ signed_message_valid({invalid, _}, _) -> true;
signed_message_valid(_, _) -> false. signed_message_valid(_, _) -> false.
prop_sign_open() -> prop_sign_open() ->
?FORALL(Msg, binary(), ?FORALL(Msg, g_iodata(),
?FORALL({SignMsg, PK}, signed_message(Msg), ?FORALL({SignMsg, PK}, signed_message(Msg),
case signed_message_valid(SignMsg, PK) of case v_iodata(Msg) andalso signed_message_valid(SignMsg, PK) of
true -> true ->
case SignMsg of case SignMsg of
{valid, SM} -> {valid, SM} ->
equals({ok, Msg}, enacl:sign_open(SM, PK)); equals({ok, iolist_to_binary(Msg)}, enacl:sign_open(SM, PK));
{invalid, SM} -> {invalid, SM} ->
equals({error, failed_verification}, enacl:sign_open(SM, PK)) equals({error, failed_verification}, enacl:sign_open(SM, PK))
end; end;
@ -287,15 +334,15 @@ secretbox_open(Msg, Nonce, Key) ->
prop_secretbox_correct() -> prop_secretbox_correct() ->
?FORALL({Msg, Nonce, Key}, ?FORALL({Msg, Nonce, Key},
{binary(), {g_iodata(),
fault_rate(1, 40, nonce()), fault_rate(1, 40, nonce()),
fault_rate(1, 40, secret_key())}, fault_rate(1, 40, secret_key())},
begin begin
case nonce_valid(Nonce) andalso secret_key_valid(Key) of case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of
true -> true ->
CipherText = enacl:secretbox(Msg, Nonce, Key), CipherText = enacl:secretbox(Msg, Nonce, Key),
{ok, DecodedMsg} = enacl:secretbox_open(CipherText, Nonce, Key), {ok, DecodedMsg} = enacl:secretbox_open(CipherText, Nonce, Key),
equals(Msg, DecodedMsg); equals(iolist_to_binary(Msg), DecodedMsg);
false -> false ->
case secretbox(Msg, Nonce, Key) of case secretbox(Msg, Nonce, Key) of
badarg -> true; badarg -> true;
@ -306,7 +353,7 @@ prop_secretbox_correct() ->
end). end).
prop_secretbox_failure_integrity() -> prop_secretbox_failure_integrity() ->
?FORALL({Msg, Nonce, Key}, {binary(), nonce(), secret_key()}, ?FORALL({Msg, Nonce, Key}, {g_iodata(), nonce(), secret_key()},
begin begin
CipherText = enacl:secretbox(Msg, Nonce, Key), CipherText = enacl:secretbox(Msg, Nonce, Key),
Err = enacl:secretbox_open([<<"x">>, CipherText], Nonce, Key), Err = enacl:secretbox_open([<<"x">>, CipherText], Nonce, Key),
@ -327,15 +374,24 @@ prop_stream_correct() ->
badargs(fun() -> enacl:stream(Len, Nonce, Key) end) badargs(fun() -> enacl:stream(Len, Nonce, Key) end)
end). end).
xor_bytes(<<A, As/binary>>, <<B, Bs/binary>>) ->
[A bxor B | xor_bytes(As, Bs)];
xor_bytes(<<>>, <<>>) -> [].
prop_stream_xor_correct() -> prop_stream_xor_correct() ->
?FORALL({Msg, Nonce, Key}, ?FORALL({Msg, Nonce, Key},
{binary(), {g_iodata(),
fault_rate(1, 40, nonce()), fault_rate(1, 40, nonce()),
fault_rate(1, 40, secret_key())}, fault_rate(1, 40, secret_key())},
case nonce_valid(Nonce) andalso secret_key_valid(Key) of case v_iodata(Msg) andalso nonce_valid(Nonce) andalso secret_key_valid(Key) of
true -> true ->
Stream = enacl:stream(iolist_size(Msg), Nonce, Key),
CipherText = enacl:stream_xor(Msg, Nonce, Key), CipherText = enacl:stream_xor(Msg, Nonce, Key),
equals(Msg, enacl:stream_xor(CipherText, Nonce, Key)); StreamXor = enacl:stream_xor(CipherText, Nonce, Key),
conjunction([
{'xor', equals(iolist_to_binary(Msg), StreamXor)},
{stream, equals(iolist_to_binary(xor_bytes(Stream, iolist_to_binary(Msg))), CipherText)}
]);
false -> false ->
badargs(fun() -> enacl:stream_xor(Msg, Nonce, Key) end) badargs(fun() -> enacl:stream_xor(Msg, Nonce, Key) end)
end). end).
@ -343,9 +399,9 @@ prop_stream_xor_correct() ->
%% CRYPTO AUTH %% CRYPTO AUTH
prop_auth_correct() -> prop_auth_correct() ->
?FORALL({Msg, Key}, ?FORALL({Msg, Key},
{binary(), {g_iodata(),
fault_rate(1, 40, secret_key())}, fault_rate(1, 40, secret_key())},
case secret_key_valid(Key) of case v_iodata(Msg) andalso secret_key_valid(Key) of
true -> true ->
Authenticator = enacl:auth(Msg, Key), Authenticator = enacl:auth(Msg, Key),
equals(Authenticator, enacl:auth(Msg, Key)); equals(Authenticator, enacl:auth(Msg, Key));
@ -377,10 +433,10 @@ authenticator_valid(_) -> false.
prop_auth_verify_correct() -> prop_auth_verify_correct() ->
?FORALL({Msg, Key}, ?FORALL({Msg, Key},
{binary(), {g_iodata(),
fault_rate(1, 40, secret_key())}, fault_rate(1, 40, secret_key())},
?FORALL(Authenticator, authenticator(Msg, Key), ?FORALL(Authenticator, authenticator(Msg, Key),
case secret_key_valid(Key) andalso authenticator_valid(Authenticator) of case v_iodata(Msg) andalso secret_key_valid(Key) andalso authenticator_valid(Authenticator) of
true -> true ->
case Authenticator of case Authenticator of
{valid, A} -> {valid, A} ->
@ -395,9 +451,9 @@ prop_auth_verify_correct() ->
%% CRYPTO ONETIME AUTH %% CRYPTO ONETIME AUTH
prop_onetimeauth_correct() -> prop_onetimeauth_correct() ->
?FORALL({Msg, Key}, ?FORALL({Msg, Key},
{binary(), {g_iodata(),
fault_rate(1, 40, secret_key())}, fault_rate(1, 40, secret_key())},
case secret_key_valid(Key) of case v_iodata(Msg) andalso secret_key_valid(Key) of
true -> true ->
Authenticator = enacl:onetime_auth(Msg, Key), Authenticator = enacl:onetime_auth(Msg, Key),
equals(Authenticator, enacl:onetime_auth(Msg, Key)); equals(Authenticator, enacl:onetime_auth(Msg, Key));
@ -429,10 +485,10 @@ ot_authenticator_valid(_) -> false.
prop_onetime_auth_verify_correct() -> prop_onetime_auth_verify_correct() ->
?FORALL({Msg, Key}, ?FORALL({Msg, Key},
{binary(), {g_iodata(),
fault_rate(1, 40, secret_key())}, fault_rate(1, 40, secret_key())},
?FORALL(Authenticator, ot_authenticator(Msg, Key), ?FORALL(Authenticator, ot_authenticator(Msg, Key),
case secret_key_valid(Key) andalso ot_authenticator_valid(Authenticator) of case v_iodata(Msg) andalso secret_key_valid(Key) andalso ot_authenticator_valid(Authenticator) of
true -> true ->
case Authenticator of case Authenticator of
{valid, A} -> {valid, A} ->
@ -446,14 +502,13 @@ prop_onetime_auth_verify_correct() ->
%% HASHING %% HASHING
%% --------------------------- %% ---------------------------
diff_pair(Sz) -> diff_pair() ->
?SUCHTHAT({X, Y}, {g_binary(Sz), g_binary(Sz)}, ?SUCHTHAT({X, Y}, {g_iodata(), g_iodata()},
X /= Y). iolist_to_binary(X) /= iolist_to_binary(Y)).
prop_crypto_hash_eq() -> prop_crypto_hash_eq() ->
?FORALL(Sz, oneof([1, 128, 1024, 1024*4]), ?FORALL(X, g_iodata(),
?FORALL(X, g_binary(Sz), case v_iodata(X) of
case is_binary(X) of
true -> equals(enacl:hash(X), enacl:hash(X)); true -> equals(enacl:hash(X), enacl:hash(X));
false -> false ->
try try
@ -463,13 +518,12 @@ prop_crypto_hash_eq() ->
error:badarg -> true error:badarg -> true
end end
end end
)). ).
prop_crypto_hash_neq() -> prop_crypto_hash_neq() ->
?FORALL(Sz, oneof([1, 128, 1024, 1024*4]), ?FORALL({X, Y}, diff_pair(),
?FORALL({X, Y}, diff_pair(Sz),
enacl:hash(X) /= enacl:hash(Y) enacl:hash(X) /= enacl:hash(Y)
)). ).
%% STRING COMPARISON %% STRING COMPARISON
%% ------------------------- %% -------------------------