1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 1996-2010. All Rights Reserved.
    5: %%
    6: %% The contents of this file are subject to the Erlang Public License,
    7: %% Version 1.1, (the "License"); you may not use this file except in
    8: %% compliance with the License. You should have received a copy of the
    9: %% Erlang Public License along with this software. If not, it can be
   10: %% retrieved online at http://www.erlang.org/.
   11: %%
   12: %% Software distributed under the License is distributed on an "AS IS"
   13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
   14: %% the License for the specific language governing rights and limitations
   15: %% under the License.
   16: %%
   17: %% %CopyrightEnd%
   18: %%
   19: 
   20: %%
   21: -module(mnesia_nice_coverage_test).
   22: -author('hakan@erix.ericsson.se').
   23: -compile([export_all]).
   24: -include("mnesia_test_lib.hrl").
   25: 
   26: -record(nice_tab, {key, val}).
   27: 
   28: init_per_testcase(Func, Conf) ->
   29:     mnesia_test_lib:init_per_testcase(Func, Conf).
   30: 
   31: end_per_testcase(Func, Conf) ->
   32:     mnesia_test_lib:end_per_testcase(Func, Conf).
   33: 
   34: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   35: all() -> 
   36:     [nice].
   37: 
   38: groups() -> 
   39:     [].
   40: 
   41: init_per_group(_GroupName, Config) ->
   42:     Config.
   43: 
   44: end_per_group(_GroupName, Config) ->
   45:     Config.
   46: 
   47: 
   48: nice(doc) -> [""];
   49: nice(suite) -> [];
   50: nice(Config) when is_list(Config) ->
   51:     %% The whole test suite is one huge test case for the time beeing
   52:     
   53:     [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 
   54:     Attrs = record_info(fields, nice_tab), 
   55:     
   56:     initialize(Attrs, Node1), 
   57:     dirty_access(Node1), 
   58:     success_and_fail(), 
   59:     index_mgt(), 
   60:     
   61:     adm(Attrs, Node1, Node2), 
   62:     snmp(Node1, Node2), 
   63:     backup(Node1), 
   64:     ?verify_mnesia(Nodes, []).
   65: 
   66: initialize(Attrs, Node1) ->
   67:     ?match(Version when is_list(Version), mnesia:system_info(version)), 
   68: 
   69:     Schema = [{name, nice_tab}, 
   70: 	      {attributes, Attrs}, {ram_copies, [Node1]}], 
   71: 
   72:     ?match({_, _}, mnesia:system_info(schema_version)), 
   73:     ?match({atomic, ok}, mnesia:create_table(Schema)), 
   74: 
   75:     ?match(ok, mnesia:info()), 
   76:     ?match(set, mnesia:table_info(nice_tab, type)), 
   77:     ?match(ok, mnesia:schema()), 
   78:     ?match(ok, mnesia:schema(nice_tab)),
   79:     ok.
   80: 
   81: dirty_access(Node1) ->
   82:     TwoThree = #nice_tab{key=23, val=23}, 
   83:     TwoFive  = #nice_tab{key=25, val=25}, 
   84:     ?match([], mnesia:dirty_slot(nice_tab, 0)), 
   85:     ?match(ok, mnesia:dirty_write(TwoThree)), 
   86:     ?match([TwoThree], mnesia:dirty_read({nice_tab, 23})), 
   87:     ?match(ok, mnesia:dirty_write(TwoFive)), 
   88:     ?match(ok, mnesia:dirty_delete_object(TwoFive)), 
   89: 
   90:     ?match(23, mnesia:dirty_first(nice_tab)), 
   91:     ?match('$end_of_table', mnesia:dirty_next(nice_tab, 23)), 
   92:     ?match([TwoThree], mnesia:dirty_match_object(TwoThree)), 
   93:     ?match(ok, mnesia:dirty_delete({nice_tab, 23})), 
   94: 
   95:     CounterSchema = [{ram_copies, [Node1]}], 
   96:     ?match({atomic, ok}, mnesia:create_table(nice_counter_tab, CounterSchema)), 
   97:     TwoFour  = {nice_counter_tab, 24, 24}, 
   98:     ?match(ok, mnesia:dirty_write(TwoFour)), 
   99:     ?match(34, mnesia:dirty_update_counter({nice_counter_tab, 24}, 10)), 
  100:     TF = {nice_counter_tab, 24, 34}, 
  101:     ?match([TF], mnesia:dirty_read({nice_counter_tab, 24})), 
  102:     ?match(ok, mnesia:dirty_delete({nice_counter_tab, 24})), 
  103:     ?match(ok, mnesia:dirty_delete_object(TF)),
  104:     ok.
  105: 
  106: success_and_fail() ->
  107:     ?match({atomic, a_good_trans}, mnesia:transaction(fun() ->good_trans()end)), 
  108: 
  109:     BadFun =
  110: 	fun() ->
  111: 		Two = #nice_tab{key=2, val=12}, 
  112: 		?match([Two], mnesia:match_object(#nice_tab{key='$1', val=12})), 
  113: 		?match([#nice_tab{key=3, val=13}], mnesia:wread({nice_tab, 3})), 
  114: 		?match(ok, mnesia:delete({nice_tab, 1})), 
  115: 		?match(ok, mnesia:delete_object(Two)), 
  116: 		mnesia:abort(bad_trans), 
  117: 		?match(bad, trans)
  118: 	end, 
  119:     ?match({aborted, bad_trans}, mnesia:transaction(BadFun)), 
  120:     ?match(L when is_list(L), mnesia:error_description(no_exists)), 
  121:     ?match({atomic, ok}, mnesia:transaction(fun(A) -> lock(), A end, [ok])), 
  122:     ?match({atomic, ok}, mnesia:transaction(fun(A) -> lock(), A end, [ok], 3)),
  123:     ok.
  124: 
  125: good_trans() ->
  126:     ?match([], mnesia:read(nice_tab, 3)), 
  127:     ?match([], mnesia:read({nice_tab, 3})), 
  128:     ?match(ok, mnesia:write(#nice_tab{key=14, val=4})), 
  129:     ?match([14], mnesia:all_keys(nice_tab)), 
  130: 
  131:     Records = [ #nice_tab{key=K, val=K+10} || K <- lists:seq(1, 10) ], 
  132:     Ok = [ ok || _ <- Records], 
  133:     ?match(Ok, lists:map(fun(R) -> mnesia:write(R) end, Records)), 
  134:     a_good_trans.
  135: 
  136: 
  137: lock() ->
  138:     ?match(ok, mnesia:s_write(#nice_tab{key=22, val=22})), 
  139:     ?match(ok, mnesia:read_lock_table(nice_tab)), 
  140:     ?match(ok, mnesia:write_lock_table(nice_tab)),
  141:     ok.
  142: 
  143: index_mgt() ->
  144:     UniversalRec = #nice_tab{key=4711, val=4711}, 
  145:     ?match(ok, mnesia:dirty_write(UniversalRec)), 
  146:     ValPos = #nice_tab.val, 
  147:     ?match({atomic, ok}, mnesia:add_table_index(nice_tab, ValPos)), 
  148: 
  149:     IndexFun =
  150: 	fun() ->
  151: 		?match([UniversalRec], 
  152: 		       mnesia:index_read(nice_tab, 4711, ValPos)), 
  153: 		Pat = #nice_tab{key='$1', val=4711}, 
  154: 		?match([UniversalRec], 
  155: 		       mnesia:index_match_object(Pat, ValPos)), 
  156: 		index_trans
  157: 	end, 
  158:     ?match({atomic, index_trans}, mnesia:transaction(IndexFun, infinity)), 
  159:     ?match([UniversalRec], 
  160: 	   mnesia:dirty_index_read(nice_tab, 4711, ValPos)), 
  161:     ?match([UniversalRec], 
  162: 	   mnesia:dirty_index_match_object(#nice_tab{key='$1', val=4711}, ValPos)), 
  163: 
  164:     ?match({atomic, ok}, mnesia:del_table_index(nice_tab, ValPos)),
  165:     ok.
  166: 
  167: adm(Attrs, Node1, Node2) ->
  168:     This = node(), 
  169:     ?match({ok, This}, mnesia:subscribe(system)), 
  170:     ?match({atomic, ok}, 
  171: 	   mnesia:add_table_copy(nice_tab, Node2, disc_only_copies)), 
  172:     ?match({atomic, ok}, 
  173: 	   mnesia:change_table_copy_type(nice_tab, Node2, ram_copies)), 
  174:     ?match({atomic, ok}, mnesia:del_table_copy(nice_tab, Node1)), 
  175:     ?match(stopped, rpc:call(Node1, mnesia, stop, [])), 
  176:     ?match([], mnesia_test_lib:start_mnesia([Node1, Node2], [nice_tab])), 
  177:     ?match(ok, mnesia:wait_for_tables([schema], infinity)), 
  178: 
  179:     Transformer = fun(Rec) ->
  180: 			  list_to_tuple(tuple_to_list(Rec) ++ [initial_value])
  181: 		  end, 
  182:     ?match({atomic, ok}, 
  183: 	   mnesia:transform_table(nice_tab, Transformer, Attrs ++ [extra])), 
  184: 
  185:     ?match({atomic, ok}, mnesia:delete_table(nice_tab)), 
  186:     DumpSchema = [{name, nice_tab}, {attributes, Attrs}, {ram_copies, [Node2]}], 
  187:     ?match({atomic, ok}, mnesia:create_table(DumpSchema)), 
  188:     ?match({atomic, ok}, mnesia:dump_tables([nice_tab])), 
  189:     ?match({atomic, ok}, mnesia:move_table_copy(nice_tab, Node2, Node1)), 
  190: 
  191:     ?match(yes, mnesia:force_load_table(nice_counter_tab)), 
  192:     ?match(dumped, mnesia:dump_log()),
  193:     ok.
  194: 
  195: backup(Node1) ->
  196:     Tab = backup_nice,
  197:     Def = [{disc_copies, [Node1]}], 
  198:     ?match({atomic, ok}, mnesia:create_table(Tab, Def)),    
  199:     ?match({ok,_,_}, mnesia:activate_checkpoint([{name, cp}, {max, [Tab]}])), 
  200:     File = "nice_backup.BUP",
  201:     File2 = "nice_backup2.BUP",
  202:     File3 = "nice_backup3.BUP",
  203:     ?match(ok, mnesia:backup_checkpoint(cp, File)), 
  204:     ?match(ok, mnesia:backup_checkpoint(cp, File, mnesia_backup)), 
  205:     ?match(ok, mnesia:deactivate_checkpoint(cp)), 
  206:     ?match(ok, mnesia:backup(File)), 
  207:     ?match(ok, mnesia:backup(File, mnesia_backup)), 
  208: 
  209:     Fun = fun(X, Acc) -> {[X], Acc} end,
  210:     ?match({ok, 0}, mnesia:traverse_backup(File, File2, Fun, 0)), 
  211:     ?match({ok, 0}, mnesia:traverse_backup(File, mnesia_backup, dummy, read_only, Fun, 0)), 
  212:     ?match(ok, mnesia:install_fallback(File)), 
  213:     ?match(ok, mnesia:uninstall_fallback()), 
  214:     ?match(ok, mnesia:install_fallback(File, mnesia_backup)), 
  215:     ?match(ok, mnesia:dump_to_textfile(File3)), 
  216:     ?match({atomic, ok}, mnesia:load_textfile(File3)),
  217:     ?match(ok, file:delete(File)),
  218:     ?match(ok, file:delete(File2)),
  219:     ?match(ok, file:delete(File3)),
  220:     ok.
  221: 
  222: snmp(Node1, Node2) ->
  223:     Tab = nice_snmp, 
  224:     Def = [{disc_copies, [Node1]}, {ram_copies, [Node2]}], 
  225:     ?match({atomic, ok}, mnesia:create_table(Tab, Def)),
  226:     ?match({aborted, {badarg, Tab, _}}, mnesia:snmp_open_table(Tab, [])),
  227:     ?match({atomic, ok}, mnesia:snmp_open_table(Tab, [{key, integer}])),
  228:     ?match(endOfTable, mnesia:snmp_get_next_index(Tab, [0])), 
  229:     ?match(undefined, mnesia:snmp_get_row(Tab, [0])), 
  230:     ?match(undefined, mnesia:snmp_get_mnesia_key(Tab, [0])), 
  231:     ?match({atomic, ok}, mnesia:snmp_close_table(Tab)),
  232:     ok.
  233: