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