From 96b341fde50052785f296e969c658d010c2c037c Mon Sep 17 00:00:00 2001 From: Gilbert Date: Wed, 7 Aug 2019 09:24:03 +0800 Subject: [PATCH] Add proper tests for base62 (#2761) * Add proper tests for base62 * Delete useless comment --- .travis.yml | 1 + Makefile | 7 ++++++ rebar.config | 6 +++--- src/emqx_base62.erl | 13 +---------- src/emqx_guid.erl | 3 +-- test/prop_base62.erl | 51 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 test/prop_base62.erl diff --git a/.travis.yml b/.travis.yml index abe6f7a6a..c0b7bf5b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ script: - make xref - make eunit - make ct + - make proper - make cover after_success: diff --git a/Makefile b/Makefile index 202046e60..b0a1dce16 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,13 @@ RUN_NODE_NAME = emqxdebug@127.0.0.1 .PHONY: all all: compile +.PHONY: tests +tests: eunit ct proper + +.PHONY: proper +proper: + @rebar3 proper + .PHONY: run run: run_setup unlock @rebar3 as test get-deps diff --git a/rebar.config b/rebar.config index 3d0971cdf..fff6954c9 100644 --- a/rebar.config +++ b/rebar.config @@ -21,15 +21,15 @@ {cover_opts, [verbose]}. {cover_export_enabled, true}. -{plugins, [coveralls]}. +{plugins, [coveralls, + rebar3_proper]}. {erl_first_files, ["src/emqx_logger.erl"]}. {profiles, [{test, [{deps, - [{meck, "0.8.13"}, % hex - {bbmustache, "1.7.0"}, % hex + [{bbmustache, "1.7.0"}, % hex {emqtt, {git, "https://github.com/emqx/emqtt", {tag, "v1.0.1"}}}, {emqx_ct_helpers, {git, "https://github.com/emqx/emqx-ct-helpers", {branch, "develop"}}} ]} diff --git a/src/emqx_base62.erl b/src/emqx_base62.erl index 6d1f5a882..979821d06 100644 --- a/src/emqx_base62.erl +++ b/src/emqx_base62.erl @@ -18,9 +18,7 @@ %% APIs -export([ encode/1 - , encode/2 , decode/1 - , decode/2 ]). %%-------------------------------------------------------------------- @@ -32,7 +30,7 @@ encode(I) when is_integer(I) -> encode(integer_to_binary(I)); encode(S) when is_list(S)-> - encode(list_to_binary(S)); + encode(unicode:characters_to_binary(S)); encode(B) when is_binary(B) -> encode(B, <<>>). @@ -40,8 +38,6 @@ encode(B) when is_binary(B) -> %% binary_to_list(encode(D)). %% @doc Decode base62 binary to origin data binary -decode(L) when is_list(L) -> - decode(list_to_binary(L)); decode(B) when is_binary(B) -> decode(B, <<>>). @@ -49,8 +45,6 @@ decode(B) when is_binary(B) -> %% Interval Functions %%-------------------------------------------------------------------- -encode(D, string) -> - binary_to_list(encode(D)); encode(<>, Acc) -> CharList = [encode_char(Index1), encode_char(Index2), encode_char(Index3), encode_char(Index4)], NewAcc = <>, @@ -66,10 +60,6 @@ encode(<>, Acc) -> encode(<<>>, Acc) -> Acc. -decode(D, integer) -> - binary_to_integer(decode(D)); -decode(D, string) -> - binary_to_list(decode(D)); decode(<>, Acc) when bit_size(Rest) >= 8-> case Head == $9 of @@ -114,4 +104,3 @@ decode_char(I) when I >= $A andalso I =< $Z-> decode_char(9, I) -> I + 61 - $A. - diff --git a/src/emqx_guid.erl b/src/emqx_guid.erl index 2a3715b9e..c9368ca1c 100644 --- a/src/emqx_guid.erl +++ b/src/emqx_guid.erl @@ -138,6 +138,5 @@ to_base62(<>) -> emqx_base62:encode(I). from_base62(S) -> - I = emqx_base62:decode(S, integer), + I = binary_to_integer( emqx_base62:decode(S)), <>. - diff --git a/test/prop_base62.erl b/test/prop_base62.erl new file mode 100644 index 000000000..a660012db --- /dev/null +++ b/test/prop_base62.erl @@ -0,0 +1,51 @@ +-module(prop_base62). +-include_lib("proper/include/proper.hrl"). + +%%%%%%%%%%%%%%%%%% +%%% Properties %%% +%%%%%%%%%%%%%%%%%% +prop_symmetric() -> + ?FORALL(Data, raw_data(), + begin + Encoded = emqx_base62:encode(Data), + to_binary(Data) =:= emqx_base62:decode(Encoded) + end). + +prop_size() -> + ?FORALL(Data, binary(), + begin + Encoded = emqx_base62:encode(Data), + base62_size(Data, Encoded) + end). + +%%%%%%%%%%%%%%% +%%% Helpers %%% +%%%%%%%%%%%%%%% +to_binary(Data) when is_list(Data) -> + unicode:characters_to_binary(Data); +to_binary(Data) when is_integer(Data) -> + integer_to_binary(Data); +to_binary(Data) when is_binary(Data) -> + Data. + +base62_size(Data, Encoded) -> + DataSize = erlang:size(Data), + EncodedSize = erlang:size(Encoded), + case (DataSize * 8 rem 6) of + 0 -> + %% Due to the particularity of base 62, 3 bytes data maybe encoded + %% as 4 bytes data or 5 bytes data, the encode size maybe in the + %% range between DataSize*4/3 and DataSize*8/3 + RangeStart = DataSize div 3 * 4, + RangeEnd = DataSize div 3 * 8, + EncodedSize >= RangeStart andalso EncodedSize =< RangeEnd; + _Rem -> + RangeStart = DataSize * 8 div 6 + 1, + RangeEnd = DataSize * 8 div 6 * 2 + 1, + EncodedSize >= RangeStart andalso EncodedSize =< RangeEnd + end. + +%%%%%%%%%%%%%%%%%% +%%% Generators %%% +%%%%%%%%%%%%%%%%%% +raw_data() -> oneof([integer(), string(), binary()]).