1: %%
    2: %% %CopyrightBegin%
    3: %%
    4: %% Copyright Ericsson AB 2010-2011. 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_majority_test).
   22: -author('ulf.wiger@erlang-solutions.com').
   23: -compile(export_all).
   24: -include("mnesia_test_lib.hrl").
   25: 
   26: init_per_testcase(Func, Conf) ->
   27:     mnesia_test_lib:init_per_testcase(Func, Conf).
   28: 
   29: end_per_testcase(Func, Conf) ->
   30:     mnesia_test_lib:end_per_testcase(Func, Conf).
   31: 
   32: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   33: all() ->
   34:     [
   35:      write
   36:      , wread
   37:      , delete
   38:      , clear_table
   39:      , frag
   40:      , change_majority
   41:      , frag_change_majority
   42:     ].
   43: 
   44: write(suite) -> [];
   45: write(Config) when is_list(Config) ->
   46:     [N1, N2, N3] = ?acquire_nodes(3, Config),
   47:     Tab = t,
   48:     Schema = [{name, Tab}, {ram_copies, [N1,N2,N3]}, {majority,true}],
   49:     ?match({atomic, ok}, mnesia:create_table(Schema)),
   50:     ?match({[ok,ok,ok],[]},
   51: 	   rpc:multicall([N1,N2,N3], mnesia, wait_for_tables, [[Tab], 3000])),
   52:     ?match({atomic,ok},
   53: 	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
   54:     mnesia_test_lib:kill_mnesia([N3]),
   55:     ?match({atomic,ok},
   56: 	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
   57:     mnesia_test_lib:kill_mnesia([N2]),
   58:     ?match({aborted,{no_majority,Tab}},
   59: 	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)).
   60: 
   61: wread(suite) -> [];
   62: wread(Config) when is_list(Config) ->
   63:     [N1, N2] = ?acquire_nodes(2, Config),
   64:     Tab = t,
   65:     Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
   66:     ?match({atomic, ok}, mnesia:create_table(Schema)),
   67:     ?match({[ok,ok],[]},
   68: 	   rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
   69:     ?match({atomic,[]},
   70: 	   mnesia:transaction(fun() -> mnesia:read(t,1,write) end)),
   71:     mnesia_test_lib:kill_mnesia([N2]),
   72:     ?match({aborted,{no_majority,Tab}},
   73: 	   mnesia:transaction(fun() -> mnesia:read(t,1,write) end)).
   74: 
   75: delete(suite) -> [];
   76: delete(Config) when is_list(Config) ->
   77:     [N1, N2] = ?acquire_nodes(2, Config),
   78:     Tab = t,
   79:     Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
   80:     ?match({atomic, ok}, mnesia:create_table(Schema)),
   81:     ?match({[ok,ok],[]},
   82: 	   rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
   83:     %% works as expected with majority of nodes present
   84:     ?match({atomic,ok},
   85: 	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
   86:     ?match({atomic,ok},
   87: 	   mnesia:transaction(fun() -> mnesia:delete({t,1}) end)),
   88:     ?match({atomic,[]},
   89: 	   mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
   90:     %% put the record back
   91:     ?match({atomic,ok},
   92: 	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
   93:     ?match({atomic,[{t,1,a}]},
   94: 	   mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
   95:     mnesia_test_lib:kill_mnesia([N2]),
   96:     ?match({aborted,{no_majority,Tab}},
   97: 	   mnesia:transaction(fun() -> mnesia:delete({t,1}) end)).
   98: 
   99: clear_table(suite) -> [];
  100: clear_table(Config) when is_list(Config) ->
  101:     [N1, N2] = ?acquire_nodes(2, Config),
  102:     Tab = t,
  103:     Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
  104:     ?match({atomic, ok}, mnesia:create_table(Schema)),
  105:     ?match({[ok,ok],[]},
  106: 	   rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
  107:     %% works as expected with majority of nodes present
  108:     ?match({atomic,ok},
  109: 	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
  110:     ?match({atomic,ok}, mnesia:clear_table(t)),
  111:     ?match({atomic,[]},
  112: 	   mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
  113:     %% put the record back
  114:     ?match({atomic,ok},
  115: 	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
  116:     ?match({atomic,[{t,1,a}]},
  117: 	   mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
  118:     mnesia_test_lib:kill_mnesia([N2]),
  119:     ?match({aborted,{no_majority,Tab}}, mnesia:clear_table(t)).
  120: 
  121: frag(suite) -> [];
  122: frag(Config) when is_list(Config) ->
  123:     [N1] = ?acquire_nodes(1, Config),
  124:     Tab = t,
  125:     Schema = [
  126: 	      {name, Tab}, {ram_copies, [N1]},
  127: 	      {majority,true},
  128: 	      {frag_properties, [{n_fragments, 2}]}
  129: 	     ],
  130:     ?match({atomic, ok}, mnesia:create_table(Schema)),
  131:     ?match(true, mnesia:table_info(t, majority)),
  132:     ?match(true, mnesia:table_info(t_frag2, majority)).
  133: 
  134: change_majority(suite) -> [];
  135: change_majority(Config) when is_list(Config) ->
  136:     [N1,N2] = ?acquire_nodes(2, Config),
  137:     Tab = t,
  138:     Schema = [
  139: 	      {name, Tab}, {ram_copies, [N1,N2]},
  140: 	      {majority,false}
  141: 	     ],
  142:     ?match({atomic, ok}, mnesia:create_table(Schema)),
  143:     ?match(false, mnesia:table_info(t, majority)),
  144:     ?match({atomic, ok},
  145: 	   mnesia:change_table_majority(t, true)),
  146:     ?match(true, mnesia:table_info(t, majority)),
  147:     ?match(ok,
  148: 	   mnesia:activity(transaction, fun() ->
  149: 						mnesia:write({t,1,a})
  150: 					end)),
  151:     mnesia_test_lib:kill_mnesia([N2]),
  152:     ?match({'EXIT',{aborted,{no_majority,_}}},
  153: 	   mnesia:activity(transaction, fun() ->
  154: 						mnesia:write({t,1,a})
  155: 					end)).
  156: 
  157: frag_change_majority(suite) -> [];
  158: frag_change_majority(Config) when is_list(Config) ->
  159:     [N1,N2] = ?acquire_nodes(2, Config),
  160:     Tab = t,
  161:     Schema = [
  162: 	      {name, Tab}, {ram_copies, [N1,N2]},
  163: 	      {majority,false},
  164: 	      {frag_properties,
  165: 	       [{n_fragments, 2},
  166: 		{n_ram_copies, 2},
  167: 		{node_pool, [N1,N2]}]}
  168: 	     ],
  169:     ?match({atomic, ok}, mnesia:create_table(Schema)),
  170:     ?match(false, mnesia:table_info(t, majority)),
  171:     ?match(false, mnesia:table_info(t_frag2, majority)),
  172:     ?match({aborted,{bad_type,t_frag2}},
  173: 	   mnesia:change_table_majority(t_frag2, true)),
  174:     ?match({atomic, ok},
  175: 	   mnesia:change_table_majority(t, true)),
  176:     ?match(true, mnesia:table_info(t, majority)),
  177:     ?match(true, mnesia:table_info(t_frag2, majority)),
  178:     ?match(ok,
  179: 	   mnesia:activity(transaction, fun() ->
  180: 						mnesia:write({t,1,a})
  181: 					end, mnesia_frag)),
  182:     mnesia_test_lib:kill_mnesia([N2]),
  183:     ?match({'EXIT',{aborted,{no_majority,_}}},
  184: 	   mnesia:activity(transaction, fun() ->
  185: 						mnesia:write({t,1,a})
  186: 					end, mnesia_frag)).