diff --git a/.gitignore b/.gitignore index 3e54b2a..ce5e047 100644 --- a/.gitignore +++ b/.gitignore @@ -5,9 +5,11 @@ *.dump *.tag.gz *.tgz +*.lock ebin/ deps/ .eunit/ tests/ -rebar +rebar3 +_build/ *.sublime-* diff --git a/src/cache.app.src b/src/cache.app.src index c4576cb..c67a019 100644 --- a/src/cache.app.src +++ b/src/cache.app.src @@ -1,7 +1,7 @@ {application, cache, [ {description, "in-memory cache"}, - {vsn, "2.0.0"}, + {vsn, "2.1.0"}, {modules, []}, {registered, []}, {applications,[ diff --git a/src/cache_heap.erl b/src/cache_heap.erl index e6cab1a..16731d3 100644 --- a/src/cache_heap.erl +++ b/src/cache_heap.erl @@ -72,7 +72,7 @@ tail(#heap{segments=[_ | Tail]}) -> Tail. %% -%% return tail +%% return reference to all segments -spec(refs/1 :: (#heap{}) -> [{integer(), integer()}]). refs(#heap{segments=Refs}) -> diff --git a/test/cache_SUITE.erl b/test/cache_SUITE.erl index f110828..c120c66 100644 --- a/test/cache_SUITE.erl +++ b/test/cache_SUITE.erl @@ -36,9 +36,26 @@ %% %% cache basic i/o -export([ - put/1 + put/1, + get/1, + lookup/1, + has/1, + remove/1 ]). +%% +%% cache extended i/o +-export([ + acc/1, + set/1, + add/1, + replace/1, + append/1, + prepend/1, + delete/1 +]). + + %%%---------------------------------------------------------------------------- %%% %%% suite @@ -47,7 +64,8 @@ all() -> [ {group, primitives}, - {group, basic_io} + {group, basic_io}, + {group, extended_io} ]. groups() -> @@ -55,7 +73,9 @@ groups() -> {primitives, [parallel], [lifecycle]}, {basic_io, [parallel], - [put]} + [put, get, lookup, has, remove]}, + {extended_io, [parallel], + [acc, set, add, replace, append, prepend, delete]} ]. @@ -98,6 +118,97 @@ lifecycle(_Config) -> put(_Config) -> {ok, Cache} = cache:start_link([]), ok = cache:put(Cache, key, val), + [{key, val}] = ets:lookup(cache:heap(Cache, 1), key), + ok = cache:drop(Cache). + +get(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:put(Cache, key, val), + val = cache:get(Cache, key), + undefined = cache:get(Cache, unknown), + ok = cache:drop(Cache). + +lookup(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:put(Cache, key, val), + val = cache:lookup(Cache, key), + undefined = cache:lookup(Cache, unknown), + ok = cache:drop(Cache). + +has(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:put(Cache, key, val), + true = cache:has(Cache, key), + false = cache:has(Cache, unknown), + ok = cache:drop(Cache). + +remove(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:put(Cache, key, val), + true = cache:has(Cache, key), + ok = cache:remove(Cache, key), + false= cache:has(Cache, key), + ok = cache:drop(Cache). + + +%%%---------------------------------------------------------------------------- +%%% +%%% cache extended i/o +%%% +%%%---------------------------------------------------------------------------- + +acc(_Config) -> + {ok, Cache} = cache:start_link([]), + undefined = cache:acc(Cache, key, 1), + 1 = cache:acc(Cache, key, 10), + 11 = cache:acc(Cache, key, 1), + ok = cache:drop(Cache). + +set(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:set(Cache, key, val), + val = cache:get(Cache, key), + ok = cache:drop(Cache). + +add(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:add(Cache, key, val), + {error, conflict} = cache:add(Cache, key, val), + ok = cache:drop(Cache). + +replace(_Config) -> + {ok, Cache} = cache:start_link([]), + {error, not_found} = cache:replace(Cache, key, val), + ok = cache:set(Cache, key, val), + ok = cache:replace(Cache, key, val), + ok = cache:drop(Cache). + +append(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:append(Cache, key, a), + [a] = cache:get(Cache, key), + ok = cache:append(Cache, key, b), + [a, b] = cache:get(Cache, key), + ok = cache:append(Cache, key, c), + [a, b, c] = cache:get(Cache, key), + ok = cache:drop(Cache). + +prepend(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:prepend(Cache, key, a), + [a] = cache:get(Cache, key), + ok = cache:prepend(Cache, key, b), + [b, a] = cache:get(Cache, key), + ok = cache:prepend(Cache, key, c), + [c, b, a] = cache:get(Cache, key), + ok = cache:drop(Cache). + +delete(_Config) -> + {ok, Cache} = cache:start_link([]), + ok = cache:put(Cache, key, val), + true = cache:has(Cache, key), + ok = cache:delete(Cache, key), + false= cache:has(Cache, key), ok = cache:drop(Cache). diff --git a/test/cache_tests.erl b/test/cache_tests.erl deleted file mode 100644 index 6ff92f7..0000000 --- a/test/cache_tests.erl +++ /dev/null @@ -1,115 +0,0 @@ -%% -%% Copyright 2012 Dmitry Kolesnikov, All Rights Reserved -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. -%% -%% @description -%% cache unit test --module(cache_tests). --author('Dmitry Kolesnikov '). --include_lib("eunit/include/eunit.hrl"). - --define(CACHE, [ - {ttl, 3}, %% time-to-live 3 sec - {n, 3}, %% 3 cells - {check, 1} %% check eviction status 1 sec -]). - - -%%%---------------------------------------------------------------------------- -%%% -%%% suites -%%% -%%%---------------------------------------------------------------------------- - -cache_interface_test_() -> - {foreach, - fun init/0 - ,fun free/1 - ,[ - fun i/1 - ,fun heap/1 - ,fun put/1 - ,fun get/1 - ] - }. - -%%%---------------------------------------------------------------------------- -%%% -%%% factory -%%% -%%%---------------------------------------------------------------------------- - -init() -> - {ok, Pid} = cache:start_link(?CACHE), - Pid. - -free(Pid) -> - erlang:unlink(Pid), - cache:drop(Pid). - - -%%%---------------------------------------------------------------------------- -%%% -%%% unit test -%%% -%%%---------------------------------------------------------------------------- - -i(Pid) -> - [ - ?_assertMatch({_, _}, lists:keyfind(heap, 1, cache:i(Pid))) - ,?_assertMatch({_, _}, lists:keyfind(size, 1, cache:i(Pid))) - ,?_assertMatch({_, _}, lists:keyfind(memory, 1, cache:i(Pid))) - ,?_assertMatch({_, _}, lists:keyfind(expire, 1, cache:i(Pid))) - ,?_assertMatch([_| _], cache:i(Pid, heap)) - ,?_assertMatch([_| _], cache:i(Pid, size)) - ,?_assertMatch([_| _], cache:i(Pid, memory)) - ,?_assertMatch([_| _], cache:i(Pid, expire)) - ]. - -heap(Pid) -> - [ - ?_assertMatch(true, is_integer(cache:heap(Pid, 1))) - ,?_assertMatch(badarg, cache:heap(Pid, 2)) - ]. - -put(Pid) -> - [ - ?_assertMatch(ok, cache:put(Pid, <<"key-1">>, <<"val-1">>)) - ,?_assertMatch(ok, cache:put(Pid, <<"key-2">>, <<"val-2">>, 5)) - ,?_assertMatch(ok, async(cache:put_(Pid, <<"key-3">>, <<"val-3">>))) - ,?_assertMatch(ok, async(cache:put_(Pid, <<"key-4">>, <<"val-4">>, 5))) - ]. - -get(Pid) -> - [ - ?_assertMatch(ok, cache:put(Pid, <<"key-1">>, <<"val-1">>)) - ,?_assertMatch(<<"val-1">>, cache:get(Pid, <<"key-1">>)) - ,?_assertMatch(<<"val-1">>, cache:lookup(Pid, <<"key-1">>)) - ,?_assertMatch(true, cache:has(Pid, <<"key-1">>)) - - ,?_assertMatch(ok, async(cache:put_(Pid, <<"key-3">>, <<"val-3">>))) - ,?_assertMatch(<<"val-3">>, cache:get(Pid, <<"key-3">>)) - ,?_assertMatch(<<"val-3">>, cache:lookup(Pid, <<"key-3">>)) - ,?_assertMatch(true, cache:has(Pid, <<"key-3">>)) - - ,?_assertMatch(undefined, cache:get(Pid, <<"key-5">>)) - ,?_assertMatch(undefined, cache:lookup(Pid, <<"key-5">>)) - ,?_assertMatch(false, cache:has(Pid, <<"key-5">>)) - ]. - -async(Ref) -> - receive - {Ref, X} -> - X - end.