diff options
Diffstat (limited to 'lib/mnesia/test')
-rw-r--r-- | lib/mnesia/test/mnesia_durability_test.erl | 107 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_evil_coverage_test.erl | 105 | ||||
-rw-r--r-- | lib/mnesia/test/mnesia_isolation_test.erl | 11 |
3 files changed, 216 insertions, 7 deletions
diff --git a/lib/mnesia/test/mnesia_durability_test.erl b/lib/mnesia/test/mnesia_durability_test.erl index 62199d8b9a..ccbfdc9738 100644 --- a/lib/mnesia/test/mnesia_durability_test.erl +++ b/lib/mnesia/test/mnesia_durability_test.erl @@ -46,6 +46,7 @@ master_nodes/1, starting_master_nodes/1, master_on_non_local_tables/1, remote_force_load_with_local_master_node/1, + master_node_with_ram_copy_2/1, master_node_with_ram_copy_3/1, dump_ram_copies/1, dump_disc_copies/1, dump_disc_only/1]). -include("mnesia_test_lib.hrl"). @@ -91,7 +92,8 @@ groups() -> {load_tables_with_master_tables, [], [master_nodes, starting_master_nodes, master_on_non_local_tables, - remote_force_load_with_local_master_node]}, + remote_force_load_with_local_master_node, + master_node_with_ram_copy_2, master_node_with_ram_copy_3]}, {durability_of_dump_tables, [], [dump_ram_copies, dump_disc_copies, dump_disc_only]}]. @@ -1165,6 +1167,107 @@ remote_force_load_with_local_master_node(Config) when is_list(Config) -> ?verify_mnesia(Nodes, []). +master_node_with_ram_copy_2(Config) when is_list(Config) -> + [A, B] = Nodes = ?acquire_nodes(2, Config), + Tab = ?FUNCTION_NAME, + ?match({atomic,ok}, mnesia:create_table(Tab, [{disc_copies, [A]}, {ram_copies, [B]}])), + ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))), + + %% Test that we don't load from ram_copies + ?match(stopped, rpc:call(A, mnesia, stop, [])), + ?match(stopped, rpc:call(B, mnesia, stop, [])), + ?match(ok, rpc:call(B, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])), + ?match(ok, rpc:call(A, mnesia, start, [])), + ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])), + ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])), + ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])), + + %% Test that master_nodes set to ram_copy node require force_load + ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])), + ?match(stopped, rpc:call(A, mnesia, stop, [])), + ?match(stopped, rpc:call(B, mnesia, stop, [])), + ?match(ok, rpc:call(B, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])), + ?match(ok, rpc:call(A, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])), + + ?match(yes, rpc:call(A, mnesia, force_load_table, [Tab])), + ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 1000])), + ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])), + ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])), + ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])), + + ?verify_mnesia(Nodes, []). + + +master_node_with_ram_copy_3(Config) when is_list(Config) -> + [A, B, C] = Nodes = ?acquire_nodes(3, Config), + Tab = ?FUNCTION_NAME, + ?match({atomic,ok}, mnesia:create_table(Tab, [{disc_copies, [A,C]}, {ram_copies, [B]}])), + ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))), + + %% Test that we don't load from ram_copies + ?match(stopped, rpc:call(A, mnesia, stop, [])), + ?match(stopped, rpc:call(C, mnesia, stop, [])), + ?match(stopped, rpc:call(B, mnesia, stop, [])), + ?match(ok, rpc:call(B, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 1000])), + ?match(ok, rpc:call(A, mnesia, start, [])), + ?match(ok, rpc:call(C, mnesia, start, [])), + ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])), + ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])), + ?match([{Tab, 1, init}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])), + ?match([{Tab, 1, init}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])), + ?match([{Tab, 1, init}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])), + + %% Test that master_nodes set to ram_copy node will wait until loaded + ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])), + ?match(stopped, rpc:call(A, mnesia, stop, [])), + ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, update})])), + ?match(stopped, rpc:call(C, mnesia, stop, [])), + ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, ram_copies})])), + ?match(stopped, rpc:call(B, mnesia, stop, [])), + ?match(ok, rpc:call(B, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])), + ?match(ok, rpc:call(A, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])), + ?match(ok, rpc:call(C, mnesia, start, [])), + ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])), + ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])), + ?match([{Tab, 1, update}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])), + ?match([{Tab, 1, update}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])), + ?match([{Tab, 1, update}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])), + + %% Test that master_nodes set to ram_copy node requires force load + ?match({atomic,ok}, mnesia:sync_transaction(?SDwrite({Tab, 1, init}))), + ?match(ok, rpc:call(A, mnesia, set_master_nodes, [[B]])), + ?match(ok, rpc:call(C, mnesia, set_master_nodes, [[B]])), + + ?match(stopped, rpc:call(A, mnesia, stop, [])), + ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, update})])), + ?match(stopped, rpc:call(C, mnesia, stop, [])), + ?match({atomic,ok}, rpc:call(B, mnesia, sync_transaction, [?SDwrite({Tab, 1, ram_copies})])), + ?match(stopped, rpc:call(B, mnesia, stop, [])), + ?match(ok, rpc:call(B, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])), + ?match(ok, rpc:call(A, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])), + ?match(ok, rpc:call(C, mnesia, start, [])), + ?match({timeout, [Tab]}, rpc:call(A, mnesia, wait_for_tables, [[Tab], 500])), + ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])), + ?match({timeout, [Tab]}, rpc:call(B, mnesia, wait_for_tables, [[Tab], 500])), + ?match(yes, rpc:call(C, mnesia, force_load_table, [Tab])), + + ?match(ok, rpc:call(A, mnesia, wait_for_tables, [[Tab], 3000])), + ?match(ok, rpc:call(B, mnesia, wait_for_tables, [[Tab], 3000])), + ?match(ok, rpc:call(C, mnesia, wait_for_tables, [[Tab], 3000])), + ?match([{Tab, 1, update}], rpc:call(A, mnesia, dirty_read, [{Tab, 1}])), + ?match([{Tab, 1, update}], rpc:call(B, mnesia, dirty_read, [{Tab, 1}])), + ?match([{Tab, 1, update}], rpc:call(C, mnesia, dirty_read, [{Tab, 1}])), + + ?verify_mnesia(Nodes, []). + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -1415,7 +1518,7 @@ do_disc_durability(Config,CopyType) -> [{Tab_bag, 22, a_2222}], [{Tab_bag, 33, a_3333}], [{Tab_set, counter, 10}]]), - timer:sleep(1000), %% Debugging strange msgs.. + timer:sleep(500), %% Debugging strange msgs.. ?log("Flushed ~p ~n", [mnesia_test_lib:flush()]), ?verify_mnesia(Nodes, []). diff --git a/lib/mnesia/test/mnesia_evil_coverage_test.erl b/lib/mnesia/test/mnesia_evil_coverage_test.erl index eb1f987cf0..a451c8d0c8 100644 --- a/lib/mnesia/test/mnesia_evil_coverage_test.erl +++ b/lib/mnesia/test/mnesia_evil_coverage_test.erl @@ -31,10 +31,11 @@ db_node_lifecycle/1, evil_delete_db_node/1, start_and_stop/1, checkpoint/1, table_lifecycle/1, storage_options/1, add_copy_conflict/1, add_copy_when_going_down/1, + add_copy_with_down/1, replica_management/1, clear_table_during_load/1, schema_availability/1, local_content/1, replica_location/1, user_properties/1, unsupp_user_props/1, - sorted_ets/1, + sorted_ets/1, index_cleanup/1, change_table_access_mode/1, change_table_load_order/1, set_master_nodes/1, offline_set_master_nodes/1, dump_tables/1, dump_log/1, wait_for_tables/1, force_load_table/1, @@ -48,7 +49,7 @@ record_name_dirty_access_disc_only/1, record_name_dirty_access_xets/1]). --export([info_check/8]). +-export([info_check/8, index_size/1]). -define(cleanup(N, Config), mnesia_test_lib:prepare_test_case([{reload_appls, [mnesia]}], @@ -65,13 +66,14 @@ all() -> db_node_lifecycle, evil_delete_db_node, start_and_stop, checkpoint, table_lifecycle, storage_options, add_copy_conflict, - add_copy_when_going_down, replica_management, clear_table_during_load, + add_copy_when_going_down, add_copy_with_down, replica_management, + clear_table_during_load, schema_availability, local_content, {group, table_access_modifications}, replica_location, {group, table_sync}, user_properties, unsupp_user_props, {group, record_name}, {group, snmp_access}, {group, subscriptions}, {group, iteration}, - {group, debug_support}, sorted_ets, + {group, debug_support}, sorted_ets, index_cleanup, {mnesia_dirty_access_test, all}, {mnesia_trans_access_test, all}, {mnesia_evil_backup, all}]. @@ -732,6 +734,49 @@ add_copy_when_going_down(Config) -> ?match_receive({test,{aborted,_}}), ?verify_mnesia([Node2], []). +add_copy_with_down(suite) -> []; +add_copy_with_down(Config) -> + %% Allow add_table_copy() with ram_copies even all other replicas are down + Nodes = [Node1, Node2, Node3] = ?acquire_nodes(3, Config), + ?match({atomic, ok}, mnesia:create_table(a, [{ram_copies, [Node3]}, {disc_copies, [Node2]}])), + stopped = rpc:call(Node2, mnesia, stop, []), + stopped = rpc:call(Node3, mnesia, stop, []), + ?match({aborted, _}, mnesia:add_table_copy(a, Node1, ram_copies)), + ?match({aborted, _}, mnesia:del_table_copy(a, Node2)), + ok = rpc:call(Node3, mnesia, start, []), + ?match({aborted, _}, mnesia:add_table_copy(a, Node1, ram_copies)), + ?match([], mnesia_test_lib:start_mnesia([Node2], [a])), + ?match({atomic, ok}, mnesia:change_table_copy_type(a, Node2, ram_copies)), + stopped = rpc:call(Node2, mnesia, stop, []), + stopped = rpc:call(Node3, mnesia, stop, []), + ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, ram_copies)), + ?match(ok, mnesia:dirty_write({a,1,1})), + ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])), + ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])), + ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])), + ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])), + + ?match({atomic, ok}, mnesia:del_table_copy(a, Node1)), + stopped = rpc:call(Node2, mnesia, stop, []), + stopped = rpc:call(Node3, mnesia, stop, []), + ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, disc_copies)), + ?match(ok, mnesia:dirty_write({a,1,1})), + ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])), + ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])), + ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])), + ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])), + + ?match({atomic, ok}, mnesia:del_table_copy(a, Node1)), + stopped = rpc:call(Node2, mnesia, stop, []), + stopped = rpc:call(Node3, mnesia, stop, []), + ?match({atomic, ok}, mnesia:add_table_copy(a, Node1, disc_only_copies)), + ?match(ok, mnesia:dirty_write({a,1,1})), + ?match([], mnesia_test_lib:start_mnesia([Node2,Node3], [a])), + ?match([{a,1,1}], rpc:call(Node1, mnesia, dirty_read, [{a,1}])), + ?match([{a,1,1}], rpc:call(Node2, mnesia, dirty_read, [{a,1}])), + ?match([{a,1,1}], rpc:call(Node3, mnesia, dirty_read, [{a,1}])), + + ?verify_mnesia(Nodes, []). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Add, drop and move replicas, change storage types @@ -2514,3 +2559,55 @@ sorted_ets(Config) when is_list(Config) -> ?match({atomic, [{rec,1,1}, {rec,2,1}]}, mnesia:transaction(TestIt)). +index_cleanup(Config) when is_list(Config) -> + [N1, N2] = All = ?acquire_nodes(2, Config), + ?match({atomic, ok}, mnesia:create_table(i_set, [{type, set}, {ram_copies, [N1]}, {index, [val]}, + {disc_only_copies, [N2]}])), + ?match({atomic, ok}, mnesia:create_table(i_bag, [{type, bag}, {ram_copies, [N1]}, {index, [val]}, + {disc_only_copies, [N2]}])), + ?match({atomic, ok}, mnesia:create_table(i_oset, [{type, ordered_set}, {ram_copies, [N1, N2]}, + {index, [val]}])), + + Tabs = [i_set, i_bag, i_oset], + + Add = fun(Tab) -> + Write = fun(Tab) -> + Recs = [{Tab, N, N rem 5} || N <- lists:seq(1,10)], + [ok = mnesia:write(Rec) || Rec <- Recs], + Recs + end, + {atomic, Recs} = mnesia:sync_transaction(Write, [Tab]), + lists:sort(Recs) + end, + + IRead = fun(Tab) -> + Read = fun(Tab) -> + [mnesia:index_read(Tab, N, val) || N <- lists:seq(0,4)] + end, + {atomic, Recs} = mnesia:transaction(Read, [Tab]), + lists:sort(lists:flatten(Recs)) + end, + + Delete = fun(Rec) -> + Del = fun() -> mnesia:delete_object(Rec) end, + {atomic, ok} = mnesia:sync_transaction(Del), + ok + end, + + + Recs = [Add(Tab) || Tab <- Tabs], + ?match(Recs, [IRead(Tab) || Tab <- Tabs]), + [Delete(Rec) || Rec <- lists:flatten(Recs)], + + [?match({Tab,0}, {Tab,mnesia:table_info(Tab, size)}) || Tab <- Tabs], + + [?match({Tab,Node,0, _}, rpc:call(Node, ?MODULE, index_size, [Tab])) + || Node <- All, Tab <- Tabs], + ?verify_mnesia(All, []). + +index_size(Tab) -> + %% White box testing + case mnesia:table_info(Tab, index_info) of + {index, _, [{_, {ram, Ref}}=Dbg]} -> {Tab, node(), ets:info(Ref, size), Dbg}; + {index, _, [{_, {dets, Ref}}=Dbg]} -> {Tab, node(), dets:info(Ref, size), Dbg} + end. diff --git a/lib/mnesia/test/mnesia_isolation_test.erl b/lib/mnesia/test/mnesia_isolation_test.erl index b2eea2390b..49bcec14af 100644 --- a/lib/mnesia/test/mnesia_isolation_test.erl +++ b/lib/mnesia/test/mnesia_isolation_test.erl @@ -1563,7 +1563,8 @@ trans_update_visible_inside_trans(Config) when is_list(Config) -> ?match({atomic, ok}, mnesia:create_table([{name, Tab}, {ram_copies, [Node1]}])), ValPos = 3, - RecA = {Tab, a, 1}, + RecA = {Tab, a, 1}, + RecA2 = {Tab, a, 2}, PatA = {Tab, '$1', 1}, RecB = {Tab, b, 3}, PatB = {Tab, '$1', 3}, @@ -1598,6 +1599,14 @@ trans_update_visible_inside_trans(Config) when is_list(Config) -> ?match([], mnesia:index_read(Tab, 3, ValPos)), %% delete_object + ?match(ok, mnesia:delete_object(RecA2)), + ?match([RecA], mnesia:read({Tab, a})), + ?match([RecA], mnesia:wread({Tab, a})), + ?match([RecA], mnesia:match_object(PatA)), + ?match([a], mnesia:all_keys(Tab)), + ?match([RecA], mnesia:index_match_object(PatA, ValPos)), + ?match([RecA], mnesia:index_read(Tab, 1, ValPos)), + ?match(ok, mnesia:delete_object(RecA)), ?match([], mnesia:read({Tab, a})), ?match([], mnesia:wread({Tab, a})), |