You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@couchdb.apache.org by rn...@apache.org on 2015/06/25 11:38:57 UTC
[5/6] couchdb-couch-epi git commit: Rewrite test suite to test new
functionality
Rewrite test suite to test new functionality
Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/commit/baa9a355
Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/tree/baa9a355
Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/diff/baa9a355
Branch: refs/heads/master
Commit: baa9a3556097ff16a4390026495ba601cc10d0cd
Parents: 67612a6
Author: ILYA Khlopotov <ii...@ca.ibm.com>
Authored: Wed Jun 24 14:14:37 2015 -0700
Committer: ILYA Khlopotov <ii...@ca.ibm.com>
Committed: Wed Jun 24 15:13:50 2015 -0700
----------------------------------------------------------------------
test/couch_epi_tests.erl | 280 ++++++++++++++++++++++++++++--------------
1 file changed, 185 insertions(+), 95 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/couchdb-couch-epi/blob/baa9a355/test/couch_epi_tests.erl
----------------------------------------------------------------------
diff --git a/test/couch_epi_tests.erl b/test/couch_epi_tests.erl
index bba2ae6..227a79f 100644
--- a/test/couch_epi_tests.erl
+++ b/test/couch_epi_tests.erl
@@ -19,9 +19,7 @@
-export([notify_cb/5, save/3]).
--record(ctx, {
- file, data_handle, data_source,
- functions_handle, functions_source, kv}).
+-record(ctx, {file, handle, pid, kv, key}).
-define(TIMEOUT, 5000).
@@ -50,87 +48,146 @@
throw(check_error).
").
+-define(DATA_MODULE1(Name), "
+ -export([data/0]).
+
+ data() ->
+ [
+ {[complex, key, 1], [
+ {type, counter},
+ {desc, foo}
+ ]}
+ ].
+").
+
+-define(DATA_MODULE2(Name), "
+ -export([data/0]).
+
+ data() ->
+ [
+ {[complex, key, 2], [
+ {type, counter},
+ {desc, bar}
+ ]},
+ {[complex, key, 1], [
+ {type, counter},
+ {desc, updated_foo}
+ ]}
+ ].
+").
notify_cb(App, Key, OldData, Data, KV) ->
save(KV, is_called, {App, Key, OldData, Data}).
-setup() ->
+
+setup(couch_epi_data_source) ->
error_logger:tty(false),
Key = {test_app, descriptions},
File = ?tempfile(),
{ok, _} = file:copy(?DATA_FILE1, File),
application:start(couch_epi),
- {ok, DataPid} = couch_epi_data_source:start_link(
+ {ok, Pid} = couch_epi_data_source:start_link(
test_app, {epi_key, Key}, {file, File}, [{interval, 100}]),
- ok = couch_epi_data_source:wait(DataPid),
+ ok = couch_epi_data_source:wait(Pid),
+ KV = state_storage(),
+ #ctx{
+ file = File,
+ key = Key,
+ handle = couch_epi:get_handle(Key),
+ kv = KV,
+ pid = Pid};
+setup(couch_epi_data) ->
+ error_logger:tty(false),
+ Key = {test_app, descriptions},
+ application:start(couch_epi),
+ ok = generate_module(provider, ?DATA_MODULE1(provider)),
+
+ {ok, Pid} = couch_epi_data:start_link(
+ test_app, {epi_key, Key}, provider, []),
+ ok = couch_epi_data:wait(Pid),
+ KV = state_storage(),
+ #ctx{
+ key = Key,
+ handle = couch_epi:get_handle(Key),
+ kv = KV,
+ pid = Pid};
+setup(couch_epi_functions) ->
+ Key = my_service,
+ error_logger:tty(false),
+
+ application:start(couch_epi),
ok = generate_module(provider1, ?MODULE1(provider1)),
ok = generate_module(provider2, ?MODULE2(provider2)),
- {ok, FunctionsPid} = couch_epi_functions:start_link(
- test_app, {epi_key, my_service}, {modules, [provider1, provider2]},
+ {ok, Pid} = couch_epi_functions:start_link(
+ test_app, {epi_key, Key}, {modules, [provider1, provider2]},
[{interval, 100}]),
- ok = couch_epi_functions:wait(FunctionsPid),
+ ok = couch_epi_functions:wait(Pid),
KV = state_storage(),
#ctx{
- file = File,
- data_handle = couch_epi:get_handle(Key),
- functions_handle = couch_epi:get_handle(my_service),
+ key = Key,
+ handle = couch_epi:get_handle(Key),
kv = KV,
- data_source = DataPid,
- functions_source = FunctionsPid}.
-
+ pid = Pid};
setup(_Opts) ->
- setup().
+ setup(couch_epi_functions).
-teardown(_, #ctx{} = Ctx) ->
+teardown(Module, #ctx{pid = Pid} = Ctx) when is_atom(Module) ->
+ Module:stop(Pid),
+ teardown(Ctx);
+teardown(_Opts, #ctx{pid = Pid} = Ctx) ->
+ couch_epi_functions:stop(Pid),
teardown(Ctx).
-teardown(#ctx{data_source = DataPid,
- functions_source = FunctionsPid,
- kv = KV, file = File}) ->
+teardown(#ctx{file = File} = Ctx) when File /= undefined ->
file:delete(File),
- couch_epi_data_source:stop(DataPid),
- couch_epi_functions:stop(FunctionsPid),
- catch meck:unload(compile),
+ teardown(Ctx#ctx{file = undefined});
+teardown(#ctx{kv = KV}) ->
call(KV, stop),
application:stop(couch_epi),
ok.
+upgrade_release(Pid, Module) ->
+ sys:suspend(Pid),
+ 'ok' = sys:change_code(Pid, Module, 'undefined', []),
+ sys:resume(Pid),
+ ok.
+
epi_config_update_test_() ->
Funs = [
fun ensure_notified_when_changed/2,
fun ensure_not_notified_when_no_change/2,
fun ensure_not_notified_when_unsubscribed/2
],
+ Modules= [
+ couch_epi_data,
+ couch_epi_data_source,
+ couch_epi_functions
+ ],
{
"config update tests",
- {
- foreach,
- fun setup/0,
- fun teardown/1,
- [make_case("Check notifications for: ", [module, file], Funs)]
- }
+ [make_case("Check notifications for: ", Modules, Funs)]
}.
epi_data_source_test_() ->
+ Funs = [
+ fun check_dump/2,
+ fun check_get/2,
+ fun check_get_value/2,
+ fun check_by_key/2,
+ fun check_by_source/2,
+ fun check_keys/2,
+ fun check_subscribers/2
+ ],
+ Modules= [
+ couch_epi_data,
+ couch_epi_data_source
+ ],
{
- "epi data_source tests",
- {
- foreach,
- fun setup/0,
- fun teardown/1,
- [
- fun check_dump/1,
- fun check_get/1,
- fun check_get_value/1,
- fun check_by_key/1,
- fun check_by_source/1,
- fun check_keys/1,
- fun check_subscribers/1
- ]
- }
+ "epi data API tests",
+ [make_case("Check query API for: ", Modules, Funs)]
}.
@@ -139,7 +196,7 @@ epi_apply_test_() ->
"epi dispatch tests",
{
foreach,
- fun setup/0,
+ fun() -> setup(couch_epi_functions) end,
fun teardown/1,
[
fun check_pipe/1,
@@ -150,16 +207,35 @@ epi_apply_test_() ->
}
}.
+
epi_subscription_test_() ->
+ Funs = [
+ fun ensure_unsubscribe_when_caller_die/2
+ ],
+ Modules= [
+ couch_epi_data,
+ couch_epi_data_source,
+ couch_epi_functions
+ ],
{
"epi subscription tests",
+ [make_case("Check subscription API for: ", Modules, Funs)]
+ }.
+
+
+epi_reload_test_() ->
+ Modules= [
+ couch_epi_data,
+ couch_epi_data_source,
+ couch_epi_functions
+ ],
+ {
+ "epi reload tests",
{
- foreach,
- fun setup/0,
- fun teardown/1,
- [
- fun ensure_unsubscribe_when_caller_die/1
- ]
+ foreachx,
+ fun setup/1,
+ fun teardown/2,
+ [{M, fun ensure_reloaded/2} || M <- Modules]
}
}.
@@ -191,11 +267,22 @@ valid_options_permutations() ->
[concurrent, ignore_errors]
].
-ensure_notified_when_changed(file, #ctx{file = File} = Ctx) ->
+ensure_notified_when_changed(couch_epi_functions, #ctx{key = Key} = Ctx) ->
+ ?_test(begin
+ subscribe(Ctx, test_app, Key),
+ update(couch_epi_functions, Ctx),
+ timer:sleep(200),
+ Result = get(Ctx, is_called),
+ Expected = {test_app, Key,
+ {modules, [provider1, provider2]},
+ {modules, [provider1, provider2]}},
+ ?assertMatch({ok, Expected}, Result),
+ ok
+ end);
+ensure_notified_when_changed(Module, #ctx{key = Key} = Ctx) ->
?_test(begin
- Key = {test_app, descriptions},
subscribe(Ctx, test_app, Key),
- update(file, Ctx),
+ update(Module, Ctx),
timer:sleep(200),
ExpectedData = lists:usort([
{[complex, key, 1], [{type, counter}, {desc, updated_foo}]},
@@ -208,84 +295,68 @@ ensure_notified_when_changed(file, #ctx{file = File} = Ctx) ->
?assertMatch(
[{[complex, key, 1], [{type, counter}, {desc, foo}]}],
lists:usort(OldData))
- end);
-ensure_notified_when_changed(module, #ctx{file = File} = Ctx) ->
- ?_test(begin
- subscribe(Ctx, test_app, my_service),
- update(module, Ctx),
- timer:sleep(200),
- Result = get(Ctx, is_called),
- Expected = {test_app, my_service,
- {modules, [provider1, provider2]},
- {modules, [provider1, provider2]}},
- ?assertMatch({ok, Expected}, Result),
- ok
end).
-ensure_not_notified_when_no_change(Case, #ctx{} = Ctx) ->
+ensure_not_notified_when_no_change(_Module, #ctx{key = Key} = Ctx) ->
?_test(begin
- Key = {test_app, descriptions},
subscribe(Ctx, test_app, Key),
timer:sleep(200),
?assertMatch(error, get(Ctx, is_called))
end).
-ensure_not_notified_when_unsubscribed(Case, #ctx{file = File} = Ctx) ->
+ensure_not_notified_when_unsubscribed(Module, #ctx{key = Key} = Ctx) ->
?_test(begin
- Key = {test_app, descriptions},
SubscriptionId = subscribe(Ctx, test_app, Key),
couch_epi:unsubscribe(SubscriptionId),
timer:sleep(100),
- update(Case, Ctx),
+ update(Module, Ctx),
timer:sleep(200),
?assertMatch(error, get(Ctx, is_called))
end).
-ensure_apply_is_called(Opts, #ctx{functions_handle = Handle, kv = KV} = Ctx) ->
+ensure_apply_is_called(Opts, #ctx{handle = Handle, kv = KV, key = Key} = Ctx) ->
?_test(begin
- couch_epi:apply(Handle, my_service, inc, [KV, 2], Opts),
+ couch_epi:apply(Handle, Key, inc, [KV, 2], Opts),
maybe_wait(Opts),
?assertMatch({ok, _}, get(Ctx, inc1)),
?assertMatch({ok, _}, get(Ctx, inc2)),
ok
end).
-check_pipe(#ctx{functions_handle = Handle, kv = KV}) ->
+check_pipe(#ctx{handle = Handle, kv = KV, key = Key}) ->
?_test(begin
- Result = couch_epi:apply(Handle, my_service, inc, [KV, 2], [pipe]),
+ Result = couch_epi:apply(Handle, Key, inc, [KV, 2], [pipe]),
?assertMatch([KV, 4], Result),
ok
end).
-check_broken_pipe(#ctx{functions_handle = Handle, kv = KV} = Ctx) ->
+check_broken_pipe(#ctx{handle = Handle, kv = KV, key = Key} = Ctx) ->
?_test(begin
- Result = couch_epi:apply(Handle, my_service, fail, [KV, 2], [pipe, ignore_errors]),
+ Result = couch_epi:apply(Handle, Key, fail, [KV, 2], [pipe, ignore_errors]),
?assertMatch([KV, 3], Result),
?assertMatch([3, check_error], pipe_state(Ctx)),
ok
end).
-ensure_fail_pipe(#ctx{functions_handle = Handle, kv = KV}) ->
+ensure_fail_pipe(#ctx{handle = Handle, kv = KV, key = Key}) ->
?_test(begin
?assertThrow(check_error,
- couch_epi:apply(Handle, my_service, fail, [KV, 2], [pipe])),
+ couch_epi:apply(Handle, Key, fail, [KV, 2], [pipe])),
ok
end).
-ensure_fail(#ctx{functions_handle = Handle, kv = KV}) ->
+ensure_fail(#ctx{handle = Handle, kv = KV, key = Key}) ->
?_test(begin
?assertThrow(check_error,
- couch_epi:apply(Handle, my_service, fail, [KV, 2], [])),
+ couch_epi:apply(Handle, Key, fail, [KV, 2], [])),
ok
end).
-ensure_unsubscribe_when_caller_die(#ctx{} = Ctx) ->
+ensure_unsubscribe_when_caller_die(_Module, #ctx{key = Key} = Ctx) ->
?_test(begin
- Key = {test_app, descriptions},
spawn(fun() ->
subscribe(Ctx, test_app, Key)
end),
- %%update(file, Ctx),
timer:sleep(200),
?assertMatch(error, get(Ctx, is_called))
end).
@@ -295,28 +366,28 @@ pipe_state(Ctx) ->
Trace = [get(Ctx, inc1), get(Ctx, inc2)],
lists:usort([State || {ok, State} <- Trace]).
-check_dump(#ctx{data_handle = Handle}) ->
+check_dump(_Module, #ctx{handle = Handle}) ->
?_test(begin
?assertMatch(
[[{type, counter}, {desc, foo}]],
couch_epi:dump(Handle))
end).
-check_get(#ctx{data_handle = Handle}) ->
+check_get(_Module, #ctx{handle = Handle}) ->
?_test(begin
?assertMatch(
[[{type, counter}, {desc, foo}]],
couch_epi:get(Handle, [complex,key, 1]))
end).
-check_get_value(#ctx{data_handle = Handle}) ->
+check_get_value(_Module, #ctx{handle = Handle}) ->
?_test(begin
?assertMatch(
[{type, counter}, {desc, foo}],
couch_epi:get_value(Handle, test_app, [complex,key, 1]))
end).
-check_by_key(#ctx{data_handle = Handle}) ->
+check_by_key(_Module, #ctx{handle = Handle}) ->
?_test(begin
?assertMatch(
[{[complex, key, 1],
@@ -327,7 +398,7 @@ check_by_key(#ctx{data_handle = Handle}) ->
couch_epi:by_key(Handle, [complex, key, 1]))
end).
-check_by_source(#ctx{data_handle = Handle}) ->
+check_by_source(_Module, #ctx{handle = Handle}) ->
?_test(begin
?assertMatch(
[{test_app,
@@ -338,13 +409,24 @@ check_by_source(#ctx{data_handle = Handle}) ->
couch_epi:by_source(Handle, test_app))
end).
-check_keys(#ctx{data_handle = Handle}) ->
+check_keys(_Module, #ctx{handle = Handle}) ->
?_assertMatch([[complex,key,1]], couch_epi:keys(Handle)).
-check_subscribers(#ctx{data_handle = Handle}) ->
+check_subscribers(_Module, #ctx{handle = Handle}) ->
?_assertMatch([test_app], couch_epi:subscribers(Handle)).
+ensure_reloaded(Module, #ctx{pid = Pid, key = Key} = Ctx) ->
+ ?_test(begin
+ subscribe(Ctx, test_app, Key),
+ update_definitions(Module, Ctx),
+ Module:reload(Pid),
+ timer:sleep(200),
+ Result = get(Ctx, is_called),
+ ?assertNotMatch(error, Result)
+ end).
+
+
%% ------------------------------------------------------------------
%% Internal Function Definitions
%% ------------------------------------------------------------------
@@ -353,11 +435,19 @@ generate_module(Name, Body) ->
Tokens = couch_epi_codegen:scan(Body),
couch_epi_codegen:generate(Name, Tokens).
-update(module, #ctx{}) ->
- ok = generate_module(provider1, ?MODULE2(provider1));
-update(file, #ctx{file = File}) ->
+update(Module, #ctx{pid = Pid} = Ctx) ->
+ update_definitions(Module, Ctx),
+ upgrade_release(Pid, Module).
+
+update_definitions(couch_epi_data_source, #ctx{file = File}) ->
{ok, _} = file:copy(?DATA_FILE2, File),
- ok.
+ ok;
+update_definitions(couch_epi_data, #ctx{}) ->
+ ok = generate_module(provider, ?DATA_MODULE2(provider));
+update_definitions(couch_epi_functions, #ctx{}) ->
+ ok = generate_module(provider1, ?MODULE2(provider1)).
+
+
subscribe(#ctx{kv = Kv}, App, Key) ->
{ok, Pid} = couch_epi:subscribe(App, Key, ?MODULE, notify_cb, Kv),