aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mnesia/test/mnesia_evil_coverage_test.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mnesia/test/mnesia_evil_coverage_test.erl')
-rw-r--r--lib/mnesia/test/mnesia_evil_coverage_test.erl234
1 files changed, 234 insertions, 0 deletions
diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl
index 06674d9eef..4fbf1b4003 100644
--- a/lib/mnesia/test/mnesia_evil_coverage_test.erl
+++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl
@@ -61,6 +61,7 @@ all(suite) ->
unsupp_user_props,
record_name,
snmp_access,
+ subscriptions,
iteration,
debug_support,
sorted_ets,
@@ -1775,6 +1776,239 @@ get_keys(Tab, Key) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+-record(tab, {i, e1, e2}). % Simple test table
+
+subscriptions(doc) ->
+ ["Test the event subscription mechanism"];
+subscriptions(suite) ->
+ [subscribe_standard,
+ subscribe_extended].
+
+subscribe_extended(doc) ->
+ ["Test the extended set of events, test with and without checkpoints. "];
+subscribe_extended(suite) ->
+ [];
+subscribe_extended(Config) when is_list(Config) ->
+ [N1, N2]=Nodes=?acquire_nodes(2, Config),
+ Tab1 = etab,
+ Storage = mnesia_test_lib:storage_type(ram_copies, Config),
+ Def1 = [{Storage, [N1, N2]}, {attributes, record_info(fields, tab)}],
+ ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)),
+
+ Tab2 = bag,
+ Def2 = [{Storage, [N1, N2]},
+ {type, bag},
+ {record_name, Tab1},
+ {attributes, record_info(fields, tab)}],
+ ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)),
+
+ ?match({ok, N1}, mnesia:subscribe({table, Tab1, detailed})),
+ ?match({ok, N1}, mnesia:subscribe({table, Tab2, detailed})),
+
+ ?match({error, {already_exists, _}}, mnesia:subscribe({table, Tab1, simple})),
+ ?match({error, {badarg, {table, Tab1, bad}}}, mnesia:subscribe({table, Tab1, bad})),
+
+ ?match({ok, N1}, mnesia:subscribe(activity)),
+ test_ext_sub(Tab1, Tab2),
+
+ ?match({ok, N1}, mnesia:unsubscribe(activity)),
+ ?match({ok, N1}, mnesia:subscribe({table, Tab1, detailed})),
+ ?match({atomic, ok}, mnesia:clear_table(Tab1)),
+ ?match({mnesia_table_event, {delete, schema, {schema, Tab1}, [{schema, Tab1, _}],_}}, recv_event()),
+ ?match({mnesia_table_event, {write, schema, {schema, Tab1, _}, [], _}}, recv_event()),
+
+ ?match({atomic, ok}, mnesia_schema:clear_table(Tab2)),
+ ?match({mnesia_table_event, {delete, schema, {schema, Tab2}, [{schema, Tab2, _}],_}},
+ recv_event()),
+ ?match({mnesia_table_event, {write, schema, {schema, Tab2, _}, [], _}}, recv_event()),
+
+ ?match({ok, N1}, mnesia:unsubscribe({table, Tab2, detailed})),
+ {ok, _, _} = mnesia:activate_checkpoint([{name, testing},
+ {ram_overrides_dump, true},
+ {max, [Tab1, Tab2]}]),
+ ?match({ok, N1}, mnesia:subscribe({table, Tab2, detailed})),
+ ?match({ok, N1}, mnesia:subscribe(activity)),
+ test_ext_sub(Tab1, Tab2),
+
+ ?verify_mnesia(Nodes, []).
+
+test_ext_sub(Tab1, Tab2) ->
+ %% The basics
+ Rec1 = {Tab1, 1, 0, 0},
+ Rec2 = {Tab1, 1, 1, 0},
+ Rec3 = {Tab1, 2, 1, 0},
+ Rec4 = {Tab1, 2, 2, 0},
+
+ Write = fun(Tab, Rec) ->
+ mnesia:transaction(fun() -> mnesia:write(Tab, Rec, write)
+ end)
+ end,
+ Delete = fun(Tab, Rec) ->
+ mnesia:transaction(fun() -> mnesia:delete(Tab, Rec, write)
+ end)
+ end,
+ DelObj = fun(Tab, Rec) ->
+ mnesia:transaction(fun() -> mnesia:delete_object(Tab, Rec, write)
+ end)
+ end,
+
+ S = self(),
+ D = {dirty, self()},
+ %% SET
+ ?match(ok, mnesia:dirty_write(Rec1)),
+ ?match({mnesia_table_event, {write, Tab1, Rec1, [], D}}, recv_event()),
+ ?match(ok, mnesia:dirty_write(Rec3)),
+ ?match({mnesia_table_event, {write, Tab1, Rec3, [], D}}, recv_event()),
+ ?match(ok, mnesia:dirty_write(Rec1)),
+ ?match({mnesia_table_event, {write, Tab1, Rec1, [Rec1], D}}, recv_event()),
+ ?match({atomic, ok}, Write(Tab1, Rec2)),
+ ?match({mnesia_table_event, {write, Tab1, Rec2, [Rec1], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ?match(ok, mnesia:dirty_delete({Tab1, 2})),
+ ?match({mnesia_table_event, {delete, Tab1, {Tab1, 2}, [Rec3], D}}, recv_event()),
+ ?match({atomic, ok}, DelObj(Tab1, Rec2)),
+ ?match({mnesia_table_event, {delete, Tab1, Rec2, [Rec2], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+
+ ?match({atomic, ok}, Delete(Tab1, 1)),
+ ?match({mnesia_table_event, {delete, Tab1, {Tab1, 1}, [], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+
+ ?match({ok, _N1}, mnesia:unsubscribe({table, Tab1, detailed})),
+
+ %% BAG
+
+ ?match({atomic, ok}, Write(Tab2, Rec1)),
+ ?match({mnesia_table_event, {write, Tab2, Rec1, [], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ?match({atomic, ok}, Write(Tab2, Rec4)),
+ ?match({mnesia_table_event, {write, Tab2, Rec4, [], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ?match({atomic, ok}, Write(Tab2, Rec3)),
+ ?match({mnesia_table_event, {write, Tab2, Rec3, [Rec4], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ?match({atomic, ok}, Write(Tab2, Rec2)),
+ ?match({mnesia_table_event, {write, Tab2, Rec2, [Rec1], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ?match({atomic, ok}, Write(Tab2, Rec1)),
+ ?match({mnesia_table_event, {write, Tab2, Rec1, [Rec1, Rec2], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ?match({atomic, ok}, DelObj(Tab2, Rec2)),
+ ?match({mnesia_table_event, {delete, Tab2, Rec2, [Rec2], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ?match({atomic, ok}, Delete(Tab2, 1)),
+ ?match({mnesia_table_event, {delete, Tab2, {Tab2, 1}, [Rec1], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ?match({atomic, ok}, Delete(Tab2, 2)),
+ ?match({mnesia_table_event, {delete, Tab2, {Tab2, 2}, [Rec4, Rec3], {tid,_,S}}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()),
+ ok.
+
+
+subscribe_standard(doc) ->
+ ["Tests system events and the orignal table events"];
+subscribe_standard(suite) -> [];
+subscribe_standard(Config) when is_list(Config)->
+ [N1, N2]=?acquire_nodes(2, Config),
+ Tab = tab,
+
+ Storage = mnesia_test_lib:storage_type(disc_copies, Config),
+ Def = [{Storage, [N1, N2]}, {attributes, record_info(fields, tab)}],
+
+ ?match({atomic, ok}, mnesia:create_table(Tab, Def)),
+
+ %% Check system events
+ ?match({ok, N1}, mnesia:subscribe(system)),
+ ?match({ok, N1}, mnesia:subscribe(activity)),
+
+ ?match([], mnesia_test_lib:kill_mnesia([N2])),
+ ?match({mnesia_system_event, {mnesia_down, N2}}, recv_event()),
+ ?match(timeout, recv_event()),
+
+ ?match([], mnesia_test_lib:start_mnesia([N2], [Tab])),
+ ?match({mnesia_activity_event, _}, recv_event()),
+ ?match({mnesia_system_event,{mnesia_up, N2}}, recv_event()),
+
+ ?match(true, lists:member(self(), mnesia:system_info(subscribers))),
+ ?match([], mnesia_test_lib:kill_mnesia([N1])),
+ timer:sleep(500),
+ mnesia_test_lib:flush(),
+ ?match([], mnesia_test_lib:start_mnesia([N1], [Tab])),
+ ?match(timeout, recv_event()),
+
+ ?match({ok, N1}, mnesia:subscribe(system)),
+ ?match({error, {already_exists, system}}, mnesia:subscribe(system)),
+ ?match(stopped, mnesia:stop()),
+ ?match({mnesia_system_event, {mnesia_down, N1}}, recv_event()),
+ ?match({error, {node_not_running, N1}}, mnesia:subscribe(system)),
+ ?match([], mnesia_test_lib:start_mnesia([N1, N2], [Tab])),
+
+ %% Check table events
+ ?match({ok, N1}, mnesia:subscribe(activity)),
+ Old_Level = mnesia:set_debug_level(trace),
+ ?match({ok, N1}, mnesia:subscribe({table,Tab})),
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(#tab{i=155}) end)),
+ Self = self(),
+ ?match({mnesia_table_event, {write, _, _}}, recv_event()),
+ ?match({mnesia_activity_event, {complete, {tid, _, Self}}}, recv_event()),
+
+ ?match({ok, N1}, mnesia:unsubscribe({table,Tab})),
+ ?match({ok, N1}, mnesia:unsubscribe(activity)),
+
+ ?match({atomic, ok},
+ mnesia:transaction(fun() -> mnesia:write(#tab{i=255}) end)),
+
+ ?match(timeout, recv_event()),
+ mnesia:set_debug_level(Old_Level),
+
+ %% Check deletion of replica
+
+ ?match({ok, N1}, mnesia:subscribe({table,Tab})),
+ ?match({ok, N1}, mnesia:subscribe(activity)),
+ ?match(ok, mnesia:dirty_write(#tab{i=355})),
+ ?match({mnesia_table_event, {write, _, _}}, recv_event()),
+ ?match({atomic, ok}, mnesia:del_table_copy(Tab, N1)),
+ ?match({mnesia_activity_event, _}, recv_event()),
+ ?match(ok, mnesia:dirty_write(#tab{i=455})),
+ ?match(timeout, recv_event()),
+
+ ?match({atomic, ok}, mnesia:move_table_copy(Tab, N2, N1)),
+ ?match({mnesia_activity_event, _}, recv_event()),
+ ?match({ok, N1}, mnesia:subscribe({table,Tab})),
+ ?match(ok, mnesia:dirty_write(#tab{i=555})),
+ ?match({mnesia_table_event, {write, _, _}}, recv_event()),
+ ?match({atomic, ok}, mnesia:move_table_copy(Tab, N1, N2)),
+ ?match({mnesia_activity_event, _}, recv_event()),
+ ?match(ok, mnesia:dirty_write(#tab{i=655})),
+ ?match(timeout, recv_event()),
+
+ ?match({atomic, ok}, mnesia:add_table_copy(Tab, N1, ram_copies)),
+ ?match({mnesia_activity_event, _}, recv_event()),
+ ?match({ok, N1}, mnesia:subscribe({table,Tab})),
+ ?match({error, {already_exists, {table,Tab, simple}}},
+ mnesia:subscribe({table,Tab})),
+ ?match(ok, mnesia:dirty_write(#tab{i=755})),
+ ?match({mnesia_table_event, {write, _, _}}, recv_event()),
+
+ ?match({atomic, ok}, mnesia:delete_table(Tab)),
+ ?match({mnesia_activity_event, _}, recv_event()),
+ ?match(timeout, recv_event()),
+
+ mnesia_test_lib:kill_mnesia([N1]),
+
+ ?verify_mnesia([N2], [N1]).
+
+recv_event() ->
+ receive
+ Event -> Event
+ after 1000 ->
+ timeout
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
iteration(doc) ->
["Verify that the iteration functions works as expected"];
iteration(suite) ->