diff --git a/src/gm_ctflow.erl b/src/gm_ctflow.erl index 44c8882..a360468 100644 --- a/src/gm_ctflow.erl +++ b/src/gm_ctflow.erl @@ -1,5 +1,30 @@ -module(gm_ctflow). --type flow() :: any(). +-export([ put/2 + , get/1 + , get/2 + , erase/1 + ]). + +-type flow() :: any(). +-type key() :: any(). +-type value() :: any(). -export_type([ flow/0 ]). + +-spec put(key(), value()) -> 'ok'. +put(Key, Value) -> + gm_ctflow_state:put(Key, Value). + +-spec get(key()) -> value() | no_return(). +get(Key) -> + gm_ctflow_state:get(Key). + +-spec get(key(), Default) -> value() + when Default :: value(). +get(Key, Default) -> + gm_ctflow_state:get(Key, Default). + +-spec erase(key()) -> 'ok'. +erase(Key) -> + gm_ctflow_state:erase(Key). diff --git a/src/gm_ctflow_app.erl b/src/gm_ctflow_app.erl index 6848e4e..8489b3e 100644 --- a/src/gm_ctflow_app.erl +++ b/src/gm_ctflow_app.erl @@ -10,6 +10,7 @@ -export([start/2, stop/1]). start(_StartType, _StartArgs) -> + gm_ctflow_state:init(), gm_ctflow_sup:start_link(). stop(_State) -> diff --git a/src/gm_ctflow_state.erl b/src/gm_ctflow_state.erl new file mode 100644 index 0000000..d3910ad --- /dev/null +++ b/src/gm_ctflow_state.erl @@ -0,0 +1,42 @@ +-module(gm_ctflow_state). + +-export([ init/0 + , put/2 + , get/1 + , get/2 + , erase/1 ]). + +-type key() :: any(). +-type value() :: any(). + + +init() -> + ets:new(?MODULE, [ordered_set, public, named_table]). + +-spec put(key(), value()) -> 'ok'. +put(Key, Value) -> + ets:insert(?MODULE, {Key, Value}), + ok. + +-spec get(key()) -> value() | no_return(). +get(Key) -> + case ets:lookup(?MODULE, Key) of + [] -> + error({no_such_key, Key}); + [{_, Value}] -> + Value + end. + +-spec get(key(), Default) -> value() + when Default :: value(). +get(Key, Default) -> + case ets:lookup(?MODULE, Key) of + [{_, Value}] -> + Value; + [] -> + Default + end. + +erase(Key) -> + ets:delete(?MODULE, Key), + ok. diff --git a/test/gm_ctflow_SUITE.erl b/test/gm_ctflow_SUITE.erl index 1bf01c0..ed255e9 100644 --- a/test/gm_ctflow_SUITE.erl +++ b/test/gm_ctflow_SUITE.erl @@ -11,7 +11,10 @@ ]). %% test cases --export([ init_counter/1 +-export([ put_a/1 + , get_a/1 + , erase_a/1 + , init_counter/1 , incr/1 , check1/1 , check2/1 @@ -27,12 +30,17 @@ all() -> [ - {group, statefuns} + {group, state} + , {group, statefuns} , {group, workers} ]. groups() -> - [ {statefuns, [sequence], [ init_counter + [ {state, [sequence], [ put_a + , get_a + , erase_a + ]} + , {statefuns, [sequence], [ init_counter , incr , check1 %% state = 1 , incr @@ -71,6 +79,21 @@ init_per_testcase(_Case, Config) -> end_per_testcase(_Case, _Config) -> ok. +%% ====================================================================== +%% State update commands + +put_a(_Cfg) -> + ok = gm_ctflow:put(a, 1), + ?assertMatch(1, gm_ctflow:get(a)). + +get_a(_Cfg) -> + ?assertMatch(1, gm_ctflow:get(a)). + +erase_a(_Cfg) -> + ok = gm_ctflow:erase(a), + ?assertException(error, {no_such_key,a}, gm_ctflow:get(a)), + ?assertMatch(undefined, gm_ctflow:get(a, undefined)). + %% ====================================================================== %% This is our 'ctflow_fun' instance, which floats above some simple %% test cases. In this test suite, we only exercise the flow funs, but