1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 1996-2013. 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_evil_coverage_test). 22: -author('hakan@erix.ericsson.se'). 23: -include("mnesia_test_lib.hrl"). 24: 25: -compile([export_all]). 26: 27: -define(cleanup(N, Config), 28: mnesia_test_lib:prepare_test_case([{reload_appls, [mnesia]}], 29: N, Config, ?FILE, ?LINE)). 30: init_per_testcase(Func, Conf) -> 31: mnesia_test_lib:init_per_testcase(Func, Conf). 32: 33: end_per_testcase(Func, Conf) -> 34: mnesia_test_lib:end_per_testcase(Func, Conf). 35: 36: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37: all() -> 38: [system_info, table_info, error_description, 39: db_node_lifecycle, evil_delete_db_node, start_and_stop, 40: checkpoint, table_lifecycle, storage_options, 41: add_copy_conflict, 42: add_copy_when_going_down, replica_management, clear_table_during_load, 43: schema_availability, local_content, 44: {group, table_access_modifications}, replica_location, 45: {group, table_sync}, user_properties, unsupp_user_props, 46: {group, record_name}, {group, snmp_access}, 47: {group, subscriptions}, {group, iteration}, 48: {group, debug_support}, sorted_ets, 49: {mnesia_dirty_access_test, all}, 50: {mnesia_trans_access_test, all}, 51: {mnesia_evil_backup, all}]. 52: 53: groups() -> 54: [{table_access_modifications, [], 55: [change_table_access_mode, change_table_load_order, 56: set_master_nodes, offline_set_master_nodes]}, 57: {table_sync, [], 58: [dump_tables, dump_log, wait_for_tables, 59: force_load_table]}, 60: {snmp_access, [], 61: [snmp_open_table, snmp_close_table, snmp_get_next_index, 62: snmp_get_row, snmp_get_mnesia_key, snmp_update_counter, 63: snmp_order]}, 64: {subscriptions, [], 65: [subscribe_standard, subscribe_extended]}, 66: {iteration, [], [foldl]}, 67: {debug_support, [], 68: [info, schema_0, schema_1, view_0, view_1, view_2, 69: lkill, kill]}, 70: {record_name, [], [{group, record_name_dirty_access}]}, 71: {record_name_dirty_access, [], 72: [record_name_dirty_access_ram, 73: record_name_dirty_access_disc, 74: record_name_dirty_access_disc_only]}]. 75: 76: init_per_group(_GroupName, Config) -> 77: Config. 78: 79: end_per_group(_GroupName, Config) -> 80: Config. 81: 82: 83: 84: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 85: %% Get meta info about Mnesia 86: 87: system_info(suite) -> []; 88: system_info(Config) when is_list(Config) -> 89: Nodes = ?acquire_nodes(all, Config), 90: Ns = ?sort(Nodes), 91: ?match(yes, mnesia:system_info(is_running)), 92: ?match(Ns, ?sort(mnesia:system_info(db_nodes))), 93: ?match(Ns, ?sort(mnesia:system_info(running_db_nodes))), 94: ?match(A when is_atom(A), mnesia:system_info(debug)), 95: ?match(L when is_list(L), mnesia:system_info(directory)), 96: ?match(L when is_list(L), mnesia:system_info(log_version)), 97: ?match({_, _}, mnesia:system_info(schema_version)), 98: ?match(L when is_list(L), mnesia:system_info(tables)), 99: ?match(L when is_list(L), mnesia:system_info(local_tables)), 100: ?match(L when is_list(L), mnesia:system_info(held_locks)), 101: ?match(L when is_list(L), mnesia:system_info(lock_queue)), 102: ?match(L when is_list(L), mnesia:system_info(transactions)), 103: ?match(I when is_integer(I), mnesia:system_info(transaction_failures)), 104: ?match(I when is_integer(I), mnesia:system_info(transaction_commits)), 105: ?match(I when is_integer(I), mnesia:system_info(transaction_restarts)), 106: ?match(L when is_list(L), mnesia:system_info(checkpoints)), 107: ?match(A when is_atom(A), mnesia:system_info(backup_module)), 108: ?match(true, mnesia:system_info(auto_repair)), 109: ?match({_, _}, mnesia:system_info(dump_log_interval)), 110: ?match(A when is_atom(A), mnesia:system_info(dump_log_update_in_place)), 111: ?match(I when is_integer(I), mnesia:system_info(transaction_log_writes)), 112: ?match(I when is_integer(I), mnesia:system_info(send_compressed)), 113: ?match(L when is_list(L), mnesia:system_info(all)), 114: ?match({'EXIT', {aborted, Reason }} when element(1, Reason) == badarg 115: , mnesia:system_info(ali_baba)), 116: ?verify_mnesia(Nodes, []). 117: 118: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 119: %% Get meta info about table 120: 121: table_info(suite) -> []; 122: table_info(Config) when is_list(Config) -> 123: [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), 124: 125: Tab = table_info, 126: Type = bag, 127: ValPos = 3, 128: Attrs = [k, v], 129: Arity = length(Attrs) +1, 130: 131: Schema = 132: case mnesia_test_lib:diskless(Config) of 133: true -> [{type, Type}, {attributes, Attrs}, {index, [ValPos]}, 134: {ram_copies, Nodes}]; 135: false -> 136: [{type, Type}, {attributes, Attrs}, {index, [ValPos]}, 137: {disc_only_copies, [Node1]}, {ram_copies, [Node2]}, 138: {disc_copies, [Node3]}] 139: end, 140: ?match({atomic, ok}, mnesia:create_table(Tab, Schema)), 141: 142: Size = 10, 143: Keys = lists:seq(1, Size), 144: Records = [{Tab, A, 7} || A <- Keys], 145: lists:foreach(fun(Rec) -> ?match(ok, mnesia:dirty_write(Rec)) end, Records), 146: ?match(Mem when is_integer(Mem), mnesia:table_info(Tab, memory)), 147: ?match(Size, mnesia:table_info(Tab, size)), 148: ?match(Type, mnesia:table_info(Tab, type)), 149: 150: case mnesia_test_lib:diskless(Config) of 151: true -> 152: ?match(Nodes, mnesia:table_info(Tab, ram_copies)); 153: false -> 154: ?match([Node3], mnesia:table_info(Tab, mnesia_test_lib:storage_type(disc_copies, Config))), 155: ?match([Node2], mnesia:table_info(Tab, ram_copies)), 156: ?match([Node1], mnesia:table_info(Tab, mnesia_test_lib:storage_type(disc_only_copies, Config))) 157: end, 158: Read = [Node1, Node2, Node3], 159: ?match(true, lists:member(mnesia:table_info(Tab, where_to_read), Read)), 160: Write = ?sort([Node1, Node2, Node3]), 161: ?match(Write, ?sort(mnesia:table_info(Tab, where_to_write))), 162: ?match([ValPos], mnesia:table_info(Tab, index)), 163: ?match(Arity, mnesia:table_info(Tab, arity)), 164: ?match(Attrs, mnesia:table_info(Tab, attributes)), 165: ?match({Tab, '_', '_'}, mnesia:table_info(Tab, wild_pattern)), 166: ?match({atomic, Attrs}, mnesia:transaction(fun() -> 167: mnesia:table_info(Tab, attributes) end)), 168: 169: ?match(L when is_list(L), mnesia:table_info(Tab, all)), 170: 171: %% Table info when table not loaded 172: ?match({atomic, ok}, 173: mnesia:create_table(tab_info, Schema)), 174: ?match(stopped, mnesia:stop()), 175: ?match(stopped, rpc:call(Node2, mnesia, stop, [])), 176: ?match(ok, mnesia:start()), 177: ?match(ok, mnesia:wait_for_tables([tab_info], 5000)), 178: ?match(0, mnesia:table_info(tab_info, size)), 179: ?verify_mnesia([Node1, Node3], [Node2]). 180: 181: 182: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 183: %% Check the error descriptions 184: 185: error_description(suite) -> []; 186: error_description(Config) when is_list(Config) -> 187: ?acquire_nodes(1, Config), 188: Errors = [nested_transaction, badarg, no_transaction, combine_error, 189: bad_index, already_exists, index_exists, no_exists, system_limit, 190: mnesia_down, not_a_db_node, bad_type, node_not_running, 191: truncated_binary_file, active, illegal 192: ], 193: ?match(X when is_atom(X), mnesia:error_description({error, bad_error_msg})), 194: ?match(X when is_tuple(X), mnesia:error_description({'EXIT', pid, bad})), 195: %% This is real error msg 196: ?match(X when is_tuple(X), mnesia:error_description( 197: {error, 198: {"Cannot prepare checkpoint (bad reply)", 199: {{877,957351,758147},a@legolas}, 200: {error,{node_not_running,a1@legolas}}}})), 201: check_errors(error, Errors), 202: check_errors(aborted, Errors), 203: check_errors('EXIT', Errors). 204: 205: check_errors(_Err, []) -> ok; 206: check_errors(Err, [Desc|R]) -> 207: ?match(X when is_list(X), mnesia:error_description({Err, Desc})), 208: check_errors(Err, R). 209: 210: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 211: %% Add and drop db nodes 212: 213: db_node_lifecycle(suite) -> []; 214: db_node_lifecycle(Config) when is_list(Config) -> 215: [Node1, Node2, Node3] = AllNodes = ?acquire_nodes(3, Config), 216: Tab = db_node_lifecycle, 217: 218: Who = fun(T) -> 219: L1 = mnesia:table_info(T, ram_copies), 220: L2 = mnesia:table_info(T, disc_copies), 221: L3 = mnesia:table_info(T, disc_only_copies), 222: L1 ++ L2 ++ L3 223: end, 224: 225: SNs = ?sort(AllNodes), 226: 227: Schema = [{name, Tab}, {ram_copies, [Node1, Node2]}], 228: ?match({atomic, ok}, mnesia:create_table(Schema)), 229: 230: ?match([], mnesia_test_lib:stop_mnesia(AllNodes)), 231: ?match(ok, mnesia:delete_schema(AllNodes)), 232: ?match({error, _}, mnesia:create_schema(foo)), 233: ?match({error, _}, mnesia:create_schema([foo])), 234: ?match({error, _}, mnesia:create_schema([foo@bar])), 235: ?match(ok, mnesia:start()), 236: ?match(false, mnesia:system_info(use_dir)), 237: ?match({atomic, ok}, mnesia:create_table(Tab, [])), 238: ?match({aborted, {has_no_disc, Node1}}, mnesia:dump_tables([Tab])), 239: ?match({aborted, {has_no_disc, Node1}}, mnesia:change_table_copy_type(Tab, node(), disc_copies)), 240: ?match({aborted, {has_no_disc, Node1}}, mnesia:change_table_copy_type(Tab, node(), disc_only_copies)), 241: 242: ?match(stopped, mnesia:stop()), 243: 244: ?match(ok, mnesia:create_schema(AllNodes)), 245: ?match([], mnesia_test_lib:start_mnesia(AllNodes)), 246: 247: ?match([SNs, SNs, SNs], 248: lists:map(fun lists:sort/1, 249: element(1, rpc:multicall(AllNodes, mnesia, table_info, 250: [schema, disc_copies])))), 251: 252: ?match({aborted, {already_exists, schema, Node2, _}}, 253: mnesia:change_table_copy_type(schema, Node2, disc_copies)), 254: ?match({atomic, ok}, 255: mnesia:change_table_copy_type(schema, Node2, ram_copies)), 256: ?match({aborted, {already_exists, schema, Node2, _}}, 257: mnesia:change_table_copy_type(schema, Node2, ram_copies)), 258: 259: ?match({atomic, ok}, 260: mnesia:change_table_copy_type(schema, Node2, disc_copies)), 261: 262: ?match([SNs, SNs, SNs], 263: lists:map(fun lists:sort/1, 264: element(1, rpc:multicall(AllNodes, mnesia, table_info, 265: [schema, disc_copies])))), 266: 267: %% Delete the DB 268: 269: Tab2 = disk_tab, 270: Tab3 = not_local, 271: Tab4 = local, 272: Tab5 = remote, 273: 274: Tabs = [Schema, 275: [{name, Tab2}, {disc_copies, AllNodes}], 276: [{name, Tab3}, {ram_copies, [Node2, Node3]}], 277: [{name, Tab4}, {disc_only_copies, [Node1]}], 278: [{name, Tab5}, {disc_only_copies, [Node2]}]], 279: 280: [?match({atomic, ok}, mnesia:create_table(T)) || T <- Tabs ], 281: 282: ?match({aborted, {active, _, Node2}}, 283: mnesia:del_table_copy(schema, Node2)), 284: 285: ?match([], mnesia_test_lib:stop_mnesia([Node1])), 286: ?match({aborted, {node_not_running, Node1}}, 287: mnesia:del_table_copy(schema, Node2)), 288: 289: ?match([], mnesia_test_lib:start_mnesia([Node1],[Tab2,Tab4])), 290: ?match([], mnesia_test_lib:stop_mnesia([Node2])), 291: ?match({atomic, ok}, 292: mnesia:del_table_copy(schema, Node2)), 293: 294: %% Check 295: RemNodes = AllNodes -- [Node2], 296: 297: ?match(RemNodes, mnesia:system_info(db_nodes)), 298: ?match([Node1], Who(Tab)), 299: ?match(RemNodes, Who(Tab2)), 300: ?match([Node3], Who(Tab3)), 301: ?match([Node1], Who(Tab4)), 302: ?match({'EXIT', {aborted, {no_exists, _, _}}}, Who(Tab5)), 303: 304: ?match({atomic, ok}, 305: mnesia:change_table_copy_type(Tab2, Node3, ram_copies)), 306: 307: ?match({atomic, ok}, 308: mnesia:change_table_copy_type(schema, Node3, ram_copies)), 309: 310: ?match([], mnesia_test_lib:stop_mnesia([Node3])), 311: ?match({atomic, ok}, 312: mnesia:del_table_copy(schema, Node3)), 313: ?match([Node1], mnesia:system_info(db_nodes)), 314: ?match([Node1], Who(Tab)), 315: ?match([Node1], Who(Tab2)), 316: ?match({'EXIT', {aborted, {no_exists, _, _}}}, Who(Tab3)), 317: ?match([Node1], Who(Tab4)), 318: ?match({'EXIT', {aborted, {no_exists, _, _}}}, Who(Tab5)), 319: 320: ?verify_mnesia([Node1], []). 321: 322: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 323: %% Drop a db node when several disk resident nodes are down 324: 325: evil_delete_db_node(suite) -> []; 326: evil_delete_db_node(Config) when is_list(Config) -> 327: [Node1, Node2, Node3] = AllNodes = ?acquire_nodes(3, Config), 328: Tab = evil_delete_db_node, 329: 330: ?match({atomic, ok}, mnesia:create_table(Tab, [{disc_copies, AllNodes}])), 331: 332: ?match([], mnesia_test_lib:stop_mnesia([Node2, Node3])), 333: 334: ?match({atomic, ok}, mnesia:del_table_copy(schema, Node2)), 335: 336: RemNodes = AllNodes -- [Node2], 337: 338: ?match(RemNodes, mnesia:system_info(db_nodes)), 339: ?match(RemNodes, mnesia:table_info(Tab, disc_copies)), 340: 341: ?verify_mnesia([Node1], []). 342: 343: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 344: %% Start and stop the system 345: 346: start_and_stop(suite) -> []; 347: start_and_stop(Config) when is_list(Config) -> 348: [Node1 | _] = Nodes = ?acquire_nodes(all, Config), 349: 350: ?match(stopped, rpc:call(Node1, mnesia, stop, [])), 351: ?match(stopped, rpc:call(Node1, mnesia, stop, [])), 352: ?match(ok, rpc:call(Node1, mnesia, start, [])), 353: ?match(ok, rpc:call(Node1, mnesia, start, [])), 354: ?match(stopped, rpc:call(Node1, mnesia, stop, [])), 355: ?verify_mnesia(Nodes -- [Node1], [Node1]), 356: ?match([], mnesia_test_lib:start_mnesia(Nodes)), 357: ?verify_mnesia(Nodes, []). 358: 359: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 360: %% Checkpoints and backup management 361: 362: checkpoint(suite) -> []; 363: checkpoint(Config) when is_list(Config) -> 364: checkpoint(2, Config), 365: checkpoint(3, Config). 366: 367: checkpoint(NodeConfig, Config) -> 368: [Node1 | _] = TabNodes = ?acquire_nodes(NodeConfig, Config), 369: CreateTab = fun(Type, N, Ns) -> 370: Tab0 = lists:concat(["local_checkpoint_", Type, N]), 371: Tab = list_to_atom(Tab0), 372: catch mnesia:delete_table(Tab), 373: ?match({atomic, ok}, 374: mnesia:create_table(Tab, [{Type, Ns}])), 375: Tab 376: end, 377: CreateTabs = fun(Type, Acc) -> 378: [CreateTab(Type, 1, [hd(TabNodes)]), 379: CreateTab(Type, 2, TabNodes), 380: CreateTab(Type, 3, [lists:last(TabNodes)])] ++ 381: Acc 382: end, 383: Types = [ram_copies, disc_copies, disc_only_copies], 384: Tabs = lists:foldl(CreateTabs, [], Types), 385: Recs = ?sort([{T, N, N} || T <- Tabs, N <- lists:seq(1, 10)]), 386: lists:foreach(fun(R) -> ?match(ok, mnesia:dirty_write(R)) end, Recs), 387: 388: CpName = a_checkpoint_name, 389: MinArgs = [{name, CpName}, {min, Tabs}, {allow_remote, false}], 390: ?match({error, _}, rpc:call(Node1, mnesia, activate_checkpoint, [MinArgs])), 391: 392: MaxArgs = [{name, CpName}, {max, Tabs}, {allow_remote, true}], 393: ?match({ok, CpName, L} when is_list(L), 394: rpc:call(Node1, mnesia, activate_checkpoint, [MaxArgs])), 395: ?match(ok, rpc:call(Node1, mnesia, deactivate_checkpoint, [CpName])), 396: 397: Args = [{name, CpName}, {min, Tabs}, {allow_remote, true}], 398: ?match({ok, CpName, L} when is_list(L), 399: rpc:call(Node1, mnesia, activate_checkpoint, [Args])), 400: Recs2 = ?sort([{T, K, 0} || {T, K, _} <- Recs]), 401: lists:foreach(fun(R) -> ?match(ok, mnesia:dirty_write(R)) end, Recs2), 402: ?match(ok, rpc:call(Node1, mnesia, deactivate_checkpoint, [CpName])), 403: 404: ?match({error, Reason1 } when element(1, Reason1) == no_exists, 405: mnesia:deactivate_checkpoint(CpName)), 406: ?match({error, Reason2 } when element(1, Reason2) == badarg, 407: mnesia:activate_checkpoint(foo)), 408: ?match({error, Reason3 } when element(1, Reason3) == badarg, 409: mnesia:activate_checkpoint([{foo, foo}])), 410: ?match({error, Reason4 } when element(1, Reason4) == badarg, 411: mnesia:activate_checkpoint([{max, foo}])), 412: ?match({error, Reason5 } when element(1, Reason5) == badarg, 413: mnesia:activate_checkpoint([{min, foo}])), 414: ?match({error, _}, mnesia:activate_checkpoint([{min, [foo@bar]}])), 415: ?match({error, Reason6 } when element(1, Reason6) == badarg, 416: mnesia:activate_checkpoint([{allow_remote, foo}])), 417: 418: Fun = fun(Tab) -> ?match({atomic, ok}, mnesia:delete_table(Tab)) end, 419: lists:foreach(Fun, Tabs), 420: ?verify_mnesia(TabNodes, []). 421: 422: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 423: %% Create and delete tables 424: 425: %% Get meta info about table 426: 427: -define(vrl, mnesia_test_lib:verify_replica_location). 428: 429: replica_location(suite) -> []; 430: replica_location(Config) when is_list(Config) -> 431: [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), 432: Tab = replica_location, 433: 434: %% Create three replicas 435: Schema = [{name, Tab}, {disc_only_copies, [Node1]}, 436: {ram_copies, [Node2]}, {disc_copies, [Node3]}], 437: ?match({atomic, ok}, mnesia:create_table(Schema)), 438: ?match([], ?vrl(Tab, [Node1], [Node2], [Node3], Nodes)), 439: 440: %% Delete one replica 441: ?match({atomic, ok}, mnesia:del_table_copy(Tab, Node2)), 442: ?match([], ?vrl(Tab, [Node1], [], [Node3], Nodes)), 443: 444: %% Move one replica 445: ?match({atomic, ok}, mnesia:move_table_copy(Tab, Node1, Node2)), 446: ?match([], ?vrl(Tab, [Node2], [], [Node3], Nodes)), 447: 448: %% Change replica type 449: ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, Node2, ram_copies)), 450: ?match([], ?vrl(Tab, [], [Node2], [Node3], Nodes)), 451: 452: ?verify_mnesia(Nodes, []). 453: 454: table_lifecycle(suite) -> []; 455: table_lifecycle(Config) when is_list(Config) -> 456: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 457: 458: ?match({atomic, ok}, mnesia:create_table([{type, bag}, 459: {ram_copies, [Node1]}, 460: {attributes, [rajtan, tajtan]}, 461: {name, order_of_args}])), 462: ?match([], mnesia:dirty_read({order_of_args, 4711})), 463: ?match({atomic, ok}, mnesia:create_table([{name, already_exists}, 464: {ram_copies, [Node1]}])), 465: ?match({aborted, Reason23 } when element(1, Reason23) ==already_exists, 466: mnesia:create_table([{name, already_exists}, 467: {ram_copies, [Node1]}])), 468: ?match({aborted, Reason21 } when element(1, Reason21) == bad_type, 469: mnesia:create_table([{name, bad_node}, {ram_copies, ["foo"]}])), 470: ?match({aborted, Reason2} when element(1, Reason2) == bad_type, 471: mnesia:create_table([{name, zero_arity}, {attributes, []}])), 472: ?match({aborted, Reason3} when element(1, Reason3) == badarg, 473: mnesia:create_table([])), 474: ?match({aborted, Reason4} when element(1, Reason4) == badarg, 475: mnesia:create_table(atom)), 476: ?match({aborted, Reason5} when element(1, Reason5) == badarg, 477: mnesia:create_table({cstruct, table_name_as_atom})), 478: ?match({aborted, Reason6 } when element(1, Reason6) == bad_type, 479: mnesia:create_table([{name, no_host}, {ram_copies, foo}])), 480: ?match({aborted, Reason7 } when element(1, Reason7) == bad_type, 481: mnesia:create_table([{name, no_host}, {disc_only_copies, foo}])), 482: ?match({aborted, Reason8} when element(1, Reason8) == bad_type, 483: mnesia:create_table([{name, no_host}, {disc_copies, foo}])), 484: 485: CreateFun = 486: fun() -> ?match({aborted, nested_transaction}, 487: mnesia:create_table([{name, nested_trans}])), ok 488: end, 489: ?match({atomic, ok}, mnesia:transaction(CreateFun)), 490: ?match({atomic, ok}, mnesia:create_table([{name, remote_tab}, 491: {ram_copies, [Node2]}])), 492: 493: ?match({atomic, ok}, mnesia:create_table([{name, a_brand_new_tab}, 494: {ram_copies, [Node1]}])), 495: ?match([], mnesia:dirty_read({a_brand_new_tab, 4711})), 496: ?match({atomic, ok}, mnesia:delete_table(a_brand_new_tab)), 497: ?match({'EXIT', {aborted, Reason31}} when element(1, Reason31) == no_exists, 498: mnesia:dirty_read({a_brand_new_tab, 4711})), 499: ?match({aborted, Reason41} when element(1, Reason41) == no_exists, 500: mnesia:delete_table(a_brand_new_tab)), 501: ?match({aborted, Reason9} when element(1, Reason9) == badarg, 502: mnesia:create_table([])), 503: 504: ?match({atomic, ok}, mnesia:create_table([{name, nested_del_trans}, 505: {ram_copies, [Node1]}])), 506: 507: DeleteFun = fun() -> ?match({aborted, nested_transaction}, 508: mnesia:delete_table(nested_del_trans)), ok end, 509: ?match({atomic, ok}, mnesia:transaction(DeleteFun)), 510: 511: ?match({aborted, Reason10} when element(1, Reason10) == bad_type, 512: mnesia:create_table([{name, create_with_index}, {index, 2}])), 513: ?match({aborted, Reason32} when element(1, Reason32) == bad_type, 514: mnesia:create_table([{name, create_with_index}, {index, [-1]}])), 515: ?match({aborted, Reason33} when element(1, Reason33) == bad_type, 516: mnesia:create_table([{name, create_with_index}, {index, [0]}])), 517: ?match({aborted, Reason34} when element(1, Reason34) == bad_type, 518: mnesia:create_table([{name, create_with_index}, {index, [1]}])), 519: ?match({aborted, Reason35} when element(1, Reason35) == bad_type, 520: mnesia:create_table([{name, create_with_index}, {index, [2]}])), 521: ?match({atomic, ok}, 522: mnesia:create_table([{name, create_with_index}, {index, [3]}, 523: {ram_copies, [Node1]}])), 524: 525: ets:new(ets_table, [named_table]), 526: ?match({aborted, _}, mnesia:create_table(ets_table, [{ram_copies, Nodes}])), 527: ?match({aborted, _}, mnesia:create_table(ets_table, [{ram_copies, [Node1]}])), 528: ets:delete(ets_table), 529: ?match({atomic, ok}, mnesia:create_table(ets_table, [{ram_copies, [Node1]}])), 530: ?match(Node1, rpc:call(Node1, mnesia_lib, val, [{ets_table,where_to_read}])), 531: ?match(Node1, rpc:call(Node2, mnesia_lib, val, [{ets_table,where_to_read}])), 532: ?match({atomic, ok}, mnesia:change_table_copy_type(ets_table, Node1, disc_only_copies)), 533: ?match(Node1, rpc:call(Node2, mnesia_lib, val, [{ets_table,where_to_read}])), 534: 535: ?verify_mnesia(Nodes, []). 536: 537: 538: storage_options(suite) -> []; 539: storage_options(Config) when is_list(Config) -> 540: [N1,N2,N3] = Nodes = ?acquire_nodes(3, Config), 541: 542: ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,foobar}]}])), 543: ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,[foobar]}]}])), 544: ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{ets,[duplicate_bag]}]}])), 545: ?match({aborted,_}, mnesia:create_table(a, [{storage_properties, [{dets,[{type,bag}]}]}])), 546: 547: ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [N1]}, 548: {disc_only_copies, [N2]}, 549: {storage_properties, 550: [{ets,[compressed]}, 551: {dets, [{auto_save, 5000}]} ]}])), 552: ?match(true, ets:info(a, compressed)), 553: ?match(5000, rpc:call(N2, dets, info, [a, auto_save])), 554: ?match(ok, mnesia:dirty_write({a,1,1})), 555: ?match([{a,1,1}], mnesia:dirty_read({a,1})), 556: mnesia:dump_log(), 557: W2C1 = [{N2, disc_only_copies}, {N1, ram_copies}], 558: ?match(W2C1, lists:sort(rpc:call(N2, mnesia_lib, val, [{a, where_to_commit}]))), 559: ?match(W2C1, lists:sort(rpc:call(N3, mnesia_lib, val, [{a, where_to_commit}]))), 560: ?match({atomic,ok}, mnesia:change_table_copy_type(a, N1, disc_only_copies)), 561: W2C2 = [{N2, disc_only_copies}, {N1, disc_only_copies}], 562: ?match(W2C2, lists:sort(rpc:call(N2, mnesia_lib, val, [{a, where_to_commit}]))), 563: ?match(W2C2, lists:sort(rpc:call(N3, mnesia_lib, val, [{a, where_to_commit}]))), 564: ?match(undefined, ets:info(a, compressed)), 565: ?match(5000, dets:info(a, auto_save)), 566: ?match({atomic,ok}, mnesia:change_table_copy_type(a, N1, disc_copies)), 567: ?match(true, ets:info(a, compressed)), 568: 569: ?verify_mnesia(Nodes, []). 570: 571: 572: clear_table_during_load(suite) -> []; 573: clear_table_during_load(doc) -> 574: ["Clear table caused during load caused a schema entry in the actual tab"]; 575: clear_table_during_load(Config) when is_list(Config) -> 576: Nodes = [_, Node2] = ?acquire_nodes(2, Config ++ [{tc_timeout, timer:minutes(2)}]), 577: ?match({atomic,ok}, mnesia:create_table(cleartab, [{ram_copies, Nodes}])), 578: Tester = self(), 579: Bin = <<"Testingasdasd", 0:32000>>, 580: Fill = fun() -> [mnesia:write({cleartab, N, Bin}) || N <- lists:seq(1, 3000)], ok end, 581: ?match({atomic, ok}, mnesia:sync_transaction(Fill)), 582: 583: StopAndStart = fun() -> 584: stopped = mnesia:stop(), 585: Tester ! {self(), stopped}, 586: receive start_node -> ok end, 587: ok = mnesia:start(), 588: ok = mnesia:wait_for_tables([cleartab], 2000), 589: lists:foreach(fun({cleartab,_,_}) -> ok; 590: (What) -> Tester ! {failed, What}, 591: unlink(Tester), 592: exit(foo) 593: end, 594: ets:tab2list(cleartab)), 595: Tester ! {self(), ok}, 596: normal 597: end, 598: 599: Test = fun(N) -> 600: Pid = spawn_link(Node2, StopAndStart), 601: receive {Pid, stopped} -> ok end, 602: Pid ! start_node, 603: timer:sleep(N*10), 604: {atomic, ok} = mnesia:clear_table(cleartab), 605: receive 606: {Pid, ok} -> ok; 607: {failed, What} -> 608: io:format("Failed in ~p tries, with ~p~n",[N, What]), 609: exit({error, What}); 610: {'EXIT', Pid, Reason} -> 611: exit({died, Reason}) 612: end 613: end, 614: [Test(N) || N <- lists:seq(1, 10)], 615: ?verify_mnesia(Nodes, []). 616: 617: 618: add_copy_conflict(suite) -> []; 619: add_copy_conflict(doc) -> 620: ["Verify that OTP-5065 doesn't happen again, whitebox testing"]; 621: add_copy_conflict(Config) when is_list(Config) -> 622: Nodes = [Node1, Node2] = 623: ?acquire_nodes(2, Config ++ [{tc_timeout, timer:minutes(2)}]), 624: 625: ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, Nodes}])), 626: ?match({atomic, ok}, mnesia:create_table(b, [{ram_copies, Nodes}])), 627: ?match({atomic, ok}, mnesia:create_table(test, [{ram_copies, [Node2]}])), 628: mnesia:stop(), 629: ?match(ok,mnesia:start([{no_table_loaders, 1}])), 630: 631: verify_ll_queue(10), 632: 633: Self = self(), 634: Test = fun() -> 635: Res = mnesia:add_table_copy(test, Node1, ram_copies), 636: Self ! {test, Res} 637: end, 638: %% Create conflict with loader queue. 639: spawn_link(Test), 640: ?match_receive(timeout), 641: %% Conflict ok 642: mnesia_controller:unblock_controller(), 643: 644: ?match_receive({test, {atomic,ok}}), 645: ?match(ok, mnesia:wait_for_tables([a,b], 3000)), 646: ?verify_mnesia(Nodes, []), 647: ?cleanup(1, Config). 648: 649: verify_ll_queue(0) -> 650: ?error("Couldn't find anything in queue~n",[]); 651: verify_ll_queue(N) -> 652: ?match(granted,mnesia_controller:block_controller()), 653: case mnesia_controller:get_info(1000) of 654: {info,{state,_,true,[],_Loader,[],[],[],_,_,_,_,_,_}} -> 655: %% Very slow SMP machines havn't loaded it yet.. 656: mnesia_controller:unblock_controller(), 657: timer:sleep(10), 658: verify_ll_queue(N-1); 659: {info,{state,_,true,[],Loader,LL,[],[],_,_,_,_,_,_}} -> 660: io:format("~p~n", [{Loader,LL}]), 661: ?match([_], LL); %% Verify that something is in the loader queue 662: Else -> 663: ?error("No match ~p maybe the internal format has changed~n",[Else]) 664: end. 665: 666: add_copy_when_going_down(suite) -> []; 667: add_copy_when_going_down(doc) -> 668: ["Tests abort when node we load from goes down"]; 669: add_copy_when_going_down(Config) -> 670: [Node1, Node2] = 671: ?acquire_nodes(2, Config ++ [{tc_timeout, timer:minutes(2)}]), 672: ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [Node1]}])), 673: %% Grab a write lock 674: WriteAndWait = fun() -> 675: mnesia:write({a,1,1}), 676: receive continue -> ok 677: end 678: end, 679: _Lock = spawn(fun() -> mnesia:transaction(WriteAndWait) end), 680: Tester = self(), 681: spawn_link(fun() -> Res = rpc:call(Node2, mnesia, add_table_copy, 682: [a, Node2, ram_copies]), 683: Tester ! {test, Res} 684: end), 685: %% We have a lock here we should get a timeout 686: ?match_receive(timeout), 687: mnesia_test_lib:kill_mnesia([Node1]), 688: ?match_receive({test,{aborted,_}}), 689: ?verify_mnesia([Node2], []). 690: 691: 692: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 693: %% Add, drop and move replicas, change storage types 694: %% Change table layout (only arity change supported) 695: 696: -record(replica_management, {k, v}). 697: -record(new_replica_management, {k, v, extra}). 698: 699: -define(SS(R), lists:sort(element(1,R))). 700: 701: replica_management(doc) -> 702: "Add, drop and move replicas, change storage types."; 703: replica_management(suite) -> 704: []; 705: replica_management(Config) when is_list(Config) -> 706: %% add_table_copy/3, del_table_copy/2, move_table_copy/3, 707: %% change_table_copy_type/3, transform_table/3 708: 709: Nodes = [Node1, Node2, Node3] = ?acquire_nodes(3, Config), 710: 711: Tab = replica_management, 712: Attrs = record_info(fields, replica_management), 713: 714: %% 715: %% Add, delete and change replicas 716: %% 717: ?match({atomic, ok}, 718: mnesia:create_table([{name, Tab}, {attributes, Attrs}, 719: {ram_copies, [Node1, Node3]}])), 720: [?match(ok, mnesia:dirty_write({Tab, K, K + 2})) || K <-lists:seq(1, 10)], 721: ?match([], ?vrl(Tab, [], [Node1, Node3], [], Nodes)), 722: %% R - - 723: ?match({atomic, ok}, mnesia:dump_tables([Tab])), 724: ?match({aborted, Reason50 } when element(1, Reason50) == combine_error, 725: mnesia:add_table_copy(Tab, Node2, disc_copies)), 726: ?match({aborted, Reason51 } when element(1, Reason51) == combine_error, 727: mnesia:change_table_copy_type(Tab, Node1, disc_copies)), 728: ?match({atomic, ok}, mnesia:clear_table(Tab)), 729: SyncedCheck = fun() -> 730: mnesia:lock({record,Tab,0}, write), 731: ?match([0,0,0], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))) 732: end, 733: mnesia:transaction(SyncedCheck), 734: 735: ?match({[0,0,0], []}, rpc:multicall(Nodes, mnesia, table_info, [Tab, size])), 736: ?match({atomic, ok}, mnesia:del_table_copy(Tab, Node1)), 737: ?match({atomic, ok}, mnesia:del_table_copy(Tab, Node3)), 738: ?match([], ?vrl(Tab, [], [], [], Nodes)), 739: %% - - - 740: ?match({aborted,Reason52} when element(1, Reason52) == no_exists, 741: mnesia:add_table_copy(Tab, Node3, ram_copies)), 742: 743: ?match({atomic, ok}, mnesia:create_table([{name, Tab}, 744: {attributes, Attrs}, 745: {disc_copies, [Node1]}])), 746: ?match([], ?vrl(Tab, [], [], [Node1], Nodes)), 747: %% D - - 748: [?match(ok, mnesia:dirty_write({Tab, K, K + 2})) || K <-lists:seq(1, 10)], 749: 750: ?match({aborted, Reason53} when element(1, Reason53) == badarg, 751: mnesia:add_table_copy(Tab, Node2, bad_storage_type)), 752: ?match({atomic, ok}, mnesia:add_table_copy(Tab, Node2, disc_only_copies)), 753: ?match([], ?vrl(Tab, [Node2], [], [Node1], Nodes)), 754: ?match([0,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 755: %% D DO - 756: ?match({atomic, ok}, mnesia:add_table_copy(Tab, Node3, ram_copies)), 757: ?match([], ?vrl(Tab, [Node2], [Node3], [Node1], Nodes)), 758: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 759: %% D DO R 760: ?match({atomic, ok}, 761: mnesia:change_table_copy_type(Tab, Node1, disc_only_copies)), 762: ?match([], ?vrl(Tab, [Node1, Node2], [Node3], [], Nodes)), 763: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 764: %% DO DO R 765: ?match({aborted, Reason54} when element(1, Reason54) == already_exists, 766: mnesia:add_table_copy(Tab, Node3, ram_copies)), 767: ?match({atomic, ok}, mnesia:del_table_copy(Tab, Node1)), 768: ?match([], ?vrl(Tab, [Node2], [Node3], [], Nodes)), 769: %% - DO R 770: ?match({aborted, _}, mnesia:del_table_copy(Tab, Node1)), 771: ?match(Tab, ets:new(Tab, [named_table])), 772: ?match({aborted, _}, mnesia:add_table_copy(Tab, Node1, disc_copies)), 773: ?match(true, ets:delete(Tab)), 774: ?match({atomic, ok}, mnesia:add_table_copy(Tab, Node1, disc_copies)), 775: ?match([], ?vrl(Tab, [Node2], [Node3], [Node1], Nodes)), 776: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 777: %% D DO R 778: ?match({atomic, ok},mnesia:change_table_copy_type(Tab, Node3, disc_only_copies)), 779: ?match([], ?vrl(Tab, [Node2, Node3], [], [Node1], Nodes)), 780: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 781: 782: %% D DO D0 783: ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, Node3, ram_copies)), 784: ?match([], ?vrl(Tab, [Node2], [Node3], [Node1], Nodes)), 785: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 786: %% D DO R 787: ?match({atomic, ok}, 788: mnesia:change_table_copy_type(Tab, Node2, disc_copies)), 789: ?match([], ?vrl(Tab, [], [Node3], [Node1,Node2], Nodes)), 790: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 791: 792: %% D D R 793: ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, Node1, disc_only_copies)), 794: ?match([], ?vrl(Tab, [Node1], [Node3], [Node2], Nodes)), 795: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 796: 797: %% DO D R 798: ?match(Tab, ets:new(Tab, [named_table])), 799: ?match({aborted, _}, mnesia:change_table_copy_type(Tab, Node1, ram_copies)), 800: ?match(true, ets:delete(Tab)), 801: ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, Node1, ram_copies)), 802: ?match([], ?vrl(Tab, [], [Node3,Node1], [Node2], Nodes)), 803: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 804: %% R D R 805: ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, Node1, disc_copies)), 806: ?match([], ?vrl(Tab, [], [Node3], [Node2,Node1], Nodes)), 807: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 808: 809: %% D D R 810: ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, Node2, disc_only_copies)), 811: ?match([], ?vrl(Tab, [Node2], [Node3], [Node1], Nodes)), 812: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 813: 814: %% D DO R 815: ?match({atomic, ok}, mnesia:change_table_copy_type(Tab, Node3, disc_only_copies)), 816: ?match([], ?vrl(Tab, [Node2, Node3], [], [Node1], Nodes)), 817: ?match([10,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 818: %% D DO DO 819: %% test clear 820: ?match({atomic, ok}, mnesia:clear_table(Tab)), 821: mnesia:transaction(SyncedCheck), 822: 823: %% rewrite for rest of testcase 824: [?match(ok, mnesia:dirty_write({Tab, K, K + 2})) || K <-lists:seq(1, 10)], 825: 826: %% D DO DO 827: ?match({atomic, ok}, mnesia:del_table_copy(Tab, Node2)), 828: ?match([], ?vrl(Tab, [Node3], [], [Node1], Nodes)), 829: %% D - DO 830: ?match({aborted, Reason55} when element(1, Reason55) == already_exists, 831: mnesia:change_table_copy_type(Tab, Node1, disc_copies)), 832: 833: %% 834: %% Move replica 835: %% 836: ?match({atomic, ok}, mnesia:move_table_copy(Tab, Node1, Node2)), 837: ?match([], ?vrl(Tab, [Node3], [], [Node2], Nodes)), 838: ?match([0,10,10], ?SS(rpc:multicall(Nodes, mnesia, table_info, [Tab, size]))), 839: %% - D DO 840: ?match({aborted, _}, mnesia:move_table_copy(Tab, Node1, Node2)), 841: ?match([], mnesia_test_lib:stop_mnesia([Node3])), 842: ?match({atomic,ok}, mnesia:transaction(fun() -> mnesia:write({Tab, 43, sync_me}) end)), 843: ?match([], ?vrl(Tab, [Node3], [], [Node2],Nodes -- [Node3])), 844: %% - D DO 845: ?match({aborted,Reason56} when element(1, Reason56) == not_active, 846: mnesia:move_table_copy(Tab, Node3, Node1)), 847: ?match([], ?vrl(Tab, [Node3], [], [Node2],Nodes -- [Node3])), 848: %% DO D - 849: ?match([], mnesia_test_lib:start_mnesia([Node3])), 850: ?match([], ?vrl(Tab, [Node3], [], [Node2], Nodes)), 851: %% DO D - 852: 853: %% 854: %% Transformer 855: %% 856: 857: NewAttrs = record_info(fields, new_replica_management), 858: Transformer = 859: fun(Rec) when is_record(Rec, replica_management) -> 860: #new_replica_management{k = Rec#replica_management.k, 861: v = Rec#replica_management.v, 862: extra = Rec#replica_management.k * 2} 863: end, 864: ?match({atomic, ok}, mnesia:transform_table(Tab, fun(R) -> R end, Attrs)), 865: ?match({atomic, ok}, mnesia:transform_table(Tab, Transformer, NewAttrs, new_replica_management)), 866: 867: ERlist = [#new_replica_management{k = K, v = K+2, extra = K*2} || K <- lists:seq(1, 10)], 868: ARlist = [hd(mnesia:dirty_read(Tab, K)) || K <- lists:seq(1, 10)], 869: 870: ?match(ERlist, ARlist), 871: 872: ?match({aborted, Reason56} when element(1, Reason56) == bad_type, 873: mnesia:transform_table(Tab, Transformer, 0)), 874: ?match({aborted, Reason57} when element(1, Reason57) == bad_type, 875: mnesia:transform_table(Tab, Transformer, -1)), 876: ?match({aborted, Reason58} when element(1, Reason58) == bad_type, 877: mnesia:transform_table(Tab, Transformer, [])), 878: ?match({aborted, Reason59} when element(1, Reason59) == bad_type, 879: mnesia:transform_table(Tab, no_fun, NewAttrs)), 880: ?match({aborted, Reason59} when element(1, Reason59) == bad_type, 881: mnesia:transform_table(Tab, fun(X) -> X end, NewAttrs, {tuple})), 882: 883: %% OTP-3878 884: ?match({atomic, ok}, mnesia:transform_table(Tab, ignore, 885: NewAttrs ++ [dummy])), 886: ?match({atomic, ok}, mnesia:transform_table(Tab, ignore, 887: NewAttrs ++ [dummy], last_rec)), 888: 889: ARlist = [hd(mnesia:dirty_read(Tab, K)) || K <- lists:seq(1, 10)], 890: ?match({'EXIT',{aborted,{bad_type,_}}}, 891: mnesia:dirty_write(Tab, #new_replica_management{})), 892: ?match(ok, mnesia:dirty_write(Tab, {last_rec, k, v, e, dummy})), 893: 894: ?verify_mnesia(Nodes, []). 895: 896: schema_availability(doc) -> 897: ["Test that schema succeeds (or fails) as intended when some db nodes are down."]; 898: schema_availability(suite) -> 899: []; 900: schema_availability(Config) when is_list(Config) -> 901: [N1, _N2, N3] = Nodes = ?acquire_nodes(3, Config), 902: Tab = schema_availability, 903: Storage = mnesia_test_lib:storage_type(ram_copies, Config), 904: Def1 = [{Storage, [N1, N3]}], 905: ?match({atomic, ok}, mnesia:create_table(Tab, Def1)), 906: 907: N = 10, 908: ?match(ok, mnesia:sync_dirty(fun() -> [mnesia:write({Tab, K, K + 2}) || K <- lists:seq(1, N)], ok end)), 909: ?match({[N,0,N], []}, rpc:multicall(Nodes, mnesia, table_info, [Tab, size])), 910: ?match([], mnesia_test_lib:kill_mnesia([N3])), 911: ?match({[N,0,0], []}, rpc:multicall(Nodes, mnesia, table_info, [Tab, size])), 912: 913: ?match([], mnesia_test_lib:start_mnesia([N3], [Tab])), 914: ?match({[N,0,N], []}, rpc:multicall(Nodes, mnesia, table_info, [Tab, size])), 915: ?match([], mnesia_test_lib:kill_mnesia([N3])), 916: 917: ?match({atomic, ok}, mnesia:clear_table(Tab)), 918: ?match({[0,0,0], []}, rpc:multicall(Nodes, mnesia, table_info, [Tab, size])), 919: 920: ?match([], mnesia_test_lib:start_mnesia([N3], [Tab])), 921: ?match({[0,0,0], []}, rpc:multicall(Nodes, mnesia, table_info, [Tab, size])), 922: 923: ?verify_mnesia(Nodes, []). 924: 925: -define(badrpc(Tab), {badrpc, {'EXIT', {aborted,{no_exists,Tab}}}}). 926: 927: local_content(doc) -> 928: ["Test local_content functionality, we want to see that correct" 929: " properties gets propageted correctly between nodes"]; 930: local_content(suite) -> []; 931: local_content(Config) when is_list(Config) -> 932: [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), 933: Tab1 = local1, 934: Def1 = [{local_content, true}, {ram_copies, Nodes}], 935: Tab2 = local2, 936: Def2 = [{local_content, true}, {disc_copies, [Node1]}], 937: Tab3 = local3, 938: Def3 = [{local_content, true}, {disc_only_copies, [Node1]}], 939: Tab4 = local4, 940: Def4 = [{local_content, true}, {ram_copies, [Node1]}], 941: 942: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 943: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 944: ?match({atomic, ok}, mnesia:create_table(Tab3, Def3)), 945: ?match({atomic, ok}, mnesia:create_table(Tab4, Def4)), 946: 947: ?match(ok, rpc:call(Node1, mnesia, dirty_write, [{Tab1, 1, Node1}])), 948: ?match(ok, rpc:call(Node2, mnesia, dirty_write, [{Tab1, 1, Node2}])), 949: ?match(ok, rpc:call(Node3, mnesia, dirty_write, [{Tab1, 1, Node3}])), 950: ?match(ok, rpc:call(Node1, mnesia, dirty_write, [{Tab2, 1, Node1}])), 951: ?match(ok, rpc:call(Node1, mnesia, dirty_write, [{Tab3, 1, Node1}])), 952: ?match(ok, rpc:call(Node1, mnesia, dirty_write, [{Tab4, 1, Node1}])), 953: 954: ?match(?badrpc(Tab2), rpc:call(Node2, mnesia, dirty_write, [{Tab2, 1, Node2}])), 955: ?match(?badrpc(Tab3), rpc:call(Node2, mnesia, dirty_write, [{Tab3, 1, Node2}])), 956: ?match(?badrpc(Tab4), rpc:call(Node2, mnesia, dirty_write, [{Tab4, 1, Node2}])), 957: 958: ?match({atomic, ok}, rpc:call(Node1, mnesia, add_table_copy, [Tab2, Node2, ram_copies])), 959: ?match({atomic, ok}, rpc:call(Node2, mnesia, add_table_copy, [Tab3, Node2, disc_copies])), 960: ?match({atomic, ok}, rpc:call(Node3, mnesia, add_table_copy, [Tab4, Node2, disc_only_copies])), 961: ?match([], rpc:call(Node2, mnesia, dirty_read, [{Tab2, 1}])), 962: ?match([], rpc:call(Node2, mnesia, dirty_read, [{Tab3, 1}])), 963: ?match([], rpc:call(Node2, mnesia, dirty_read, [{Tab4, 1}])), 964: 965: ?match(ok, rpc:call(Node2, mnesia, dirty_write, [{Tab2, 1, Node2}])), 966: ?match(ok, rpc:call(Node2, mnesia, dirty_write, [{Tab3, 1, Node2}])), 967: ?match(ok, rpc:call(Node2, mnesia, dirty_write, [{Tab4, 1, Node2}])), 968: 969: ?match([{Tab1, 1, Node1}], rpc:call(Node1, mnesia, dirty_read, [{Tab1, 1}])), 970: ?match([{Tab2, 1, Node1}], rpc:call(Node1, mnesia, dirty_read, [{Tab2, 1}])), 971: ?match([{Tab3, 1, Node1}], rpc:call(Node1, mnesia, dirty_read, [{Tab3, 1}])), 972: ?match([{Tab4, 1, Node1}], rpc:call(Node1, mnesia, dirty_read, [{Tab4, 1}])), 973: 974: ?match([{Tab1, 1, Node2}], rpc:call(Node2, mnesia, dirty_read, [{Tab1, 1}])), 975: ?match([{Tab2, 1, Node2}], rpc:call(Node2, mnesia, dirty_read, [{Tab2, 1}])), 976: ?match([{Tab3, 1, Node2}], rpc:call(Node2, mnesia, dirty_read, [{Tab3, 1}])), 977: ?match([{Tab4, 1, Node2}], rpc:call(Node2, mnesia, dirty_read, [{Tab4, 1}])), 978: 979: ?match([{Tab1, 1, Node3}], rpc:call(Node3, mnesia, dirty_read, [{Tab1, 1}])), 980: ?match(?badrpc([_Tab2, 1]), rpc:call(Node3, mnesia, dirty_read, [{Tab2, 1}])), 981: ?match(?badrpc([_Tab3, 1]), rpc:call(Node3, mnesia, dirty_read, [{Tab3, 1}])), 982: ?match(?badrpc([_Tab4, 1]), rpc:call(Node3, mnesia, dirty_read, [{Tab4, 1}])), 983: 984: ?match({atomic, ok}, 985: mnesia:change_table_copy_type(schema, Node3, ram_copies)), 986: ?match([], mnesia_test_lib:stop_mnesia([Node3])), 987: 988: %% Added for OTP-44306 989: ?match(ok, rpc:call(Node3, mnesia, start, [])), 990: ?match({ok, _}, mnesia:change_config(extra_db_nodes, [Node3])), 991: 992: mnesia_test_lib:sync_tables([Node3], [Tab1]), 993: 994: ?match([], rpc:call(Node3, mnesia, dirty_read, [{Tab1, 1}])), 995: 996: ?match({atomic, ok}, rpc:call(Node1, mnesia, clear_table, [Tab1])), 997: 998: SyncedCheck = fun(Tab) -> 999: mnesia:lock({record,Tab,0}, write), 1000: {OK, []} = rpc:multicall(Nodes, mnesia, table_info, [Tab, size]), 1001: OK 1002: end, 1003: ?match({atomic, [0,1,0]}, mnesia:transaction(SyncedCheck, [Tab1])), 1004: ?match({atomic, ok}, rpc:call(Node2, mnesia, clear_table, [Tab2])), 1005: ?match({atomic, [1,0,0]}, mnesia:transaction(SyncedCheck, [Tab2])), 1006: ?match({atomic, ok}, rpc:call(Node2, mnesia, clear_table, [Tab3])), 1007: ?match({atomic, [1,0,0]}, mnesia:transaction(SyncedCheck, [Tab3])), 1008: 1009: ?verify_mnesia(Nodes, []). 1010: 1011: 1012: change_table_access_mode(suite) -> []; 1013: change_table_access_mode(Config) when is_list(Config) -> 1014: [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), 1015: Tab = test_access_mode_tab, 1016: 1017: Def = case mnesia_test_lib:diskless(Config) of 1018: true -> [{name, Tab}, {ram_copies, Nodes}]; 1019: false -> [{name, Tab}, {ram_copies, [Node1]}, 1020: {disc_copies, [Node2]}, 1021: {disc_only_copies, [Node3]}] 1022: end, 1023: ?match({atomic, ok}, mnesia:create_table(Def)), 1024: 1025: Write = fun(What) -> mnesia:write({Tab, 1, What}) end, 1026: Read = fun() -> mnesia:read({Tab, 1}) end, 1027: 1028: ?match({atomic, ok}, mnesia:transaction(Write, [test_ok])), 1029: %% test read_only 1030: ?match({atomic, ok}, mnesia:change_table_access_mode(Tab, read_only)), 1031: ?match({aborted, _}, mnesia:transaction(Write, [nok])), 1032: ?match({'EXIT', {aborted, _}}, mnesia:dirty_write({Tab, 1, [nok]})), 1033: ?match({aborted, _}, rpc:call(Node2, mnesia, transaction, [Write, [nok]])), 1034: ?match({aborted, _}, rpc:call(Node3, mnesia, transaction, [Write, [nok]])), 1035: ?match({atomic, [{Tab, 1, test_ok}]}, mnesia:transaction(Read)), 1036: %% test read_write 1037: ?match({atomic, ok}, mnesia:change_table_access_mode(Tab, read_write)), 1038: ?match({atomic, ok}, mnesia:transaction(Write, [test_ok1])), 1039: ?match({atomic, [{Tab, 1, test_ok1}]}, mnesia:transaction(Read)), 1040: ?match({atomic, ok}, rpc:call(Node2, mnesia, transaction, [Write, [test_ok2]])), 1041: ?match({atomic, [{Tab, 1, test_ok2}]}, mnesia:transaction(Read)), 1042: ?match({atomic, ok}, rpc:call(Node3, mnesia, transaction, [Write, [test_ok3]])), 1043: ?match({atomic, [{Tab, 1, test_ok3}]}, mnesia:transaction(Read)), 1044: 1045: ?match({atomic, ok}, mnesia:delete_table(Tab)), 1046: 1047: Def4 = [{name, Tab}, {access_mode, read_only_bad}], 1048: ?match({aborted, {bad_type, _, _}}, mnesia:create_table(Def4)), 1049: 1050: Def2 = [{name, Tab}, {access_mode, read_only}], 1051: ?match({atomic, ok}, mnesia:create_table(Def2)), 1052: ?match({aborted, _}, mnesia:transaction(Write, [nok])), 1053: 1054: ?match({atomic, ok}, mnesia:change_table_access_mode(Tab, read_write)), 1055: ?match({atomic, ok}, mnesia:delete_table(Tab)), 1056: 1057: Def3 = [{name, Tab}, {mnesia_test_lib:storage_type(disc_copies, Config), 1058: [Node1, Node2]}, 1059: {access_mode, read_write}], 1060: ?match({atomic, ok}, mnesia:create_table(Def3)), 1061: ?match({atomic, ok}, mnesia:transaction(Write, [ok])), 1062: ?match({atomic, ok}, mnesia:change_table_access_mode(Tab, read_only)), 1063: ?match({aborted, _}, mnesia:del_table_copy(Tab, Node2)), 1064: ?match({aborted, _}, mnesia:del_table_copy(Tab, Node1)), 1065: ?match({aborted, _}, mnesia:delete_table(Tab)), 1066: ?match({atomic, ok}, mnesia:change_table_access_mode(Tab, read_write)), 1067: 1068: ?match({aborted, {bad_type, _, _}}, 1069: mnesia:change_table_access_mode(Tab, strange_atom)), 1070: ?match({atomic, ok}, mnesia:delete_table(Tab)), 1071: 1072: ?match({aborted, {no_exists, _}}, 1073: mnesia:change_table_access_mode(err_tab, read_only)), 1074: ?match({aborted, {no_exists, _}}, 1075: mnesia:change_table_access_mode([Tab], read_only)), 1076: ?verify_mnesia(Nodes, []). 1077: 1078: change_table_load_order(suite) -> []; 1079: change_table_load_order(Config) when is_list(Config) -> 1080: [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), 1081: Tab1 = load_order_tab1, 1082: Tab2 = load_order_tab2, 1083: Tab3 = load_order_tab3, 1084: 1085: Def = case mnesia_test_lib:diskless(Config) of 1086: true -> [{ram_copies, Nodes}]; 1087: false -> 1088: [{ram_copies, [Node1]}, 1089: {disc_copies, [Node2]}, 1090: {disc_only_copies, [Node3]}] 1091: end, 1092: ?match({atomic, ok}, mnesia:create_table(Tab1, Def)), 1093: ?match({atomic, ok}, mnesia:create_table(Tab2, Def)), 1094: ?match({atomic, ok}, mnesia:create_table(Tab3, Def)), 1095: 1096: ?match({aborted, _}, mnesia:change_table_load_order(Tab1, should_be_integer)), 1097: ?match({aborted, _}, mnesia:change_table_load_order(err_tab, 5)), 1098: ?match({aborted, _}, mnesia:change_table_load_order([err_tab], 5)), 1099: ?match({atomic, ok}, mnesia:change_table_load_order(Tab1, 5)), 1100: ?match({atomic, ok}, mnesia:change_table_load_order(Tab2, 4)), 1101: ?match({atomic, ok}, mnesia:change_table_load_order(Tab3, 73)), 1102: 1103: ?match({aborted, _}, mnesia:change_table_load_order(schema, -32)), 1104: 1105: ?verify_mnesia(Nodes, []). 1106: 1107: set_master_nodes(suite) -> []; 1108: set_master_nodes(Config) when is_list(Config) -> 1109: [Node1, Node2, Node3] = Nodes = ?acquire_nodes(3, Config), 1110: Tab1 = master_node_tab1, 1111: Tab2 = master_node_tab2, 1112: Tab3 = master_node_tab3, 1113: Def1 = [{ram_copies, [Node1, Node2]}], 1114: Def2 = [{disc_copies, [Node2, Node3]}], 1115: Def3 = [{disc_only_copies, [Node3, Node1]}], 1116: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1117: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1118: ?match({atomic, ok}, mnesia:create_table(Tab3, Def3)), 1119: 1120: ?match({error, _}, mnesia:set_master_nodes(schema, ['hopefully@non.existing.node'])), 1121: ?match({error, _}, mnesia:set_master_nodes(badtab, [Node2, Node3])), 1122: ?match({error, _}, mnesia:set_master_nodes(Tab1, [Node3])), 1123: ?match([], mnesia:table_info(Tab1, master_nodes)), 1124: 1125: ?match(ok, mnesia:set_master_nodes(schema, [Node3, Node1])), 1126: ?match([Node3, Node1], mnesia:table_info(schema, master_nodes)), 1127: ?match(ok, mnesia:set_master_nodes(Tab1, [Node2])), 1128: ?match([Node2], mnesia:table_info(Tab1, master_nodes)), 1129: ?match(ok, mnesia:set_master_nodes(Tab1, [Node2, Node1])), 1130: ?match([Node2, Node1], mnesia:table_info(Tab1, master_nodes)), 1131: ?match(ok, mnesia:set_master_nodes(Tab2, [Node2])), % Should set where_to_read to Node2! 1132: ?match([Node2], mnesia:table_info(Tab2, master_nodes)), 1133: ?match(ok, mnesia:set_master_nodes(Tab3, [Node3])), 1134: ?match([Node3], mnesia:table_info(Tab3, master_nodes)), 1135: ?match(ok, mnesia:set_master_nodes(Tab3, [])), 1136: ?match([], mnesia:table_info(Tab3, master_nodes)), 1137: 1138: ?match(ok, mnesia:set_master_nodes([Node1])), 1139: ?match([Node1], mnesia:table_info(schema, master_nodes)), 1140: ?match([Node1], mnesia:table_info(Tab1, master_nodes)), 1141: ?match([], mnesia:table_info(Tab2, master_nodes)), 1142: ?match([Node1], mnesia:table_info(Tab3, master_nodes)), 1143: 1144: ?match(ok, mnesia:set_master_nodes([Node1, Node2])), 1145: ?match([Node1, Node2], mnesia:table_info(schema, master_nodes)), 1146: ?match([Node1, Node2], mnesia:table_info(Tab1, master_nodes)), 1147: ?match([Node2], mnesia:table_info(Tab2, master_nodes)), 1148: ?match([Node1], mnesia:table_info(Tab3, master_nodes)), 1149: 1150: ?verify_mnesia(Nodes, []). 1151: 1152: offline_set_master_nodes(suite) -> []; 1153: offline_set_master_nodes(Config) when is_list(Config) -> 1154: [Node] = Nodes = ?acquire_nodes(1, Config), 1155: Tab1 = offline_master_node_tab1, 1156: Tab2 = offline_master_node_tab2, 1157: Tab3 = offline_master_node_tab3, 1158: Tabs = ?sort([Tab1, Tab2, Tab3]), 1159: Def1 = [{ram_copies, [Node]}], 1160: Def2 = [{disc_copies, [Node]}], 1161: Def3 = [{disc_only_copies, [Node]}], 1162: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1163: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1164: ?match({atomic, ok}, mnesia:create_table(Tab3, Def3)), 1165: ?match([], mnesia:system_info(master_node_tables)), 1166: ?match([], mnesia_test_lib:stop_mnesia([Node])), 1167: 1168: ?match(ok, mnesia:set_master_nodes(Tab1, [Node])), 1169: ?match(ok, mnesia:set_master_nodes(Tab2, [Node])), 1170: ?match(ok, mnesia:set_master_nodes(Tab3, [Node])), 1171: ?match([], mnesia_test_lib:start_mnesia([Node])), 1172: ?match(Tabs, ?sort(mnesia:system_info(master_node_tables))), 1173: 1174: ?match([], mnesia_test_lib:stop_mnesia([Node])), 1175: ?match(ok, mnesia:set_master_nodes(Tab1, [])), 1176: ?match(ok, mnesia:set_master_nodes(Tab2, [])), 1177: ?match(ok, mnesia:set_master_nodes(Tab3, [])), 1178: ?match([], mnesia_test_lib:start_mnesia([Node])), 1179: ?match([], mnesia:system_info(master_node_tables)), 1180: 1181: ?match([], mnesia_test_lib:stop_mnesia([Node])), 1182: ?match(ok, mnesia:set_master_nodes([Node])), 1183: ?match([], mnesia_test_lib:start_mnesia([Node])), 1184: AllTabs = ?sort([schema | Tabs]), 1185: ?match(AllTabs, ?sort(mnesia:system_info(master_node_tables))), 1186: 1187: ?match([], mnesia_test_lib:stop_mnesia([Node])), 1188: ?match(ok, mnesia:set_master_nodes([])), 1189: ?match([], mnesia_test_lib:start_mnesia([Node])), 1190: ?match([], mnesia:system_info(master_node_tables)), 1191: 1192: ?verify_mnesia(Nodes, []). 1193: 1194: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1195: %% Syncronize table with log or disc 1196: %% 1197: 1198: %% Dump ram tables on disc 1199: dump_tables(suite) -> []; 1200: dump_tables(Config) when is_list(Config) -> 1201: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 1202: Tab = dump_tables, 1203: Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node2]}], 1204: ?match({atomic, ok}, mnesia:create_table(Schema)), 1205: 1206: %% Dump 10 records 1207: Size = 10, 1208: Keys = lists:seq(1, Size), 1209: Records = [{Tab, A, 7} || A <- Keys], 1210: lists:foreach(fun(Rec) -> ?match(ok, mnesia:dirty_write(Rec)) end, Records), 1211: 1212: AllKeys = fun() -> ?sort(mnesia:all_keys(Tab)) end, 1213: 1214: ?match({atomic, Keys}, mnesia:transaction(AllKeys)), 1215: ?match({atomic, ok}, mnesia:dump_tables([Tab])), 1216: 1217: %% Delete one record 1218: ?match(ok, mnesia:dirty_delete({Tab, 5})), 1219: Keys2 = lists:delete(5, Keys), 1220: 1221: ?match({atomic, Keys2}, mnesia:transaction(AllKeys)), 1222: 1223: %% Check that all 10 is restored after a stop 1224: ?match([], mnesia_test_lib:stop_mnesia([Node1, Node2])), 1225: ?match([], mnesia_test_lib:start_mnesia([Node1, Node2])), 1226: ?match(ok, mnesia:wait_for_tables([Tab], infinity)), 1227: 1228: ?match({atomic, Keys}, mnesia:transaction(AllKeys)), 1229: 1230: ?match({aborted,Reason} when element(1, Reason) == no_exists, 1231: mnesia:dump_tables([foo])), 1232: ?verify_mnesia(Nodes, []). 1233: 1234: dump_log(suite) -> []; 1235: dump_log(Config) when is_list(Config) -> 1236: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 1237: Tab = dump_log, 1238: Schema = [{name, Tab}, {attributes, [k, v]}, {ram_copies, [Node1, Node2]}], 1239: ?match({atomic, ok}, mnesia:create_table(Schema)), 1240: Tab1 = dump_log1, 1241: Schema1 = [{name, Tab1}, {attributes, [k, v]}, {disc_copies, [Node1]}], 1242: ?match({atomic, ok}, mnesia:create_table(Schema1)), 1243: Tab2 = dump_log2, 1244: Schema2 = [{name, Tab2}, {attributes, [k, v]}, {disc_only_copies, [Node1]}], 1245: ?match({atomic, ok}, mnesia:create_table(Schema2)), 1246: 1247: ?match(ok, mnesia:dirty_write({Tab, 1, ok})), 1248: ?match(ok, mnesia:dirty_write({Tab1, 1, ok})), 1249: ?match(ok, mnesia:dirty_write({Tab2, 1, ok})), 1250: 1251: ?match(dumped, mnesia:dump_log()), 1252: ?match(dumped, rpc:call(Node2, mnesia, dump_log, [])), 1253: 1254: ?match({atomic, ok}, mnesia:change_table_copy_type(schema, Node2, ram_copies)), 1255: ?match(dumped, rpc:call(Node2, mnesia, dump_log, [])), 1256: 1257: Self = self(), 1258: spawn(fun() -> dump_log(100, Self) end), 1259: spawn(fun() -> dump_log(100, Self) end), 1260: 1261: ?match(ok, receive finished -> ok after 3000 -> timeout end), 1262: ?match(ok, receive finished -> ok after 3000 -> timeout end), 1263: 1264: ?verify_mnesia(Nodes, []). 1265: 1266: dump_log(N, Tester) when N > 0 -> 1267: mnesia:dump_log(), 1268: dump_log(N-1, Tester); 1269: dump_log(_, Tester) -> 1270: Tester ! finished. 1271: 1272: 1273: wait_for_tables(doc) -> 1274: ["Intf. test of wait_for_tables, see also force_load_table"]; 1275: wait_for_tables(suite) -> []; 1276: wait_for_tables(Config) when is_list(Config) -> 1277: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 1278: Tab = wf_tab, 1279: Schema = [{name, Tab}, {ram_copies, [Node1, Node2]}], 1280: ?match({atomic, ok}, mnesia:create_table(Schema)), 1281: ?match(ok, mnesia:wait_for_tables([wf_tab], infinity)), 1282: ?match(ok, mnesia:wait_for_tables([], timer:seconds(5))), 1283: ?match({timeout, [bad_tab]}, mnesia:wait_for_tables([bad_tab], timer:seconds(5))), 1284: ?match(ok, mnesia:wait_for_tables([wf_tab], 0)), 1285: ?match({error,_}, mnesia:wait_for_tables([wf_tab], -1)), 1286: ?verify_mnesia(Nodes, []). 1287: 1288: force_load_table(suite) -> []; 1289: force_load_table(Config) when is_list(Config) -> 1290: [Node1, Node2] = ?acquire_nodes(2, Config), 1291: Tab = wf_tab, 1292: 1293: Schema = [{name, Tab}, {disc_copies, [Node1, Node2]}], 1294: ?match({atomic, ok}, mnesia:create_table(Schema)), 1295: ?match(ok, mnesia:dirty_write({Tab, 1, test_ok})), 1296: mnesia_test_lib:kill_mnesia([Node1]), 1297: ?match(ok, rpc:call(Node2, mnesia, dirty_write, [{Tab, 1, test_nok}])), 1298: mnesia_test_lib:kill_mnesia([Node2]), 1299: %% timer:sleep(timer:seconds(5)), 1300: ?match(ok, mnesia:start()), 1301: ?match({timeout, [Tab]}, mnesia:wait_for_tables([Tab], 5)), 1302: ?match({'EXIT', _}, mnesia:dirty_read({Tab, 1})), 1303: ?match(yes, mnesia:force_load_table(Tab)), 1304: ?match([{Tab, 1, test_ok}], mnesia:dirty_read({Tab, 1})), 1305: 1306: ?match({error, _}, mnesia:force_load_table(error_tab)), 1307: ?verify_mnesia([Node1], [Node2]). 1308: 1309: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1310: 1311: user_properties(doc) -> 1312: ["Test of reading, writing and deletion of user properties", 1313: "Plus initialization of user properties when a table is created", 1314: "Do also test mnesia:table_info(Tab, user_properties)"]; 1315: user_properties(suite) -> []; 1316: user_properties(Config) when is_list(Config) -> 1317: [Node] = Nodes = ?acquire_nodes(1, Config), 1318: Tab1 = user_properties_1, 1319: Tab2 = user_properties_2, 1320: Tab3 = user_properties_3, 1321: Def1 = [{ram_copies, [Node]}, {user_properties, []}], 1322: Def2 = [{mnesia_test_lib:storage_type(disc_copies, Config), [Node]}], 1323: Def3 = [{mnesia_test_lib:storage_type(disc_only_copies, Config), [Node]}, 1324: {user_properties, []}], 1325: 1326: PropKey = my_prop, 1327: Prop = {PropKey, some, elements}, 1328: Prop2 = {PropKey, some, other, elements}, 1329: YourProp= {your_prop}, 1330: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1331: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1332: ?match({atomic, ok}, mnesia:create_table(Tab3, Def3)), 1333: 1334: ?match([], mnesia:table_info(Tab1, user_properties)), 1335: ?match([], mnesia:table_info(Tab2, user_properties)), 1336: ?match([], mnesia:table_info(Tab3, user_properties)), 1337: 1338: ?match({'EXIT', {no_exists, {Tab1, user_property, PropKey}}}, 1339: mnesia:read_table_property(Tab1, PropKey)), 1340: ?match({'EXIT', {no_exists, {Tab2, user_property, PropKey}}}, 1341: mnesia:read_table_property(Tab2, PropKey)), 1342: ?match({'EXIT', {no_exists, {Tab3, user_property, PropKey}}}, 1343: mnesia:read_table_property(Tab3, PropKey)), 1344: 1345: ?match({atomic, ok}, mnesia:write_table_property(Tab1, Prop)), 1346: ?match({atomic, ok}, mnesia:write_table_property(Tab2, Prop)), 1347: ?match({atomic, ok}, mnesia:write_table_property(Tab3, Prop)), 1348: ?match({atomic, ok}, mnesia:write_table_property(Tab1, YourProp)), 1349: ?match({atomic, ok}, mnesia:write_table_property(Tab2, YourProp)), 1350: ?match({atomic, ok}, mnesia:write_table_property(Tab3, YourProp)), 1351: 1352: ?match(Prop, mnesia:read_table_property(Tab1, PropKey)), 1353: ?match(Prop, mnesia:read_table_property(Tab2, PropKey)), 1354: ?match(Prop, mnesia:read_table_property(Tab3, PropKey)), 1355: 1356: ?match({atomic, ok}, mnesia:write_table_property(Tab1, Prop2)), 1357: ?match({atomic, ok}, mnesia:write_table_property(Tab2, Prop2)), 1358: ?match({atomic, ok}, mnesia:write_table_property(Tab3, Prop2)), 1359: ?match(Prop2, mnesia:read_table_property(Tab1, PropKey)), 1360: ?match(Prop2, mnesia:read_table_property(Tab2, PropKey)), 1361: ?match(Prop2, mnesia:read_table_property(Tab3, PropKey)), 1362: 1363: ?match({atomic, ok}, mnesia:delete_table_property(Tab1, PropKey)), 1364: ?match({atomic, ok}, mnesia:delete_table_property(Tab2, PropKey)), 1365: ?match({atomic, ok}, mnesia:delete_table_property(Tab3, PropKey)), 1366: 1367: ?match([YourProp], mnesia:table_info(Tab1, user_properties)), 1368: ?match([YourProp], mnesia:table_info(Tab2, user_properties)), 1369: ?match([YourProp], mnesia:table_info(Tab3, user_properties)), 1370: 1371: Tab4 = user_properties_4, 1372: ?match({atomic, ok}, 1373: mnesia:create_table(Tab4, [{user_properties, [Prop]}])), 1374: 1375: ?match([Prop], mnesia:table_info(Tab4, user_properties)), 1376: 1377: %% Some error cases 1378: 1379: ?match({aborted, {bad_type, Tab1, {}}}, 1380: mnesia:write_table_property(Tab1, {})), 1381: ?match({aborted, {bad_type, Tab1, ali}}, 1382: mnesia:write_table_property(Tab1, ali)), 1383: 1384: Tab5 = user_properties_5, 1385: ?match({aborted, {bad_type, Tab5, {user_properties, {}}}}, 1386: mnesia:create_table(Tab5, [{user_properties, {}}])), 1387: ?match({aborted, {bad_type, Tab5, {user_properties, ali}}}, 1388: mnesia:create_table(Tab5, [{user_properties, ali}])), 1389: ?match({aborted, {bad_type, Tab5, {user_properties, [{}]}}}, 1390: mnesia:create_table(Tab5, [{user_properties, [{}]}])), 1391: ?match({aborted, {bad_type, Tab5, {user_properties, [ali]}}}, 1392: mnesia:create_table(Tab5, [{user_properties, [ali]}])), 1393: 1394: ?verify_mnesia(Nodes, []). 1395: 1396: 1397: unsupp_user_props(doc) -> 1398: ["Simple test of adding user props in a schema_transaction"]; 1399: unsupp_user_props(suite) -> []; 1400: unsupp_user_props(Config) when is_list(Config) -> 1401: [Node1] = ?acquire_nodes(1, Config), 1402: Tab1 = silly1, 1403: Tab2 = silly2, 1404: Storage = mnesia_test_lib:storage_type(ram_copies, Config), 1405: 1406: ?match({atomic, ok}, rpc:call(Node1, mnesia, 1407: create_table, [Tab1, [{Storage, [Node1]}]])), 1408: ?match({atomic, ok}, rpc:call(Node1, mnesia, 1409: create_table, [Tab2, [{Storage, [Node1]}]])), 1410: 1411: F1 = fun() -> 1412: mnesia_schema:do_write_table_property( 1413: silly1, {prop, propval1}), 1414: mnesia_schema:do_write_table_property( 1415: silly2, {prop, propval2}), % same key as above 1416: mnesia_schema:do_write_table_property( 1417: schema, {prop, propval3}) % same key as above 1418: end, 1419: ?match({atomic, ok}, rpc:call(Node1, mnesia_schema, 1420: schema_transaction, [F1])), 1421: 1422: ?match([{prop,propval1}], rpc:call(Node1, mnesia, 1423: table_info, [silly1, user_properties])), 1424: ?match([{prop,propval2}], rpc:call(Node1, mnesia, 1425: table_info, [silly2, user_properties])), 1426: ?match([{prop,propval3}], rpc:call(Node1, mnesia, 1427: table_info, [schema, user_properties])), 1428: 1429: F2 = fun() -> 1430: mnesia_schema:do_write_table_property( 1431: silly1, {prop, propval1a}), 1432: mnesia_schema:do_write_table_property( 1433: silly1, {prop, propval1b}) % same key as above 1434: end, 1435: ?match({atomic, ok}, rpc:call(Node1, mnesia_schema, 1436: schema_transaction, [F2])), 1437: 1438: ?match([{prop,propval1b}], rpc:call(Node1, mnesia, 1439: table_info, 1440: [silly1, user_properties])), 1441: ?verify_mnesia([Node1], []). 1442: 1443: 1444: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1445: 1446: 1447: snmp_open_table(suite) -> []; 1448: snmp_open_table(Config) when is_list(Config) -> 1449: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 1450: Tab1 = local_snmp_table, 1451: 1452: Storage = mnesia_test_lib:storage_type(disc_copies, Config), 1453: Def1 = 1454: case mnesia_test_lib:diskless(Config) of 1455: true -> [{ram_copies, Nodes}]; 1456: false -> 1457: [{disc_copies, [Node1]}, {ram_copies, [Node2]}] 1458: end, 1459: 1460: Tab2 = ext_snmp_table, 1461: Def2 = [{Storage, [Node2]}], 1462: ErrTab = non_existing_tab, 1463: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1464: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1465: ?match({atomic, ok}, mnesia:snmp_open_table(Tab1, [{key, integer}])), 1466: ?match({atomic, ok}, mnesia:snmp_open_table(Tab2, [{key, integer}])), 1467: ?match({aborted, _}, mnesia:snmp_open_table(ErrTab, [{key, integer}])), 1468: ?verify_mnesia(Nodes, []). 1469: 1470: snmp_close_table(suite) -> []; 1471: snmp_close_table(Config) when is_list(Config) -> 1472: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 1473: Tab1 = local_snmp_table, 1474: Storage = mnesia_test_lib:storage_type(disc_copies, Config), 1475: Def1 = 1476: case mnesia_test_lib:diskless(Config) of 1477: true -> [{ram_copies, Nodes}]; 1478: false -> 1479: [{disc_copies, [Node1]}, {ram_copies, [Node2]}] 1480: end, 1481: 1482: Tab2 = ext_snmp_table, 1483: Def2 = [{snmp, [{key, integer}]}, {Storage, [Node2]}], 1484: ErrTab = non_existing_tab, 1485: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1486: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1487: ?match({atomic, ok}, mnesia:create_table(no_snmp_tab, [])), 1488: add_some_records(Tab1, Tab2, 3), 1489: ?match({atomic, ok}, mnesia:snmp_open_table(Tab1, [{key, integer}])), 1490: add_some_records(Tab1, Tab2, 5), 1491: ?match({atomic, ok}, mnesia:snmp_close_table(Tab1)), 1492: 1493: Transform = fun(Tab, Key) -> 1494: [{T,K,V}] = mnesia:read(Tab, Key, write), 1495: mnesia:delete(T,K, write), 1496: mnesia:write({T, {K,K}, V, 43+V}) 1497: end, 1498: 1499: ?match({atomic, ok}, mnesia:transform_table(Tab1, ignore, [key,val,new])), 1500: ?match({atomic, ok}, 1501: mnesia:transaction(fun() -> 1502: mnesia:write_lock_table(Tab1), 1503: Keys = mnesia:select(Tab1, [{{'_','$1','_'}, [], 1504: ['$1']}]), 1505: [Transform(Tab1, Key) || Key <- Keys], 1506: ok 1507: end)), 1508: ?match([{Tab1, {1, 1}, 1, 44}], mnesia:dirty_read(Tab1, {1, 1})), 1509: ?match({atomic, ok}, mnesia:snmp_open_table(Tab1, [{key,{integer,integer}}])), 1510: 1511: ?match({atomic, ok}, mnesia:snmp_close_table(Tab2)), 1512: ?match({atomic, ok}, mnesia:transform_table(Tab2, ignore, [key,val,new])), 1513: ?match({atomic, ok}, 1514: mnesia:transaction(fun() -> 1515: mnesia:write_lock_table(Tab2), 1516: Keys = mnesia:select(Tab2, [{{'_','$1','_'}, [], 1517: ['$1']}]), 1518: [Transform(Tab2, Key) || Key <- Keys], 1519: ok 1520: end)), 1521: 1522: ?match({atomic, ok}, mnesia:snmp_open_table(Tab2, [{key,{integer,integer}}])), 1523: 1524: %% Should be aborted ???? 1525: ?match({atomic, ok}, mnesia:snmp_close_table(no_snmp_tab)), 1526: ?match({aborted, _}, mnesia:snmp_close_table(ErrTab)), 1527: ?verify_mnesia(Nodes, []). 1528: 1529: snmp_get_next_index(suite) -> []; 1530: snmp_get_next_index(Config) when is_list(Config) -> 1531: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 1532: Tab1 = local_snmp_table, 1533: Storage = mnesia_test_lib:storage_type(disc_copies, Config), 1534: Def1 = 1535: case mnesia_test_lib:diskless(Config) of 1536: true -> [{ram_copies, Nodes}]; 1537: false -> 1538: [{disc_copies, [Node1]}, {ram_copies, [Node2]}] 1539: end, 1540: 1541: Tab2 = ext_snmp_table, 1542: Def2 = [{Storage, [Node2]}], 1543: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1544: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1545: ?match({atomic, ok}, mnesia:snmp_open_table(Tab1, [{key, integer}])), 1546: ?match({atomic, ok}, mnesia:snmp_open_table(Tab2, [{key, integer}])), 1547: add_some_records(Tab1, Tab2, 1), 1548: Test = 1549: fun() -> 1550: %% Test local tables 1551: {success, Res11} = ?match({ok, _}, mnesia:snmp_get_next_index(Tab1,[])), 1552: {ok, Index11} = Res11, 1553: {success, _Res12} = 1554: ?match(endOfTable, mnesia:snmp_get_next_index(Tab1, Index11)), 1555: ?match({'EXIT',_}, mnesia:snmp_get_next_index(Tab1, endOfTable)), 1556: 1557: %% Test external table 1558: {success, Res21} = 1559: ?match({ok, _}, mnesia:snmp_get_next_index(Tab2, [])), 1560: {ok, Index21} = Res21, 1561: {success, _Res22} = 1562: ?match(endOfTable, mnesia:snmp_get_next_index(Tab2, Index21)), 1563: 1564: {ok, Row} = mnesia:snmp_get_row(Tab1, Index11), 1565: ?match(ok, mnesia:dirty_delete(Tab1, hd(Index11))), 1566: 1567: ?match(endOfTable, mnesia:snmp_get_next_index(Tab1,[])), 1568: 1569: ok = mnesia:dirty_write(Row), %% Reset to coming tests 1570: 1571: %% Test of non existing table 1572: %%?match(endOfTable, mnesia:snmp_get_next_index(ErrTab, [])), 1573: ok 1574: end, 1575: ?match(ok, Test()), 1576: ?match({atomic,ok}, mnesia:transaction(Test)), 1577: ?match(ok, mnesia:sync_dirty(Test)), 1578: ?match(ok, mnesia:activity(transaction,Test,mnesia)), 1579: 1580: %%io:format("**********Before ~p~n", [mnesia_lib:val({Tab1,snmp})]), 1581: %%io:format(" ~p ~n", [ets:tab2list(mnesia_lib:val({local_snmp_table,{index,snmp}}))]), 1582: ?match([], mnesia_test_lib:stop_mnesia(Nodes)), 1583: ?match([], mnesia_test_lib:start_mnesia(Nodes, [Tab1, Tab2])), 1584: %%io:format("**********After ~p~n", [mnesia_lib:val({Tab1,snmp})]), 1585: %%io:format(" ~p ~n", [ets:tab2list(mnesia_lib:val({local_snmp_table,{index,snmp}}))]), 1586: 1587: ?match(ok, Test()), 1588: ?match({atomic,ok}, mnesia:transaction(Test)), 1589: ?match(ok, mnesia:sync_dirty(Test)), 1590: ?match(ok, mnesia:activity(transaction,Test,mnesia)), 1591: 1592: ?verify_mnesia(Nodes, []). 1593: 1594: add_some_records(Tab1, Tab2, N) -> 1595: Recs1 = [{Tab1, I, I} || I <- lists:reverse(lists:seq(1, N))], 1596: Recs2 = [{Tab2, I, I} || I <- lists:reverse(lists:seq(20, 20+N-1))], 1597: lists:foreach(fun(R) -> mnesia:dirty_write(R) end, Recs1), 1598: Fun = fun(R) -> mnesia:write(R) end, 1599: Trans = fun() -> lists:foreach(Fun, Recs2) end, 1600: {atomic, ok} = mnesia:transaction(Trans), 1601: %% Sync things, so everything gets everywhere! 1602: {atomic, ok} = mnesia:sync_transaction(fun() -> mnesia:write(lists:last(Recs1)) end), 1603: {atomic, ok} = mnesia:sync_transaction(fun() -> mnesia:write(lists:last(Recs2)) end), 1604: ?sort(Recs1 ++ Recs2). 1605: 1606: snmp_get_row(suite) -> []; 1607: snmp_get_row(Config) when is_list(Config) -> 1608: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 1609: Tab1 = local_snmp_table, 1610: Storage = mnesia_test_lib:storage_type(disc_copies, Config), 1611: Def1 = 1612: case mnesia_test_lib:diskless(Config) of 1613: true -> [{ram_copies, Nodes}]; 1614: false -> 1615: [{disc_copies, [Node1]}, {ram_copies, [Node2]}] 1616: end, 1617: Tab2 = ext_snmp_table, 1618: Def2 = [{Storage, [Node2]}], 1619: Tab3 = snmp_table, 1620: Def3 = [{Storage, [Node1]}, 1621: {attributes, [key, data1, data2]}], 1622: 1623: Setup = fun() -> 1624: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1625: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1626: ?match({atomic, ok}, mnesia:create_table(Tab3, Def3)), 1627: ?match({atomic, ok}, mnesia:snmp_open_table(Tab1, [{key, integer}])), 1628: ?match({atomic, ok}, mnesia:snmp_open_table(Tab2, [{key, integer}])), 1629: ?match({atomic, ok}, mnesia:snmp_open_table( 1630: Tab3, [{key, {fix_string,integer}}])), 1631: add_some_records(Tab1, Tab2, 1) 1632: end, 1633: Clear = fun() -> 1634: ?match({atomic, ok}, mnesia:delete_table(Tab1)), 1635: ?match({atomic, ok}, mnesia:delete_table(Tab2)), 1636: ?match({atomic, ok}, mnesia:delete_table(Tab3)) 1637: end, 1638: Test = 1639: fun() -> 1640: %% Test local tables 1641: {success, Res11} = 1642: ?match({ok, [1]}, mnesia:snmp_get_next_index(Tab1,[])), 1643: {ok, Index11} = Res11, 1644: ?match({ok, {Tab1,1,1}}, mnesia:snmp_get_row(Tab1, Index11)), 1645: ?match(endOfTable, mnesia:snmp_get_next_index(Tab1, Index11)), 1646: ?match({'EXIT',_}, mnesia:snmp_get_row(Tab1, endOfTable)), 1647: ?match(undefined, mnesia:snmp_get_row(Tab1, [73])), 1648: 1649: Add = fun() -> mnesia:write({Tab3, {"f_string", 3}, data1, data2}) end, 1650: ?match({atomic, ok}, mnesia:transaction(Add)), 1651: {success, {ok, Index31}} = ?match({ok, RowIndex31} when is_list(RowIndex31), 1652: mnesia:snmp_get_next_index(Tab3,[])), 1653: ?match({ok, Row31} when is_tuple(Row31), 1654: mnesia:snmp_get_row(Tab3, Index31)), 1655: ?match(endOfTable, mnesia:snmp_get_next_index(Tab3, Index31)), 1656: Del = fun() -> mnesia:delete({Tab3,{"f_string",3}}) end, 1657: ?match({atomic, ok}, mnesia:transaction(Del)), 1658: ?match(undefined, mnesia:snmp_get_row(Tab3, "f_string" ++ [3])), 1659: ?match(undefined, mnesia:snmp_get_row(Tab3, "f_string" ++ [73])), 1660: 1661: %% Test external table 1662: {success, Res21} = ?match({ok,[20]}, mnesia:snmp_get_next_index(Tab2, [])), 1663: {ok, Index21} = Res21, 1664: ?match({ok, Row2} when is_tuple(Row2), mnesia:snmp_get_row(Tab2, Index21)), 1665: ?match(endOfTable, mnesia:snmp_get_next_index(Tab2, Index21)), 1666: %% Test of non existing table 1667: %% ?match(endOfTable, mnesia:snmp_get_next_index(ErrTab, [])), 1668: ok 1669: end, 1670: Setup(), 1671: ?match(ok, Test()), 1672: Clear(), Setup(), 1673: ?match({atomic,ok}, mnesia:transaction(Test)), 1674: Clear(), Setup(), 1675: ?match(ok, mnesia:sync_dirty(Test)), 1676: Clear(), Setup(), 1677: ?match(ok, mnesia:activity(transaction,Test,mnesia)), 1678: 1679: Clear(), Setup(), 1680: ?match([], mnesia_test_lib:stop_mnesia(Nodes)), 1681: ?match([], mnesia_test_lib:start_mnesia(Nodes, [Tab1, Tab2])), 1682: ?match(ok, Test()), 1683: Clear(), Setup(), 1684: ?match([], mnesia_test_lib:stop_mnesia(Nodes)), 1685: ?match([], mnesia_test_lib:start_mnesia(Nodes, [Tab1, Tab2])), 1686: ?match({atomic,ok}, mnesia:transaction(Test)), 1687: 1688: ?verify_mnesia(Nodes, []). 1689: 1690: snmp_get_mnesia_key(suite) -> []; 1691: snmp_get_mnesia_key(Config) when is_list(Config) -> 1692: [Node1, Node2] = Nodes = ?acquire_nodes(2, Config), 1693: Tab1 = local_snmp_table, 1694: Storage = mnesia_test_lib:storage_type(disc_copies, Config), 1695: Def1 = 1696: case mnesia_test_lib:diskless(Config) of 1697: true -> [{ram_copies, Nodes}]; 1698: false -> 1699: [{disc_copies, [Node1]}, {ram_copies, [Node2]}] 1700: end, 1701: 1702: Tab2 = ext_snmp_table, 1703: Def2 = [{Storage, [Node2]}], 1704: 1705: Tab3 = fix_string, 1706: Setup = fun() -> 1707: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1708: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1709: ?match({atomic, ok}, mnesia:create_table(Tab3, Def1)), 1710: ?match({atomic, ok}, mnesia:snmp_open_table(Tab1, [{key, integer}])), 1711: ?match({atomic, ok}, mnesia:snmp_open_table(Tab2, [{key, integer}])), 1712: ?match({atomic, ok}, mnesia:snmp_open_table(Tab3, [{key, {fix_string,integer}}])), 1713: 1714: add_some_records(Tab1, Tab2, 1) 1715: end, 1716: Clear = fun() -> 1717: ?match({atomic, ok}, mnesia:delete_table(Tab1)), 1718: ?match({atomic, ok}, mnesia:delete_table(Tab2)), 1719: ?match({atomic, ok}, mnesia:delete_table(Tab3)) 1720: end, 1721: Test = 1722: fun() -> 1723: %% Test local tables 1724: {success, Res11} = 1725: ?match({ok, [1]}, mnesia:snmp_get_next_index(Tab1,[])), 1726: {ok, Index11} = Res11, 1727: ?match({ok, 1}, mnesia:snmp_get_mnesia_key(Tab1, Index11)), 1728: %% Test external tables 1729: {success, Res21} = 1730: ?match({ok, [20]}, mnesia:snmp_get_next_index(Tab2, [])), 1731: {ok, Index21} = Res21, 1732: ?match({ok, 20}, mnesia:snmp_get_mnesia_key(Tab2, Index21)), 1733: ?match(undefined, mnesia:snmp_get_mnesia_key(Tab2, [97])), 1734: ?match({'EXIT', _}, mnesia:snmp_get_mnesia_key(Tab2, 97)), 1735: 1736: ?match({atomic,ok}, mnesia:transaction(fun() -> mnesia:delete({Tab1,1}) end)), 1737: ?match(undefined, mnesia:snmp_get_mnesia_key(Tab1, Index11)), 1738: 1739: ?match({atomic,ok},mnesia:transaction(fun() -> mnesia:write({Tab1,73,7}) end)), 1740: ?match({ok, 73}, mnesia:snmp_get_mnesia_key(Tab1, [73])), 1741: ?match({atomic,ok}, mnesia:transaction(fun() -> mnesia:delete({Tab1,73}) end)), 1742: ?match(undefined, mnesia:snmp_get_mnesia_key(Tab1, [73])), 1743: 1744: ?match({atomic,ok},mnesia:transaction(fun() -> mnesia:write({Tab3,{"S",5},7}) end)), 1745: ?match({ok,{"S",5}}, mnesia:snmp_get_mnesia_key(Tab3, [$S,5])), 1746: ?match({atomic,ok},mnesia:transaction(fun() -> mnesia:delete({Tab3,{"S",5}}) end)), 1747: ?match(undefined, mnesia:snmp_get_mnesia_key(Tab3, [$S,5])), 1748: 1749: ok 1750: end, 1751: Setup(), 1752: ?match(ok, Test()), 1753: Clear(), Setup(), 1754: ?match({atomic,ok}, mnesia:transaction(Test)), 1755: Clear(), Setup(), 1756: ?match(ok, mnesia:sync_dirty(Test)), 1757: Clear(), Setup(), 1758: ?match(ok, mnesia:activity(transaction,Test,mnesia)), 1759: ?verify_mnesia(Nodes, []). 1760: 1761: snmp_update_counter(doc) -> 1762: ["Verify that counters may be updated for tables with SNMP property"]; 1763: snmp_update_counter(suite) -> []; 1764: snmp_update_counter(Config) when is_list(Config) -> 1765: [Node1] = Nodes = ?acquire_nodes(1, Config), 1766: Tab = snmp_update_counter, 1767: Def = [{attributes, [key, value]}, 1768: {snmp, [{key, integer}]}, 1769: {ram_copies, [Node1]} 1770: ], 1771: ?match({atomic, ok}, mnesia:create_table(Tab, Def)), 1772: Oid = {Tab, 1}, 1773: ?match([], mnesia:dirty_read(Oid)), 1774: ?match(ok, mnesia:dirty_write({Tab, 1, 1})), 1775: ?match([{Tab, _Key, 1}], mnesia:dirty_read(Oid)), 1776: ?match(3, mnesia:dirty_update_counter(Oid, 2)), 1777: ?match([{Tab, _Key, 3}], mnesia:dirty_read(Oid)), 1778: ?verify_mnesia(Nodes, []). 1779: 1780: snmp_order(doc) -> 1781: ["Verify that sort order is correct in transactions and dirty variants"]; 1782: snmp_order(suite) -> []; 1783: snmp_order(Config) when is_list(Config) -> 1784: [Node1] = Nodes = ?acquire_nodes(1, Config), 1785: Tab = snmp_order, 1786: Def = [{attributes, [key, value]}, 1787: {snmp, [{key, {integer, integer, integer}}]}, 1788: {ram_copies, [Node1]} 1789: ], 1790: ?match({atomic, ok}, mnesia:create_table(Tab, Def)), 1791: Oid = {Tab, 1}, 1792: ?match([], mnesia:dirty_read(Oid)), 1793: ?match({'EXIT', {aborted, _}}, mnesia:dirty_write({Tab, 1, 1})), 1794: [mnesia:dirty_write({Tab, {A,B,2}, default}) || 1795: A <- lists:seq(1, 9, 2), 1796: B <- lists:seq(2, 8, 2)], 1797: 1798: Test1 = fun() -> 1799: Keys0 = get_keys(Tab, []), 1800: ?match(Keys0, lists:sort(Keys0)), 1801: ?match([[1,2,2]|_], Keys0), 1802: Keys1 = get_keys(Tab, [5]), 1803: ?match(Keys1, lists:sort(Keys1)), 1804: ?match([[5,2,2]|_], Keys1), 1805: Keys2 = get_keys(Tab, [7, 4]), 1806: ?match(Keys2, lists:sort(Keys2)), 1807: ?match([[7,4,2]|_], Keys2), 1808: ok 1809: end, 1810: ?match(ok, Test1()), 1811: ?match({atomic, ok},mnesia:transaction(Test1)), 1812: ?match(ok,mnesia:sync_dirty(Test1)), 1813: 1814: Test2 = fun() -> 1815: mnesia:write(Tab, {Tab,{0,0,2},updated}, write), 1816: mnesia:write(Tab, {Tab,{5,3,2},updated}, write), 1817: mnesia:write(Tab, {Tab,{10,10,2},updated}, write), 1818: Keys0 = get_keys(Tab, []), 1819: ?match([[0,0,2],[1,2,2]|_], Keys0), 1820: ?match(Keys0, lists:sort(Keys0)), 1821: 1822: Keys1 = get_keys(Tab, [5]), 1823: ?match([[5,2,2],[5,3,2]|_], Keys1), 1824: ?match(Keys1, lists:sort(Keys1)), 1825: 1826: Keys2 = get_keys(Tab, [7,4]), 1827: ?match([[7,4,2]|_], Keys2), 1828: ?match(Keys2, lists:sort(Keys2)), 1829: ?match([10,10,2], lists:last(Keys0)), 1830: ?match([10,10,2], lists:last(Keys1)), 1831: ?match([10,10,2], lists:last(Keys2)), 1832: 1833: ?match([[10,10,2]], get_keys(Tab, [10])), 1834: ok 1835: end, 1836: 1837: ?match({atomic, ok},mnesia:transaction(Test2)), 1838: 1839: ?verify_mnesia(Nodes, []). 1840: 1841: get_keys(Tab, Key) -> 1842: case mnesia:snmp_get_next_index(Tab, Key) of 1843: endOfTable -> []; 1844: {ok, Next} -> 1845: [Next|get_keys(Tab, Next)] 1846: end. 1847: 1848: 1849: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1850: 1851: -record(tab, {i, e1, e2}). % Simple test table 1852: 1853: 1854: subscribe_extended(doc) -> 1855: ["Test the extended set of events, test with and without checkpoints. "]; 1856: subscribe_extended(suite) -> 1857: []; 1858: subscribe_extended(Config) when is_list(Config) -> 1859: [N1, N2]=Nodes=?acquire_nodes(2, Config), 1860: Tab1 = etab, 1861: Storage = mnesia_test_lib:storage_type(ram_copies, Config), 1862: Def1 = [{Storage, [N1, N2]}, {attributes, record_info(fields, tab)}], 1863: ?match({atomic, ok}, mnesia:create_table(Tab1, Def1)), 1864: 1865: Tab2 = bag, 1866: Def2 = [{Storage, [N1, N2]}, 1867: {type, bag}, 1868: {record_name, Tab1}, 1869: {attributes, record_info(fields, tab)}], 1870: ?match({atomic, ok}, mnesia:create_table(Tab2, Def2)), 1871: 1872: Tab3 = ctab, 1873: Def3 = [{Storage, [N1, N2]}], 1874: ?match({atomic, ok}, mnesia:create_table(Tab3, Def3)), 1875: 1876: ?match({ok, N1}, mnesia:subscribe({table, Tab1, detailed})), 1877: ?match({ok, N1}, mnesia:subscribe({table, Tab2, detailed})), 1878: ?match({ok, N1}, mnesia:subscribe({table, Tab3, detailed})), 1879: 1880: ?match({error, {already_exists, _}}, mnesia:subscribe({table, Tab1, simple})), 1881: ?match({error, {badarg, {table, Tab1, bad}}}, mnesia:subscribe({table, Tab1, bad})), 1882: 1883: ?match({ok, N1}, mnesia:subscribe(activity)), 1884: test_ext_sub(Tab1, Tab2, Tab3), 1885: 1886: ?match({ok, N1}, mnesia:unsubscribe(activity)), 1887: ?match({ok, N1}, mnesia:subscribe({table, Tab1, detailed})), 1888: ?match({atomic, ok}, mnesia:clear_table(Tab1)), 1889: ?match({mnesia_table_event, {delete, schema, {schema, Tab1}, [{schema, Tab1, _}],_}}, recv_event()), 1890: ?match({mnesia_table_event, {write, schema, {schema, Tab1, _}, [], _}}, recv_event()), 1891: 1892: ?match({atomic, ok}, mnesia:clear_table(Tab2)), 1893: ?match({mnesia_table_event, {delete, schema, {schema, Tab2}, [{schema, Tab2, _}],_}}, 1894: recv_event()), 1895: ?match({mnesia_table_event, {write, schema, {schema, Tab2, _}, [], _}}, recv_event()), 1896: 1897: ?match({ok, N1}, mnesia:unsubscribe({table, Tab2, detailed})), 1898: {ok, _, _} = mnesia:activate_checkpoint([{name, testing}, 1899: {ram_overrides_dump, true}, 1900: {max, [Tab1, Tab2]}]), 1901: ?match({ok, N1}, mnesia:subscribe({table, Tab2, detailed})), 1902: ?match({ok, N1}, mnesia:subscribe(activity)), 1903: test_ext_sub(Tab1, Tab2, Tab3), 1904: 1905: ?verify_mnesia(Nodes, []). 1906: 1907: test_ext_sub(Tab1, Tab2, Tab3) -> 1908: %% The basics 1909: Rec1 = {Tab1, 1, 0, 0}, 1910: Rec2 = {Tab1, 1, 1, 0}, 1911: Rec3 = {Tab1, 2, 1, 0}, 1912: Rec4 = {Tab1, 2, 2, 0}, 1913: 1914: Write = fun(Tab, Rec) -> 1915: mnesia:transaction(fun() -> mnesia:write(Tab, Rec, write) 1916: end) 1917: end, 1918: Delete = fun(Tab, Rec) -> 1919: mnesia:transaction(fun() -> mnesia:delete(Tab, Rec, write) 1920: end) 1921: end, 1922: DelObj = fun(Tab, Rec) -> 1923: mnesia:transaction(fun() -> mnesia:delete_object(Tab, Rec, write) 1924: end) 1925: end, 1926: 1927: S = self(), 1928: D = {dirty, self()}, 1929: %% SET 1930: ?match(ok, mnesia:dirty_write(Rec1)), 1931: ?match({mnesia_table_event, {write, Tab1, Rec1, [], D}}, recv_event()), 1932: ?match(ok, mnesia:dirty_write(Rec3)), 1933: ?match({mnesia_table_event, {write, Tab1, Rec3, [], D}}, recv_event()), 1934: ?match(ok, mnesia:dirty_write(Rec1)), 1935: ?match({mnesia_table_event, {write, Tab1, Rec1, [Rec1], D}}, recv_event()), 1936: ?match({atomic, ok}, Write(Tab1, Rec2)), 1937: ?match({mnesia_table_event, {write, Tab1, Rec2, [Rec1], {tid,_,S}}}, recv_event()), 1938: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1939: ?match(ok, mnesia:dirty_delete({Tab1, 2})), 1940: ?match({mnesia_table_event, {delete, Tab1, {Tab1, 2}, [Rec3], D}}, recv_event()), 1941: ?match({atomic, ok}, DelObj(Tab1, Rec2)), 1942: ?match({mnesia_table_event, {delete, Tab1, Rec2, [Rec2], {tid,_,S}}}, recv_event()), 1943: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1944: 1945: ?match({atomic, ok}, Delete(Tab1, 1)), 1946: ?match({mnesia_table_event, {delete, Tab1, {Tab1, 1}, [], {tid,_,S}}}, recv_event()), 1947: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1948: ?match({ok, _N1}, mnesia:unsubscribe({table, Tab1, detailed})), 1949: 1950: %% BAG 1951: 1952: ?match({atomic, ok}, Write(Tab2, Rec1)), 1953: ?match({mnesia_table_event, {write, Tab2, Rec1, [], {tid,_,S}}}, recv_event()), 1954: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1955: ?match({atomic, ok}, Write(Tab2, Rec4)), 1956: ?match({mnesia_table_event, {write, Tab2, Rec4, [], {tid,_,S}}}, recv_event()), 1957: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1958: ?match({atomic, ok}, Write(Tab2, Rec3)), 1959: ?match({mnesia_table_event, {write, Tab2, Rec3, [Rec4], {tid,_,S}}}, recv_event()), 1960: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1961: ?match({atomic, ok}, Write(Tab2, Rec2)), 1962: ?match({mnesia_table_event, {write, Tab2, Rec2, [Rec1], {tid,_,S}}}, recv_event()), 1963: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1964: ?match({atomic, ok}, Write(Tab2, Rec1)), 1965: ?match({mnesia_table_event, {write, Tab2, Rec1, [Rec1, Rec2], {tid,_,S}}}, recv_event()), 1966: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1967: ?match({atomic, ok}, DelObj(Tab2, Rec2)), 1968: ?match({mnesia_table_event, {delete, Tab2, Rec2, [Rec2], {tid,_,S}}}, recv_event()), 1969: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1970: ?match({atomic, ok}, Delete(Tab2, 1)), 1971: ?match({mnesia_table_event, {delete, Tab2, {Tab2, 1}, [Rec1], {tid,_,S}}}, recv_event()), 1972: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1973: ?match({atomic, ok}, Delete(Tab2, 2)), 1974: ?match({mnesia_table_event, {delete, Tab2, {Tab2, 2}, [Rec4, Rec3], {tid,_,S}}}, recv_event()), 1975: ?match({mnesia_activity_event, {complete, {tid,_,S}}}, recv_event()), 1976: 1977: %% COUNTERS 1978: 1979: Rec5 = {Tab3, counter, 0}, 1980: ?match(ok, mnesia:dirty_write(Rec5)), 1981: ?match({mnesia_table_event, {write, Tab3, Rec5, [], D}}, recv_event()), 1982: ?match(1, mnesia:dirty_update_counter({Tab3, counter}, 1)), 1983: ?match({mnesia_table_event, {write, Tab3, {Tab3,counter,1}, [Rec5], D}}, recv_event()), 1984: ?match(ok, mnesia:dirty_delete({Tab3, counter})), 1985: ?match({mnesia_table_event, {delete, Tab3, {Tab3,counter}, 1986: [{Tab3,counter,1}], D}}, recv_event()), 1987: ok. 1988: 1989: 1990: subscribe_standard(doc) -> 1991: ["Tests system events and the orignal table events"]; 1992: subscribe_standard(suite) -> []; 1993: subscribe_standard(Config) when is_list(Config)-> 1994: [N1, N2]=?acquire_nodes(2, Config), 1995: Tab = tab, 1996: 1997: Storage = mnesia_test_lib:storage_type(disc_copies, Config), 1998: Def = [{Storage, [N1, N2]}, {attributes, record_info(fields, tab)}], 1999: 2000: ?match({atomic, ok}, mnesia:create_table(Tab, Def)), 2001: 2002: %% Check system events 2003: ?match({error, {badarg, foo}}, mnesia:unsubscribe(foo)), 2004: ?match({error, badarg}, mnesia:unsubscribe({table, foo})), 2005: mnesia:unsubscribe(activity), 2006: 2007: ?match({ok, N1}, mnesia:subscribe(system)), 2008: ?match({ok, N1}, mnesia:subscribe(activity)), 2009: 2010: ?match([], mnesia_test_lib:kill_mnesia([N2])), 2011: ?match({mnesia_system_event, {mnesia_down, N2}}, recv_event()), 2012: ?match(timeout, recv_event()), 2013: 2014: ?match([], mnesia_test_lib:start_mnesia([N2], [Tab])), 2015: ?match({mnesia_activity_event, _}, recv_event()), 2016: ?match({mnesia_system_event,{mnesia_up, N2}}, recv_event()), 2017: 2018: ?match(true, lists:member(self(), mnesia:system_info(subscribers))), 2019: ?match([], mnesia_test_lib:kill_mnesia([N1])), 2020: timer:sleep(500), 2021: mnesia_test_lib:flush(), 2022: ?match([], mnesia_test_lib:start_mnesia([N1], [Tab])), 2023: ?match(timeout, recv_event()), 2024: 2025: ?match({ok, N1}, mnesia:subscribe(system)), 2026: ?match({error, {already_exists, system}}, mnesia:subscribe(system)), 2027: ?match(stopped, mnesia:stop()), 2028: ?match({mnesia_system_event, {mnesia_down, N1}}, recv_event()), 2029: ?match({error, {node_not_running, N1}}, mnesia:subscribe(system)), 2030: ?match([], mnesia_test_lib:start_mnesia([N1, N2], [Tab])), 2031: 2032: %% Check table events 2033: ?match({ok, N1}, mnesia:subscribe(activity)), 2034: Old_Level = mnesia:set_debug_level(trace), 2035: ?match({ok, N1}, mnesia:subscribe({table,Tab})), 2036: 2037: ?match({atomic, ok}, 2038: mnesia:transaction(fun() -> mnesia:write(#tab{i=155}) end)), 2039: Self = self(), 2040: ?match({mnesia_table_event, {write, _, _}}, recv_event()), 2041: ?match({mnesia_activity_event, {complete, {tid, _, Self}}}, recv_event()), 2042: 2043: ?match({ok, N1}, mnesia:unsubscribe({table,Tab})), 2044: ?match({ok, N1}, mnesia:unsubscribe(activity)), 2045: 2046: ?match({atomic, ok}, 2047: mnesia:transaction(fun() -> mnesia:write(#tab{i=255}) end)), 2048: 2049: ?match(timeout, recv_event()), 2050: mnesia:set_debug_level(Old_Level), 2051: 2052: %% Check deletion of replica 2053: 2054: ?match({ok, N1}, mnesia:subscribe({table,Tab})), 2055: ?match({ok, N1}, mnesia:subscribe(activity)), 2056: ?match(ok, mnesia:dirty_write(#tab{i=355})), 2057: ?match({mnesia_table_event, {write, _, _}}, recv_event()), 2058: ?match({atomic, ok}, mnesia:del_table_copy(Tab, N1)), 2059: ?match({mnesia_activity_event, _}, recv_event()), 2060: ?match(ok, mnesia:dirty_write(#tab{i=455})), 2061: ?match(timeout, recv_event()), 2062: 2063: ?match({atomic, ok}, mnesia:move_table_copy(Tab, N2, N1)), 2064: ?match({mnesia_activity_event, _}, recv_event()), 2065: ?match({ok, N1}, mnesia:subscribe({table,Tab})), 2066: ?match(ok, mnesia:dirty_write(#tab{i=555})), 2067: ?match({mnesia_table_event, {write, _, _}}, recv_event()), 2068: ?match({atomic, ok}, mnesia:move_table_copy(Tab, N1, N2)), 2069: ?match({mnesia_activity_event, _}, recv_event()), 2070: ?match(ok, mnesia:dirty_write(#tab{i=655})), 2071: ?match(timeout, recv_event()), 2072: 2073: ?match({atomic, ok}, mnesia:add_table_copy(Tab, N1, ram_copies)), 2074: ?match({mnesia_activity_event, _}, recv_event()), 2075: ?match({ok, N1}, mnesia:subscribe({table,Tab})), 2076: ?match({error, {already_exists, {table,Tab, simple}}}, 2077: mnesia:subscribe({table,Tab})), 2078: ?match(ok, mnesia:dirty_write(#tab{i=755})), 2079: ?match({mnesia_table_event, {write, _, _}}, recv_event()), 2080: 2081: ?match({atomic, ok}, mnesia:delete_table(Tab)), 2082: ?match({mnesia_activity_event, _}, recv_event()), 2083: ?match(timeout, recv_event()), 2084: 2085: mnesia_test_lib:kill_mnesia([N1]), 2086: 2087: ?verify_mnesia([N2], [N1]). 2088: 2089: recv_event() -> 2090: receive 2091: Event -> Event 2092: after 1000 -> 2093: timeout 2094: end. 2095: 2096: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2097: 2098: 2099: foldl(suite) -> 2100: []; 2101: foldl(doc) -> 2102: [""]; 2103: foldl(Config) when is_list(Config) -> 2104: Nodes = [_N1, N2] = ?acquire_nodes(2, Config), 2105: Tab1 = fold_local, 2106: Tab2 = fold_remote, 2107: Tab3 = fold_ordered, 2108: ?match({atomic, ok}, mnesia:create_table(Tab1, [{ram_copies, Nodes}])), 2109: ?match({atomic, ok}, mnesia:create_table(Tab2, [{ram_copies, [N2]}, {type, bag}])), 2110: ?match({atomic, ok}, mnesia:create_table(Tab3, [{ram_copies, Nodes}, 2111: {type, ordered_set}])), 2112: 2113: Tab1Els = [{Tab1, N, N} || N <- lists:seq(1, 10)], 2114: Tab2Els = ?sort([{Tab2, 1, 2} | [{Tab2, N, N} || N <- lists:seq(1, 10)]]), 2115: Tab3Els = [{Tab3, N, N} || N <- lists:seq(1, 10)], 2116: 2117: [mnesia:sync_transaction(fun() -> mnesia:write(E) end) || E <- Tab1Els], 2118: [mnesia:sync_transaction(fun() -> mnesia:write(E) end) || E <- Tab2Els], 2119: [mnesia:sync_transaction(fun() -> mnesia:write(E) end) || E <- Tab3Els], 2120: 2121: Fold = fun(Tab) -> 2122: lists:reverse(mnesia:foldl(fun(E, A) -> [E | A] end, [], Tab)) 2123: end, 2124: Fold2 = fun(Tab, Lock) -> 2125: lists:reverse(mnesia:foldl(fun(E, A) -> [E | A] end, [], Tab, Lock)) 2126: end, 2127: Exit = fun(Tab) -> 2128: lists:reverse(mnesia:foldl(fun(_E, _A) -> exit(testing) end, [], Tab)) 2129: end, 2130: %% Errors 2131: ?match({aborted, _}, mnesia:transaction(Fold, [error])), 2132: ?match({aborted, _}, mnesia:transaction(fun(Tab) -> mnesia:foldl(badfun,[],Tab) end, 2133: [Tab1])), 2134: ?match({aborted, testing}, mnesia:transaction(Exit, [Tab1])), 2135: ?match({aborted, _}, mnesia:transaction(Fold2, [Tab1, read_lock])), 2136: 2137: %% Success 2138: ?match({atomic, Tab1Els}, sort_res(mnesia:transaction(Fold, [Tab1]))), 2139: ?match({atomic, Tab2Els}, sort_res(mnesia:transaction(Fold, [Tab2]))), 2140: ?match({atomic, Tab3Els}, mnesia:transaction(Fold, [Tab3])), 2141: 2142: ?match({atomic, Tab1Els}, sort_res(mnesia:transaction(Fold2, [Tab1, read]))), 2143: ?match({atomic, Tab1Els}, sort_res(mnesia:transaction(Fold2, [Tab1, write]))), 2144: 2145: ?match(Tab1Els, sort_res(mnesia:sync_dirty(Fold, [Tab1]))), 2146: ?match(Tab2Els, sort_res(mnesia:async_dirty(Fold, [Tab2]))), 2147: 2148: ?verify_mnesia(Nodes, []). 2149: 2150: sort_res({atomic, List}) -> 2151: {atomic, ?sort(List)}; 2152: sort_res(Else) when is_list(Else) -> 2153: ?sort(Else); 2154: sort_res(Else) -> 2155: Else. 2156: 2157: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2158: 2159: info(suite) -> []; 2160: info(Config) when is_list(Config) -> 2161: Nodes = ?acquire_nodes(1, Config), 2162: ?match(ok, mnesia:info()), 2163: ?verify_mnesia(Nodes, []). 2164: 2165: schema_0(suite) -> []; 2166: schema_0(Config) when is_list(Config) -> 2167: Nodes = ?acquire_nodes(1, Config), 2168: ?match(ok, mnesia:schema()), 2169: ?verify_mnesia(Nodes, []). 2170: 2171: schema_1(suite) -> []; 2172: schema_1(Config) when is_list(Config) -> 2173: Nodes = ?acquire_nodes(1, Config), 2174: Tab = schema_1, 2175: ?match({atomic, ok}, mnesia:create_table(Tab, [])), 2176: ?match(ok, mnesia:schema(Tab)), 2177: ?verify_mnesia(Nodes, []). 2178: 2179: view_0(suite) -> []; 2180: view_0(Config) when is_list(Config) -> 2181: Nodes = ?acquire_nodes(1, Config), 2182: ?match(ok, mnesia_lib:view()), 2183: ?verify_mnesia(Nodes, []). 2184: 2185: view_1(suite) -> []; 2186: view_1(Config) when is_list(Config) -> 2187: Nodes = ?acquire_nodes(1, Config), 2188: BinCore = mnesia_lib:mkcore({crashinfo, "Just testing..."}), 2189: CoreFile = lists:concat(["MnesiaCore.", node(), ".view_1.", ?MODULE]), 2190: ?match(ok, file:write_file(CoreFile, BinCore)), 2191: ?match(ok, mnesia_lib:view(CoreFile)), 2192: ?match(ok, file:delete(CoreFile)), 2193: 2194: ?match(stopped, mnesia:stop()), 2195: Dir = mnesia:system_info(directory), 2196: ?match(eof, mnesia_lib:view(filename:join(Dir, "LATEST.LOG"))), 2197: ?match(ok, mnesia_lib:view(filename:join(Dir, "schema.DAT"))), 2198: ?verify_mnesia([], Nodes). 2199: 2200: view_2(suite) -> []; 2201: view_2(Config) when is_list(Config) -> 2202: Nodes = ?acquire_nodes(1, Config), 2203: BinCore = mnesia_lib:mkcore({crashinfo, "More testing..."}), 2204: File = lists:concat([?MODULE, "view_2.", node()]), 2205: ?match(ok, file:write_file(File, BinCore)), 2206: ?match(ok, mnesia_lib:view(File, core)), 2207: ?match(ok, file:delete(File)), 2208: 2209: ?match(stopped, mnesia:stop()), 2210: Dir = mnesia:system_info(directory), 2211: ?match(ok, file:rename(filename:join(Dir, "LATEST.LOG"), File)), 2212: ?match(eof, mnesia_lib:view(File, log)), 2213: ?match(ok, file:delete(File)), 2214: 2215: ?match(ok, file:rename(filename:join(Dir, "schema.DAT"), File)), 2216: ?match(ok, mnesia_lib:view(File, dat)), 2217: ?match(ok, file:delete(File)), 2218: ?verify_mnesia([], Nodes). 2219: 2220: lkill(suite) -> []; 2221: lkill(Config) when is_list(Config) -> 2222: [Node1, Node2] = ?acquire_nodes(2, Config), 2223: 2224: ?match(yes, rpc:call(Node1, mnesia, system_info, [is_running])), 2225: ?match(yes, rpc:call(Node2, mnesia, system_info, [is_running])), 2226: ?match(ok, rpc:call(Node2, mnesia, lkill, [])), 2227: ?match(yes, rpc:call(Node1, mnesia, system_info, [is_running])), 2228: ?match(no, rpc:call(Node2, mnesia, system_info, [is_running])), 2229: ?verify_mnesia([Node1], [Node2]). 2230: 2231: kill(suite) -> []; 2232: kill(Config) when is_list(Config) -> 2233: [Node1, Node2] = ?acquire_nodes(2, Config), 2234: 2235: ?match(yes, rpc:call(Node1, mnesia, system_info, [is_running])), 2236: ?match(yes, rpc:call(Node2, mnesia, system_info, [is_running])), 2237: ?match({_, []}, rpc:call(Node2, mnesia, kill, [])), 2238: ?match(no, rpc:call(Node1, mnesia, system_info, [is_running])), 2239: ?match(no, rpc:call(Node2, mnesia, system_info, [is_running])), 2240: ?verify_mnesia([], [Node1, Node2]). 2241: 2242: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2243: 2244: 2245: 2246: record_name_dirty_access_ram(suite) -> 2247: []; 2248: record_name_dirty_access_ram(Config) when is_list(Config) -> 2249: record_name_dirty_access(ram_copies, Config). 2250: 2251: record_name_dirty_access_disc(suite) -> 2252: []; 2253: record_name_dirty_access_disc(Config) when is_list(Config) -> 2254: record_name_dirty_access(disc_copies, Config). 2255: 2256: record_name_dirty_access_disc_only(suite) -> 2257: []; 2258: record_name_dirty_access_disc_only(Config) when is_list(Config) -> 2259: record_name_dirty_access(disc_only_copies, Config). 2260: 2261: record_name_dirty_access(Storage, Config) -> 2262: [Node1, _Node2] = Nodes = ?acquire_nodes(2, Config), 2263: 2264: List = lists:concat([record_name_dirty_access_, Storage]), 2265: Tab = list_to_atom(List), 2266: RecName = some_record, 2267: Attr = val, 2268: TabDef = [{type, bag}, 2269: {record_name, RecName}, 2270: {index, [Attr]}, 2271: {Storage, Nodes}], 2272: ?match({atomic, ok}, mnesia:create_table(Tab, TabDef)), 2273: 2274: ?match(RecName, mnesia:table_info(Tab, record_name)), 2275: 2276: ?match(ok, mnesia:dirty_write(Tab, {RecName, 2, 20})), 2277: ?match(ok, mnesia:dirty_write(Tab, {RecName, 2, 21})), 2278: ?match(ok, mnesia:dirty_write(Tab, {RecName, 2, 22})), 2279: 2280: %% Backup test 2281: BupFile = List ++ ".BUP", 2282: CpName = cpname, 2283: CpArgs = [{name, CpName}, {min, [Tab]}, {ram_overrides_dump, true}], 2284: ?match({ok, CpName, _}, mnesia:activate_checkpoint(CpArgs)), 2285: ?match(ok, mnesia:backup_checkpoint(CpName, BupFile)), 2286: ?match(ok, mnesia:deactivate_checkpoint(CpName)), 2287: 2288: ?match(ok, mnesia:dirty_write(Tab, {RecName, 1, 10})), 2289: ?match({ok, Node1}, mnesia:subscribe({table, Tab})), 2290: ?match(ok, mnesia:dirty_write(Tab, {RecName, 3, 10})), 2291: 2292: Twos =?sort( [{RecName, 2, 20}, {RecName, 2, 21}, {RecName, 2, 22}]), 2293: ?match(Twos, ?sort(mnesia:dirty_read(Tab, 2))), 2294: 2295: ?match(ok, mnesia:dirty_delete_object(Tab, {RecName, 2, 21})), 2296: 2297: Tens = ?sort([{RecName, 1, 10}, {RecName, 3, 10}]), 2298: TenPat = {RecName, '_', 10}, 2299: ?match(Tens, ?sort(mnesia:dirty_match_object(Tab, TenPat))), 2300: ?match(Tens, ?sort(mnesia:dirty_select(Tab, [{TenPat, [], ['$_']}]))), 2301: 2302: %% Subscription test 2303: E = mnesia_table_event, 2304: ?match_receive({E, {write, {Tab, 3, 10}, _}}), 2305: ?match_receive({E, {delete_object, {Tab, 2, 21}, _}}), 2306: ?match({ok, Node1}, mnesia:unsubscribe({table, Tab})), 2307: 2308: ?match([], mnesia_test_lib:stop_mnesia([Node1])), 2309: ?match([], mnesia_test_lib:start_mnesia(Nodes, [Tab])), 2310: 2311: ?match(Tens, ?sort(mnesia:dirty_index_match_object(Tab, TenPat, Attr) )), 2312: ?match(Tens, ?sort(mnesia:dirty_index_read(Tab, 10, Attr))), 2313: 2314: ?match([1, 2, 3], ?sort(mnesia:dirty_all_keys(Tab))), 2315: 2316: ?match({ok, Node1}, mnesia:subscribe({table, Tab})), 2317: ?match(ok, mnesia:dirty_delete(Tab, 2)), 2318: ?match([], mnesia:dirty_read(Tab, 2)), 2319: 2320: ?match_receive({E, {delete, {Tab, 2}, _}}), 2321: ?match([], mnesia_test_lib:flush()), 2322: ?match({ok, Node1}, mnesia:unsubscribe({table, Tab})), 2323: 2324: %% Restore test 2325: ?match({atomic, [Tab]}, mnesia:restore(BupFile, [{recreate_tables, [Tab]}])), 2326: ?match(RecName, mnesia:table_info(Tab, record_name)), 2327: 2328: ?match(Twos, ?sort(mnesia:dirty_match_object(Tab, mnesia:table_info(Tab, wild_pattern)))), 2329: ?match(Twos, ?sort(mnesia:dirty_select(Tab, 2330: [{mnesia:table_info(Tab, wild_pattern), 2331: [],['$_']}]))), 2332: 2333: %% Traverse backup test 2334: 2335: Fun = fun(Rec, {Good, Bad}) -> 2336: ?verbose("BUP: ~p~n", [Rec]), 2337: case Rec of 2338: {T, K, V} when T == Tab -> 2339: Good2 = Good ++ [{RecName, K, V}], 2340: {[Rec], {?sort(Good2), Bad}}; 2341: {T, K} when T == Tab -> 2342: Good2 = [G || G <- Good, element(2, G) /= K], 2343: {[Rec], {?sort(Good2), Bad}}; 2344: _ when element(1, Rec) == schema -> 2345: {[Rec], {Good, Bad}}; 2346: _ -> 2347: Bad2 = Bad ++ [Rec], 2348: {[Rec], {Good, ?sort(Bad2)}} 2349: end 2350: end, 2351: 2352: ?match({ok, {Twos, []}}, mnesia:traverse_backup(BupFile, mnesia_backup, 2353: dummy, read_only, 2354: Fun, {[], []})), 2355: ?match(ok, file:delete(BupFile)), 2356: 2357: %% Update counter test 2358: 2359: CounterTab = list_to_atom(lists:concat([Tab, "_counter"])), 2360: CounterTabDef = [{record_name, some_counter}], 2361: C = my_counter, 2362: ?match({atomic, ok}, mnesia:create_table(CounterTab, CounterTabDef)), 2363: ?match(some_counter, mnesia:table_info(CounterTab, record_name)), 2364: ?match(0, mnesia:dirty_update_counter(CounterTab, gurka, -10)), 2365: ?match(10, mnesia:dirty_update_counter(CounterTab, C, 10)), 2366: ?match(11, mnesia:dirty_update_counter(CounterTab, C, 1)), 2367: ?match(4711, mnesia:dirty_update_counter(CounterTab, C, 4700)), 2368: ?match([{some_counter, C, 4711}], mnesia:dirty_read(CounterTab, C)), 2369: ?match(0, mnesia:dirty_update_counter(CounterTab, C, -4747)), 2370: 2371: %% Registry tests 2372: 2373: RegTab = list_to_atom(lists:concat([Tab, "_registry"])), 2374: RegTabDef = [{record_name, some_reg}], 2375: ?match(ok, mnesia_registry:create_table(RegTab, RegTabDef)), 2376: ?match(some_reg, mnesia:table_info(RegTab, record_name)), 2377: {success, RegRecs} = 2378: ?match([_ | _], mnesia_registry_test:dump_registry(node(), RegTab)), 2379: 2380: R = ?sort(RegRecs), 2381: ?match(R, ?sort(mnesia_registry_test:restore_registry(node(), RegTab))), 2382: 2383: ?verify_mnesia(Nodes, []). 2384: 2385: sorted_ets(suite) -> 2386: []; 2387: sorted_ets(Config) when is_list(Config) -> 2388: [N1, N2, N3] = All = ?acquire_nodes(3, Config), 2389: 2390: Tab = sorted_tab, 2391: Def = case mnesia_test_lib:diskless(Config) of 2392: true -> [{name, Tab}, {type, ordered_set}, {ram_copies, All}]; 2393: false -> [{name, Tab}, {type, ordered_set}, 2394: {ram_copies, [N1]}, 2395: {disc_copies,[N2, N3]}] 2396: end, 2397: 2398: ?match({atomic, ok}, mnesia:create_table(Def)), 2399: ?match({aborted, _}, mnesia:create_table(fel, [{disc_only_copies, N1}])), 2400: 2401: ?match([ok | _], 2402: [mnesia:dirty_write({Tab, {dirty, N}, N}) || N <- lists:seq(1, 10)]), 2403: ?match({atomic, _}, 2404: mnesia:sync_transaction(fun() -> 2405: [mnesia:write({Tab, {trans, N}, N}) || 2406: N <- lists:seq(1, 10)] 2407: end)), 2408: 2409: List = mnesia:dirty_match_object({Tab, '_', '_'}), 2410: ?match(List, ?sort(List)), 2411: ?match(List, rpc:call(N2, mnesia, dirty_match_object, [{Tab, '_', '_'}])), 2412: ?match(List, rpc:call(N3, mnesia, dirty_match_object, [{Tab, '_', '_'}])), 2413: 2414: mnesia_test_lib:stop_mnesia(All), 2415: mnesia_test_lib:start_mnesia(All, [sorted_tab]), 2416: 2417: List = mnesia:dirty_match_object({Tab, '_', '_'}), 2418: ?match(List, ?sort(List)), 2419: ?match(List, rpc:call(N2, mnesia, dirty_match_object, [{Tab, '_', '_'}])), 2420: ?match(List, rpc:call(N3, mnesia, dirty_match_object, [{Tab, '_', '_'}])), 2421: 2422: ?match(List, rpc:call(N3, mnesia, dirty_select, [Tab, [{{Tab, '_', '_'},[],['$_']}]])), 2423: 2424: TransMatch = fun() -> 2425: mnesia:write({Tab, {trans, 0}, 0}), 2426: mnesia:write({Tab, {trans, 11}, 11}), 2427: mnesia:match_object({Tab, '_', '_'}) 2428: end, 2429: TransSelect = fun() -> 2430: mnesia:write({Tab, {trans, 0}, 0}), 2431: mnesia:write({Tab, {trans, 11}, 11}), 2432: mnesia:select(Tab, [{{Tab, '_', '_'},[],['$_']}]) 2433: end, 2434: 2435: TList = mnesia:transaction(TransMatch), 2436: STList = ?sort(TList), 2437: ?match(STList, TList), 2438: ?match(STList, rpc:call(N2, mnesia, transaction, [TransMatch])), 2439: ?match(STList, rpc:call(N3, mnesia, transaction, [TransMatch])), 2440: 2441: TSel = mnesia:transaction(TransSelect), 2442: ?match(STList, TSel), 2443: ?match(STList, rpc:call(N2, mnesia, transaction, [TransSelect])), 2444: ?match(STList, rpc:call(N3, mnesia, transaction, [TransSelect])), 2445: 2446: ?match({atomic, ok}, mnesia:create_table(rec, [{type, ordered_set}])), 2447: [ok = mnesia:dirty_write(R) || R <- [{rec,1,1}, {rec,2,1}]], 2448: ?match({atomic, ok}, mnesia:add_table_index(rec, 3)), 2449: TestIt = fun() -> 2450: ok = mnesia:write({rec,1,1}), 2451: mnesia:index_read(rec, 1, 3) 2452: end, 2453: ?match({atomic, [{rec,1,1}, {rec,2,1}]}, mnesia:transaction(TestIt)). 2454: 2455: