1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1997-2020. 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%%% Author: Hakan Mattsson hakan@erix.ericsson.se 23%%% Purpose: Nice shortcuts intended for testing of Mnesia 24%%% 25%%% See the mnesia_SUITE module about the structure of 26%%% the test suite. 27%%% 28%%% See the mnesia_test_lib module about the test case execution. 29%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 30 31-module(mt). 32-author('hakan@erix.ericsson.se'). 33-export([ 34 t/0, t/1, t/2, t/3, % Run test cases 35 loop/1, loop/2, loop/3, % loop test cases 36 doc/0, doc/1, % Generate test case doc 37 struct/0, struct/1, % View test suite struct 38 shutdown/0, ping/0, start_nodes/0, % Node admin 39 read_config/0, write_config/1 % Config admin 40 ]). 41 42-include("mnesia_test_lib.hrl"). 43 44%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 45%% Aliases for the (sub) test suites 46alias(all) -> mnesia_SUITE; 47alias(atomicity) -> mnesia_atomicity_test; 48alias(backup) -> mnesia_evil_backup; 49alias(config) -> mnesia_config_test; 50alias(consistency) -> mnesia_consistency_test; 51alias(dirty) -> mnesia_dirty_access_test; 52alias(durability) -> mnesia_durability_test; 53alias(evil) -> mnesia_evil_coverage_test; 54alias(qlc) -> mnesia_qlc_test; 55alias(examples) -> mnesia_examples_test; 56alias(frag) -> mnesia_frag_test; 57alias(heavy) -> {mnesia_SUITE, heavy}; 58alias(install) -> mnesia_install_test; 59alias(isolation) -> mnesia_isolation_test; 60alias(light) -> {mnesia_SUITE, light}; 61alias(majority) -> mnesia_majority_test; 62alias(measure) -> mnesia_measure_test; 63alias(medium) -> {mnesia_SUITE, medium}; 64alias(nice) -> mnesia_nice_coverage_test; 65alias(recover) -> mnesia_recover_test; 66alias(recovery) -> mnesia_recovery_test; 67alias(registry) -> mnesia_registry_test; 68alias(suite) -> mnesia_SUITE; 69alias(trans) -> mnesia_trans_access_test; 70alias(ixp) -> mnesia_index_plugin_test; 71alias(Other) -> Other. 72 73%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 74%% Resolves the name of test suites and test cases 75%% according to the alias definitions. Single atoms 76%% are assumed to be the name of a test suite. 77resolve(Suite0) when is_atom(Suite0) -> 78 case alias(Suite0) of 79 Suite when is_atom(Suite) -> 80 {Suite, all}; 81 {Suite, Case} -> 82 {Suite, is_group(Suite,Case)} 83 end; 84resolve({Suite0, {group, Case}}) -> 85 resolve({Suite0, Case}); 86resolve({Suite0, Case}) when is_atom(Suite0), is_atom(Case) -> 87 case alias(Suite0) of 88 Suite when is_atom(Suite) -> 89 {Suite, is_group(Suite,Case)}; 90 {Suite, Case2} -> 91 {Suite, is_group(Suite,Case2)} 92 end; 93resolve(List) when is_list(List) -> 94 [resolve(Case) || Case <- List]. 95 96is_group(Mod, Case) -> 97 try {_,_,_} = lists:keyfind(Case, 1, Mod:groups()), 98 {group, Case} 99 catch _:{badmatch,_} -> 100 Case 101 end. 102 103%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 104%% Run one or more test cases 105 106%% Run the default test case with default config 107t() -> 108 t(read_test_case()). 109 110%% Resolve the test case name and run the test case 111%% The test case is noted as default test case 112%% and the outcome of the tests are written to 113%% to a file. 114t(silly) -> 115 mnesia_install_test:silly(); 116t(diskless) -> 117 %% Run the default test case with default config, 118 %% but diskless 119 t(read_test_case(), diskless); 120t(Case) -> 121 %% Use the default config 122 t(Case, read_config()). 123 124t(Case, Config) when Config == diskless -> 125 %% Run the test case with default config, but diskless 126 Config2 = [{diskless, true} | read_config()], 127 t(Case, Config2); 128t(Mod, Fun) when is_atom(Mod), is_atom(Fun) -> 129 %% Run the test case with default config 130 t({Mod, Fun}, read_config()); 131t(RawCase, Config) when is_list(Config) -> 132 %% Resolve the test case name and run the test case 133 Case = resolve(RawCase), 134 write_test_case(Case), 135 Res = mnesia_test_lib:test(Case, Config), 136 append_test_case_info(Case, Res). 137 138t(Mod, Fun, Config) when Config == diskless -> 139 t({Mod, Fun}, diskless). 140 141config_fname() -> 142 "mnesia_test_case_config". 143 144%% Read default config file 145read_config() -> 146 Fname = config_fname(), 147 mnesia_test_lib:log("Consulting file ~s...~n", [Fname]), 148 case file:consult(Fname) of 149 {ok, Config} -> 150 mnesia_test_lib:log("Read config ~w~n", [Config]), 151 Config; 152 _Error -> 153 Config = mnesia_test_lib:default_config(), 154 mnesia_test_lib:log("<>WARNING<> Using default config: ~w~n", [Config]), 155 Config 156 end. 157 158%% Write new default config file 159write_config(Config) when is_list(Config) -> 160 Fname = config_fname(), 161 {ok, Fd} = file:open(Fname, write), 162 write_list(Fd, Config), 163 file:close(Fd). 164 165write_list(Fd, [H | T]) -> 166 ok = io:format(Fd, "~p.~n",[H]), 167 write_list(Fd, T); 168write_list(_, []) -> 169 ok. 170 171test_case_fname() -> 172 "mnesia_test_case_info". 173 174%% Read name of test case 175read_test_case() -> 176 Fname = test_case_fname(), 177 case file:open(Fname, [read]) of 178 {ok, Fd} -> 179 Res = io:read(Fd, []), 180 file:close(Fd), 181 case Res of 182 {ok, TestCase} -> 183 mnesia_test_lib:log("Using test case ~w from file ~s~n", 184 [TestCase, Fname]), 185 TestCase; 186 {error, _} -> 187 default_test_case(Fname) 188 end; 189 {error, _} -> 190 default_test_case(Fname) 191 end. 192 193default_test_case(Fname) -> 194 TestCase = all, 195 mnesia_test_lib:log("<>WARNING<> Cannot read file ~s, " 196 "using default test case: ~w~n", 197 [Fname, TestCase]), 198 TestCase. 199 200write_test_case(TestCase) -> 201 Fname = test_case_fname(), 202 {ok, Fd} = file:open(Fname, write), 203 ok = io:format(Fd, "~p.~n",[TestCase]), 204 file:close(Fd). 205 206append_test_case_info(TestCase, TestCaseInfo) -> 207 Fname = test_case_fname(), 208 {ok, Fd} = file:open(Fname, [read, write]), 209 ok = io:format(Fd, "~p.~n",[TestCase]), 210 ok = io:format(Fd, "~p.~n",[TestCaseInfo]), 211 file:close(Fd), 212 TestCaseInfo. 213 214%% Generate HTML pages from the test case structure 215doc() -> 216 doc(suite). 217 218doc(Case) -> 219 mnesia_test_lib:doc(resolve(Case)). 220 221%% Display out the test case structure 222struct() -> 223 struct(suite). 224 225struct(Case) -> 226 mnesia_test_lib:struct([resolve(Case)]). 227 228%% Shutdown all nodes with erlang:halt/0 229shutdown() -> 230 mnesia_test_lib:shutdown(). 231 232%% Ping all nodes in config spec 233ping() -> 234 Config = read_config(), 235 Nodes = mnesia_test_lib:select_nodes(all, Config, ?FILE, ?LINE), 236 [{N, net_adm:ping(N)} || N <- Nodes]. 237 238%% Slave start all nodes in config spec 239start_nodes() -> 240 Config = read_config(), 241 Nodes = mnesia_test_lib:select_nodes(all, Config, ?FILE, ?LINE), 242 mnesia_test_lib:init_nodes(Nodes, ?FILE, ?LINE), 243 ping(). 244 245%% loop one testcase /suite until it fails 246 247loop(Case) -> 248 loop_1(Case,-1,read_config()). 249 250loop(M,F) when is_atom(F) -> 251 loop_1({M,F},-1,read_config()); 252loop(Case,N) when is_integer(N) -> 253 loop_1(Case, N,read_config()). 254 255loop(M,F,N) when is_integer(N) -> 256 loop_1({M,F},N,read_config()). 257 258loop_1(Case,N,Config) when N /= 0 -> 259 io:format("Loop test ~p ~n", [abs(N)]), 260 case ok_result(Res = t(Case,Config)) of 261 true -> 262 loop_1(Case,N-1,Config); 263 error -> 264 Res 265 end; 266loop_1(_,_,_) -> 267 ok. 268 269ok_result([{_T,{ok,_,_}}|R]) -> 270 ok_result(R); 271ok_result([{_T,{TC,List}}|R]) when is_tuple(TC), is_list(List) -> 272 ok_result(List) andalso ok_result(R); 273ok_result([]) -> true; 274ok_result(_) -> error. 275