Implement sync_fold_range as part of the test.

This commit is contained in:
Jesper Louis Andersen 2012-01-22 12:34:22 +01:00
parent e61f80f4e0
commit 363e94c3cf
2 changed files with 39 additions and 1 deletions

View file

@ -13,6 +13,7 @@
open/1, close/1,
put/3,
sync_range/3,
sync_fold_range/5,
stop/0]).
%% gen_server callbacks
@ -53,6 +54,9 @@ put(N, K, V) ->
sync_range(T, LK, HK) ->
call({sync_range, T, LK, HK}).
sync_fold_range(T, Fun, Acc0, LK, HK) ->
call({sync_fold_range, T, Fun, Acc0, LK, HK}).
stop() ->
call(stop).
@ -82,6 +86,12 @@ handle_call({sync_range, Name, LoKey, HiKey}, _From,
{ok, Ref} = lsm_btree:sync_range(Tree, LoKey, HiKey),
Result = sync_range_gather(Ref),
{reply, Result, State};
handle_call({sync_fold_range, Name, Fun, Acc0, LoKey, HiKey},
_From,
#state { btrees = D } = State) ->
Tree = dict:fetch(Name, D),
Result = lsm_btree:sync_fold_range(Tree, Fun, Acc0, LoKey, HiKey),
{reply, Result, State};
handle_call({put, N, K, V}, _, #state { btrees = D} = State) ->
Tree = dict:fetch(N, D),
case lsm_btree:put(Tree, K, V) of

View file

@ -92,6 +92,9 @@ g_non_existing_key(Name, Open) ->
not dict:is_key(Key, D)
end).
g_fold_operation() ->
oneof([{fun (K, V, Acc) -> [{K, V} | Acc] end, []}]).
btree_name(I) ->
"Btree_" ++ integer_to_list(I).
@ -122,11 +125,15 @@ command(#state { open = Open, closed = Closed } = S) ->
|| open_dicts(S), open_dicts_with_keys(S)]
++ [ {500, {call, ?SERVER, delete_exist, cmd_delete_args(S)}}
|| open_dicts(S), open_dicts_with_keys(S)]
++ [ {250, {call, ?SERVER, sync_range, cmd_sync_range_args(S)}}
++ [ {125, {call, ?SERVER, sync_fold_range, cmd_sync_fold_range_args(S)}}
|| open_dicts(S), open_dicts_with_keys(S)]
++ [ {125, {call, ?SERVER, sync_range, cmd_sync_range_args(S)}}
|| open_dicts(S), open_dicts_with_keys(S)]
).
%% Precondition (abstract)
precondition(S, {call, ?SERVER, sync_fold_range, [_Tree, _F, _A0, _K1, _K2]}) ->
open_dicts(S) andalso open_dicts_with_keys(S);
precondition(S, {call, ?SERVER, sync_range, [_Tree, _K1, _K2]}) ->
open_dicts(S) andalso open_dicts_with_keys(S);
precondition(S, {call, ?SERVER, delete_exist, [_Name, _K]}) ->
@ -145,6 +152,8 @@ precondition(#state { open = Open, closed = Closed },
(dict:is_key(Name, Open)) and (not dict:is_key(Name, Closed)).
%% Next state manipulation (abstract / concrete)
next_state(S, _Res, {call, ?SERVER, sync_fold_range, [_Tree, _F, _A0, _K1, _K2]}) ->
S;
next_state(S, _Res, {call, ?SERVER, sync_range, [_Tree, _K1, _K2]}) ->
S;
next_state(S, _Res, {call, ?SERVER, lookup_fail, [_Name, _Key]}) ->
@ -178,6 +187,11 @@ next_state(#state { open = Open, closed=Closed} = S, _Res,
open = dict:erase(Name, Open) }.
%% Postcondition check (concrete)
postcondition(#state { open = Open},
{call, ?SERVER, sync_fold_range, [Tree, F, A0, K1, K2]}, Result) ->
#tree { elements = TDict } = dict:fetch(Tree, Open),
lists:sort(dict_range_query(TDict, F, A0, K1, K2))
== lists:sort(Result);
postcondition(#state { open = Open},
{call, ?SERVER, sync_range, [Tree, K1, K2]}, {ok, Result}) ->
#tree { elements = TDict } = dict:fetch(Tree, Open),
@ -199,6 +213,7 @@ postcondition(_S, {call, ?SERVER, open, [_Name]}, ok) ->
postcondition(_S, {call, ?SERVER, close, [_Name]}, ok) ->
true;
postcondition(_, _, _) ->
error_logger:error_report([{not_matching_any_postcondition}]),
false.
@ -335,6 +350,11 @@ cmd_sync_range_args(#state { open = Open }) ->
g_existing_key(Tree, Open)},
[Tree, K1, K2])).
cmd_sync_fold_range_args(State) ->
?LET([Tree, K1, K2], cmd_sync_range_args(State),
?LET({F, Acc0}, g_fold_operation(),
[Tree, F, Acc0, K1, K2])).
%% Context management
%% ----------------------------------------------------------------------
cleanup_test_trees(#state { open = Open, closed = Closed }) ->
@ -366,6 +386,14 @@ open_dicts(#state { open = Open}) ->
closed_dicts(#state { closed = Closed}) ->
dict:size(Closed) > 0.
dict_range_query(Dict, Fun, Acc0, LowKey, HighKey) ->
KVs = dict_range_query(Dict, LowKey, HighKey),
lists:foldl(fun({K, V}, Acc) ->
Fun(K, V, Acc)
end,
Acc0,
KVs).
dict_range_query(Dict, LowKey, HighKey) ->
[{K, V} || {K, V} <- dict:to_list(Dict),
K >= LowKey,