1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2010-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%
22-module(mnesia_majority_test).
23-author('ulf.wiger@erlang-solutions.com').
24-export([init_per_testcase/2, end_per_testcase/2,
25         all/0]).
26
27-export([write/1, wread/1, delete/1, clear_table/1, frag/1,
28         change_majority/1, frag_change_majority/1
29        ]).
30
31-include("mnesia_test_lib.hrl").
32
33init_per_testcase(Func, Conf) ->
34    mnesia_test_lib:init_per_testcase(Func, Conf).
35
36end_per_testcase(Func, Conf) ->
37    mnesia_test_lib:end_per_testcase(Func, Conf).
38
39%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
40all() ->
41    [
42     write
43     , wread
44     , delete
45     , clear_table
46     , frag
47     , change_majority
48     , frag_change_majority
49    ].
50
51write(suite) -> [];
52write(Config) when is_list(Config) ->
53    [N1, N2, N3] = ?acquire_nodes(3, Config),
54    Tab = t,
55    Schema = [{name, Tab}, {ram_copies, [N1,N2,N3]}, {majority,true}],
56    ?match({atomic, ok}, mnesia:create_table(Schema)),
57    ?match({[ok,ok,ok],[]},
58	   rpc:multicall([N1,N2,N3], mnesia, wait_for_tables, [[Tab], 3000])),
59    ?match({atomic,ok},
60	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
61    mnesia_test_lib:kill_mnesia([N3]),
62    ?match({atomic,ok},
63	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
64    mnesia_test_lib:kill_mnesia([N2]),
65    ?match({aborted,{no_majority,Tab}},
66	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)).
67
68wread(suite) -> [];
69wread(Config) when is_list(Config) ->
70    [N1, N2] = ?acquire_nodes(2, Config),
71    Tab = t,
72    Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
73    ?match({atomic, ok}, mnesia:create_table(Schema)),
74    ?match({[ok,ok],[]},
75	   rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
76    ?match({atomic,[]},
77	   mnesia:transaction(fun() -> mnesia:read(t,1,write) end)),
78    mnesia_test_lib:kill_mnesia([N2]),
79    ?match({aborted,{no_majority,Tab}},
80	   mnesia:transaction(fun() -> mnesia:read(t,1,write) end)).
81
82delete(suite) -> [];
83delete(Config) when is_list(Config) ->
84    [N1, N2] = ?acquire_nodes(2, Config),
85    Tab = t,
86    Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
87    ?match({atomic, ok}, mnesia:create_table(Schema)),
88    ?match({[ok,ok],[]},
89	   rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
90    %% works as expected with majority of nodes present
91    ?match({atomic,ok},
92	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
93    ?match({atomic,ok},
94	   mnesia:transaction(fun() -> mnesia:delete({t,1}) end)),
95    ?match({atomic,[]},
96	   mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
97    %% put the record back
98    ?match({atomic,ok},
99	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
100    ?match({atomic,[{t,1,a}]},
101	   mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
102    mnesia_test_lib:kill_mnesia([N2]),
103    ?match({aborted,{no_majority,Tab}},
104	   mnesia:transaction(fun() -> mnesia:delete({t,1}) end)).
105
106clear_table(suite) -> [];
107clear_table(Config) when is_list(Config) ->
108    [N1, N2] = ?acquire_nodes(2, Config),
109    Tab = t,
110    Schema = [{name, Tab}, {ram_copies, [N1,N2]}, {majority,true}],
111    ?match({atomic, ok}, mnesia:create_table(Schema)),
112    ?match({[ok,ok],[]},
113	   rpc:multicall([N1,N2], mnesia, wait_for_tables, [[Tab], 3000])),
114    %% works as expected with majority of nodes present
115    ?match({atomic,ok},
116	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
117    ?match({atomic,ok}, mnesia:clear_table(t)),
118    ?match({atomic,[]},
119	   mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
120    %% put the record back
121    ?match({atomic,ok},
122	   mnesia:transaction(fun() -> mnesia:write({t,1,a}) end)),
123    ?match({atomic,[{t,1,a}]},
124	   mnesia:transaction(fun() -> mnesia:read({t,1}) end)),
125    mnesia_test_lib:kill_mnesia([N2]),
126    ?match({aborted,{no_majority,Tab}}, mnesia:clear_table(t)).
127
128frag(suite) -> [];
129frag(Config) when is_list(Config) ->
130    [N1] = ?acquire_nodes(1, Config),
131    Tab = t,
132    Schema = [
133	      {name, Tab}, {ram_copies, [N1]},
134	      {majority,true},
135	      {frag_properties, [{n_fragments, 2}]}
136	     ],
137    ?match({atomic, ok}, mnesia:create_table(Schema)),
138    ?match(true, mnesia:table_info(t, majority)),
139    ?match(true, mnesia:table_info(t_frag2, majority)).
140
141change_majority(suite) -> [];
142change_majority(Config) when is_list(Config) ->
143    [N1,N2] = ?acquire_nodes(2, Config),
144    Tab = t,
145    Schema = [
146	      {name, Tab}, {ram_copies, [N1,N2]},
147	      {majority,false}
148	     ],
149    ?match({atomic, ok}, mnesia:create_table(Schema)),
150    ?match(false, mnesia:table_info(t, majority)),
151    ?match({atomic, ok},
152	   mnesia:change_table_majority(t, true)),
153    ?match(true, mnesia:table_info(t, majority)),
154    ?match(ok,
155	   mnesia:activity(transaction, fun() ->
156						mnesia:write({t,1,a})
157					end)),
158    mnesia_test_lib:kill_mnesia([N2]),
159    ?match({'EXIT',{aborted,{no_majority,_}}},
160	   mnesia:activity(transaction, fun() ->
161						mnesia:write({t,1,a})
162					end)).
163
164frag_change_majority(suite) -> [];
165frag_change_majority(Config) when is_list(Config) ->
166    [N1,N2] = ?acquire_nodes(2, Config),
167    Tab = t,
168    Schema = [
169	      {name, Tab}, {ram_copies, [N1,N2]},
170	      {majority,false},
171	      {frag_properties,
172	       [{n_fragments, 2},
173		{n_ram_copies, 2},
174		{node_pool, [N1,N2]}]}
175	     ],
176    ?match({atomic, ok}, mnesia:create_table(Schema)),
177    ?match(false, mnesia:table_info(t, majority)),
178    ?match(false, mnesia:table_info(t_frag2, majority)),
179    ?match({aborted,{bad_type,t_frag2}},
180	   mnesia:change_table_majority(t_frag2, true)),
181    ?match({atomic, ok},
182	   mnesia:change_table_majority(t, true)),
183    ?match(true, mnesia:table_info(t, majority)),
184    ?match(true, mnesia:table_info(t_frag2, majority)),
185    ?match(ok,
186	   mnesia:activity(transaction, fun() ->
187						mnesia:write({t,1,a})
188					end, mnesia_frag)),
189    mnesia_test_lib:kill_mnesia([N2]),
190    ?match({'EXIT',{aborted,{no_majority,_}}},
191	   mnesia:activity(transaction, fun() ->
192						mnesia:write({t,1,a})
193					end, mnesia_frag)).
194