%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1996-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
%% compliance with the License. You should have received a copy of the
%% Erlang Public License along with this software. If not, it can be
%% retrieved online at http://www.erlang.org/.
%%
%% Software distributed under the License is distributed on an "AS IS"
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% the License for the specific language governing rights and limitations
%% under the License.
%%
%% %CopyrightEnd%
%%
%%
-module(mnesia_nice_coverage_test).
-author('[email protected]').
-compile([export_all]).
-include("mnesia_test_lib.hrl").
-record(nice_tab, {key, val}).
init_per_testcase(Func, Conf) ->
mnesia_test_lib:init_per_testcase(Func, Conf).
end_per_testcase(Func, Conf) ->
mnesia_test_lib:end_per_testcase(Func, Conf).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
all() ->
[nice].
groups() ->
[].
init_per_group(_GroupName, Config) ->
Config.
end_per_group(_GroupName, Config) ->
Config.
nice(doc) -> [""];
nice(suite) -> [];
nice(Config) when is_list(Config) ->
%% The whole test suite is one huge test case for the time beeing
[Node1, Node2] = Nodes = ?acquire_nodes(2, Config),
Attrs = record_info(fields, nice_tab),
initialize(Attrs, Node1),
dirty_access(Node1),
success_and_fail(),
index_mgt(),
adm(Attrs, Node1, Node2),
snmp(Node1, Node2),
backup(Node1),
?verify_mnesia(Nodes, []).
initialize(Attrs, Node1) ->
?match(Version when is_list(Version), mnesia:system_info(version)),
Schema = [{name, nice_tab},
{attributes, Attrs}, {ram_copies, [Node1]}],
?match({_, _}, mnesia:system_info(schema_version)),
?match({atomic, ok}, mnesia:create_table(Schema)),
?match(ok, mnesia:info()),
?match(set, mnesia:table_info(nice_tab, type)),
?match(ok, mnesia:schema()),
?match(ok, mnesia:schema(nice_tab)),
ok.
dirty_access(Node1) ->
TwoThree = #nice_tab{key=23, val=23},
TwoFive = #nice_tab{key=25, val=25},
?match([], mnesia:dirty_slot(nice_tab, 0)),
?match(ok, mnesia:dirty_write(TwoThree)),
?match([TwoThree], mnesia:dirty_read({nice_tab, 23})),
?match(ok, mnesia:dirty_write(TwoFive)),
?match(ok, mnesia:dirty_delete_object(TwoFive)),
?match(23, mnesia:dirty_first(nice_tab)),
?match('$end_of_table', mnesia:dirty_next(nice_tab, 23)),
?match([TwoThree], mnesia:dirty_match_object(TwoThree)),
?match(ok, mnesia:dirty_delete({nice_tab, 23})),
CounterSchema = [{ram_copies, [Node1]}],
?match({atomic, ok}, mnesia:create_table(nice_counter_tab, CounterSchema)),
TwoFour = {nice_counter_tab, 24, 24},
?match(ok, mnesia:dirty_write(TwoFour)),
?match(34, mnesia:dirty_update_counter({nice_counter_tab, 24}, 10)),
TF = {nice_counter_tab, 24, 34},
?match([TF], mnesia:dirty_read({nice_counter_tab, 24})),
?match(ok, mnesia:dirty_delete({nice_counter_tab, 24})),
?match(ok, mnesia:dirty_delete_object(TF)),
ok.
success_and_fail() ->
?match({atomic, a_good_trans}, mnesia:transaction(fun() ->good_trans()end)),
BadFun =
fun() ->
Two = #nice_tab{key=2, val=12},
?match([Two], mnesia:match_object(#nice_tab{key='$1', val=12})),
?match([#nice_tab{key=3, val=13}], mnesia:wread({nice_tab, 3})),
?match(ok, mnesia:delete({nice_tab, 1})),
?match(ok, mnesia:delete_object(Two)),
mnesia:abort(bad_trans),
?match(bad, trans)
end,
?match({aborted, bad_trans}, mnesia:transaction(BadFun)),
?match(L when is_list(L), mnesia:error_description(no_exists)),
?match({atomic, ok}, mnesia:transaction(fun(A) -> lock(), A end, [ok])),
?match({atomic, ok}, mnesia:transaction(fun(A) -> lock(), A end, [ok], 3)),
ok.
good_trans() ->
?match([], mnesia:read(nice_tab, 3)),
?match([], mnesia:read({nice_tab, 3})),
?match(ok, mnesia:write(#nice_tab{key=14, val=4})),
?match([14], mnesia:all_keys(nice_tab)),
Records = [ #nice_tab{key=K, val=K+10} || K <- lists:seq(1, 10) ],
Ok = [ ok || _ <- Records],
?match(Ok, lists:map(fun(R) -> mnesia:write(R) end, Records)),
a_good_trans.
lock() ->
?match(ok, mnesia:s_write(#nice_tab{key=22, val=22})),
?match(ok, mnesia:read_lock_table(nice_tab)),
?match(ok, mnesia:write_lock_table(nice_tab)),
ok.
index_mgt() ->
UniversalRec = #nice_tab{key=4711, val=4711},
?match(ok, mnesia:dirty_write(UniversalRec)),
ValPos = #nice_tab.val,
?match({atomic, ok}, mnesia:add_table_index(nice_tab, ValPos)),
IndexFun =
fun() ->
?match([UniversalRec],
mnesia:index_read(nice_tab, 4711, ValPos)),
Pat = #nice_tab{key='$1', val=4711},
?match([UniversalRec],
mnesia:index_match_object(Pat, ValPos)),
index_trans
end,
?match({atomic, index_trans}, mnesia:transaction(IndexFun, infinity)),
?match([UniversalRec],
mnesia:dirty_index_read(nice_tab, 4711, ValPos)),
?match([UniversalRec],
mnesia:dirty_index_match_object(#nice_tab{key='$1', val=4711}, ValPos)),
?match({atomic, ok}, mnesia:del_table_index(nice_tab, ValPos)),
ok.
adm(Attrs, Node1, Node2) ->
This = node(),
?match({ok, This}, mnesia:subscribe(system)),
?match({atomic, ok},
mnesia:add_table_copy(nice_tab, Node2, disc_only_copies)),
?match({atomic, ok},
mnesia:change_table_copy_type(nice_tab, Node2, ram_copies)),
?match({atomic, ok}, mnesia:del_table_copy(nice_tab, Node1)),
?match(stopped, rpc:call(Node1, mnesia, stop, [])),
?match([], mnesia_test_lib:start_mnesia([Node1, Node2], [nice_tab])),
?match(ok, mnesia:wait_for_tables([schema], infinity)),
Transformer = fun(Rec) ->
list_to_tuple(tuple_to_list(Rec) ++ [initial_value])
end,
?match({atomic, ok},
mnesia:transform_table(nice_tab, Transformer, Attrs ++ [extra])),
?match({atomic, ok}, mnesia:delete_table(nice_tab)),
DumpSchema = [{name, nice_tab}, {attributes, Attrs}, {ram_copies, [Node2]}],
?match({atomic, ok}, mnesia:create_table(DumpSchema)),
?match({atomic, ok}, mnesia:dump_tables([nice_tab])),
?match({atomic, ok}, mnesia:move_table_copy(nice_tab, Node2, Node1)),
?match(yes, mnesia:force_load_table(nice_counter_tab)),
?match(ok, mnesia:sync_log()),
?match(dumped, mnesia:dump_log()),
ok.
backup(Node1) ->
Tab = backup_nice,
Def = [{disc_copies, [Node1]}],
?match({atomic, ok}, mnesia:create_table(Tab, Def)),
?match({ok,_,_}, mnesia:activate_checkpoint([{name, cp}, {max, [Tab]}])),
File = "nice_backup.BUP",
File2 = "nice_backup2.BUP",
File3 = "nice_backup3.BUP",
?match(ok, mnesia:backup_checkpoint(cp, File)),
?match(ok, mnesia:backup_checkpoint(cp, File, mnesia_backup)),
?match(ok, mnesia:deactivate_checkpoint(cp)),
?match(ok, mnesia:backup(File)),
?match(ok, mnesia:backup(File, mnesia_backup)),
Fun = fun(X, Acc) -> {[X], Acc} end,
?match({ok, 0}, mnesia:traverse_backup(File, File2, Fun, 0)),
?match({ok, 0}, mnesia:traverse_backup(File, mnesia_backup, dummy, read_only, Fun, 0)),
?match(ok, mnesia:install_fallback(File)),
?match(ok, mnesia:uninstall_fallback()),
?match(ok, mnesia:install_fallback(File, mnesia_backup)),
?match(ok, mnesia:dump_to_textfile(File3)),
?match({atomic, ok}, mnesia:load_textfile(File3)),
?match(ok, file:delete(File)),
?match(ok, file:delete(File2)),
?match(ok, file:delete(File3)),
ok.
snmp(Node1, Node2) ->
Tab = nice_snmp,
Def = [{disc_copies, [Node1]}, {ram_copies, [Node2]}],
?match({atomic, ok}, mnesia:create_table(Tab, Def)),
?match({aborted, {badarg, Tab, _}}, mnesia:snmp_open_table(Tab, [])),
?match({atomic, ok}, mnesia:snmp_open_table(Tab, [{key, integer}])),
?match(endOfTable, mnesia:snmp_get_next_index(Tab, [0])),
?match(undefined, mnesia:snmp_get_row(Tab, [0])),
?match(undefined, mnesia:snmp_get_mnesia_key(Tab, [0])),
?match({atomic, ok}, mnesia:snmp_close_table(Tab)),
ok.