1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 1997-2016. 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_config_test). 23-author('hakan@erix.ericsson.se'). 24 25-include("mnesia_test_lib.hrl"). 26 27-record(test_table,{i,a1,a2,a3}). 28-record(test_table2,{i, b}). 29 30-export([ 31 all/0,groups/0,init_per_group/2,end_per_group/2, 32 access_module/1, 33 auto_repair/1, 34 backup_module/1, 35 debug/1, 36 dir/1, 37 dump_log_load_regulation/1, 38 39 dump_log_update_in_place/1, 40 event_module/1, 41 inconsistent_database/1, 42 max_wait_for_decision/1, 43 send_compressed/1, 44 45 app_test/1, 46 47 schema_merge/1, 48 unknown_config/1, 49 50 dump_log_time_threshold/1, 51 dump_log_write_threshold/1, 52 53 start_one_disc_full_then_one_disc_less/1, 54 start_first_one_disc_less_then_one_disc_full/1, 55 start_first_one_disc_less_then_two_more_disc_less/1, 56 schema_location_and_extra_db_nodes_combinations/1, 57 table_load_to_disc_less_nodes/1, 58 59 dynamic_basic/1, 60 dynamic_ext/1, 61 dynamic_bad/1, 62 63 init_per_testcase/2, 64 end_per_testcase/2, 65 c_nodes/0 66 ]). 67 68-export([check_logs/1]). 69 70-define(init(N, Config), 71 mnesia_test_lib:prepare_test_case([{init_test_case, [mnesia]}, 72 delete_schema, 73 {reload_appls, [mnesia]}], 74 N, Config, ?FILE, ?LINE)). 75-define(acquire(N, Config), 76 mnesia_test_lib:prepare_test_case([{init_test_case, [mnesia]}, 77 delete_schema, 78 {reload_appls, [mnesia]}, 79 create_schema, 80 {start_appls, [mnesia]}], 81 N, Config, ?FILE, ?LINE)). 82-define(acquire_schema(N, Config), 83 mnesia_test_lib:prepare_test_case([{init_test_case, [mnesia]}, 84 delete_schema, 85 {reload_appls, [mnesia]}, 86 create_schema], 87 N, Config, ?FILE, ?LINE)). 88-define(cleanup(N, Config), 89 mnesia_test_lib:prepare_test_case([{reload_appls, [mnesia]}], 90 N, Config, ?FILE, ?LINE)). 91-define(trans(Fun), 92 ?match({atomic, ok}, mnesia:transaction(Fun))). 93 94init_per_testcase(Func, Conf) -> 95 mnesia_test_lib:init_per_testcase(Func, Conf). 96 97end_per_testcase(Func, Conf) -> 98 mnesia_test_lib:end_per_testcase(Func, Conf). 99 100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 101 102 103all() -> 104 [access_module, auto_repair, backup_module, debug, dir, 105 dump_log_load_regulation, {group, dump_log_thresholds}, 106 dump_log_update_in_place, 107 event_module, 108 inconsistent_database, max_wait_for_decision, 109 send_compressed, app_test, {group, schema_config}, 110 unknown_config]. 111 112groups() -> 113 [{dump_log_thresholds, [], 114 [dump_log_time_threshold, dump_log_write_threshold]}, 115 {schema_config, [], 116 [start_one_disc_full_then_one_disc_less, 117 start_first_one_disc_less_then_one_disc_full, 118 start_first_one_disc_less_then_two_more_disc_less, 119 schema_location_and_extra_db_nodes_combinations, 120 table_load_to_disc_less_nodes, schema_merge, 121 {group, dynamic_connect}]}, 122 {dynamic_connect, [], 123 [dynamic_basic, dynamic_ext, dynamic_bad]}]. 124 125init_per_group(_GroupName, Config) -> 126 Config. 127 128end_per_group(_GroupName, Config) -> 129 Config. 130 131 132 133%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 134 135access_module(doc) -> 136 ["Replace the activity access module with another module and ", 137 "use it to read and write to some alternate table storage"]; 138access_module(suite) -> []; 139access_module(Config) when is_list(Config) -> 140 Nodes = ?acquire_schema(1, Config), 141 ?match(ok, mnesia:start([{access_module, mnesia_frag}])), 142 143 ?match(mnesia_frag, mnesia:system_info(access_module)), 144 145 access_tab(ram_copies, Nodes), 146 case mnesia_test_lib:diskless(Config) of 147 true -> skip; 148 false -> 149 access_tab(disc_copies, Nodes) 150 , access_tab(disc_only_copies, Nodes) 151 end, 152 153 ?verify_mnesia(Nodes, []), 154 ?cleanup(1, Config). 155 156access_tab(Storage, Nodes) -> 157 Tab = list_to_atom(lists:concat([access_tab_, Storage])), 158 RecName = some_access, 159 Attr = val, 160 TabDef = [{Storage, Nodes}, 161 {type, bag}, 162 {index, [Attr]}, 163 {record_name, RecName}], 164 ?match({atomic,ok}, mnesia:create_table(Tab, TabDef)), 165 166 Activity = fun(Kind) -> 167 A = [Kind, Tab, RecName, Attr, Nodes], 168 io:format("kind: ~w, storage: ~w~n", [Kind, Storage]), 169 mnesia:activity(Kind, fun do_access/5, A) 170 end, 171 ModActivity = fun(Kind, M) -> 172 io:format("kind: ~w, storage: ~w. module: ~w~n", 173 [Kind, Storage, M]), 174 A = [Kind, Tab, RecName, Attr, Nodes], 175 mnesia:activity(Kind, fun do_access/5, A, M) 176 end, 177 ?match(ok, Activity(transaction)), 178 ?match(ok, Activity({transaction, 47})), 179 ?match(ok, ModActivity(transaction, mnesia)), 180 ?match(ok, ModActivity(transaction, mnesia_frag)), 181 182 ?match(ok, Activity(async_dirty)), 183 ?match(ok, Activity(sync_dirty)), 184 case Storage of 185 ram_copies -> 186 ?match(ok, Activity(ets)); 187 _ -> 188 ignore 189 end. 190 191do_access(Kind, Tab, RecName, Attr, Nodes) -> 192 Tens = lists:sort([{RecName, 1, 10}, {RecName, 3, 10}]), 193 {OptNodes, OptTens} = 194 case Kind of 195 transaction -> {Nodes, Tens}; 196 {transaction, _} -> {Nodes, Tens}; 197 async_dirty -> {[], Tens}; 198 sync_dirty -> {[], Tens}; 199 ets -> {[], []} 200 end, 201 ?match(RecName, mnesia:table_info(Tab, record_name)), 202 203 ?match(ok, mnesia:write(Tab, {RecName, 1, 10}, write)), 204 ?match(ok, mnesia:write(Tab, {RecName, 2, 20}, sticky_write)), 205 ?match(ok, mnesia:write(Tab, {RecName, 2, 21}, sticky_write)), 206 ?match(ok, mnesia:write(Tab, {RecName, 2, 22}, write)), 207 ?match(ok, mnesia:write(Tab, {RecName, 3, 10}, write)), 208 209 Twos = [{RecName, 2, 20}, {RecName, 2, 21}, {RecName, 2, 22}], 210 ?match(Twos, lists:sort(mnesia:read(Tab, 2, read))), 211 212 ?match(ok, mnesia:delete_object(Tab, {RecName, 2, 21}, sticky_write)), 213 214 TenPat = {RecName, '_', 10}, 215 ?match(Tens, lists:sort(mnesia:match_object(Tab, TenPat, read))), 216 ?match(OptTens, lists:sort(mnesia:index_match_object(Tab, TenPat, Attr, read) )), 217 ?match(OptTens, lists:sort(mnesia:index_read(Tab, 10, Attr))), 218 Keys = [1, 2, 3], 219 ?match(Keys, lists:sort(mnesia:all_keys(Tab))), 220 221 First = mnesia:first(Tab), 222 Mid = mnesia:next(Tab, First), 223 Last = mnesia:next(Tab, Mid), 224 ?match('$end_of_table', mnesia:next(Tab, Last)), 225 ?match(Keys, lists:sort([First,Mid,Last])), 226 227 %% For set and bag these last, prev works as first and next 228 First2 = mnesia:last(Tab), 229 Mid2 = mnesia:prev(Tab, First2), 230 Last2 = mnesia:prev(Tab, Mid2), 231 ?match('$end_of_table', mnesia:prev(Tab, Last2)), 232 ?match(Keys, lists:sort([First2,Mid2,Last2])), 233 234 ?match([ok, ok, ok], [mnesia:delete(Tab, K, write) || K <- Keys]), 235 W = wild_pattern, 236 ?match([], mnesia:match_object(Tab, mnesia:table_info(Tab, W), read)), 237 ?log("Safe fixed ~p~n", [catch ets:info(Tab, safe_fixed)]), 238 ?log("Fixed ~p ~n", [catch ets:info(Tab, fixed)]), 239 240 ?match(OptNodes, mnesia:lock({global, some_lock_item, Nodes}, write)), 241 ?match(OptNodes, mnesia:lock({global, some_lock_item, Nodes}, read)), 242 ?match(OptNodes, mnesia:lock({table, Tab}, read)), 243 ?match(OptNodes, mnesia:lock({table, Tab}, write)), 244 245 ok. 246 247%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 248auto_repair(doc) -> 249 ["Try the auto_repair mechanism on the various disk_logs and dets files.", 250 "", 251 "The case tests both normal values of the parameter, and also", 252 "one crazy value.", 253 "The test of the real auto_repair functionality is made in the", 254 "dets suite" 255 ]; 256auto_repair(suite) -> []; 257auto_repair(Config) when is_list(Config) -> 258 ?init(1, Config), 259 ?match(ok, mnesia:start()), % Check default true 260 ?match(true, mnesia:system_info(auto_repair)), 261 ?match(stopped, mnesia:stop()), 262 ?match(ok, mnesia:start([{auto_repair, true}])), 263 ?match(true, mnesia:system_info(auto_repair)), 264 ?match(stopped, mnesia:stop()), 265 ?match(ok, mnesia:start([{auto_repair, false}])), 266 ?match(false, mnesia:system_info(auto_repair)), 267 ?match(stopped, mnesia:stop()), 268 ?match({error, {bad_type, auto_repair, your_mama}}, 269 mnesia:start([{auto_repair, your_mama}])), 270 ?match(stopped, mnesia:stop()), 271 ?cleanup(1, Config), 272 ok. 273 274 275%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 276 277backup_module(doc) -> 278 ["Replace the backup module with another module and use it to", 279 "read and write to an alternate backup media, e.g stored in", 280 "the internal state of a simple process."]; 281backup_module(suite) -> []; 282backup_module(Config) when is_list(Config) -> 283 Nodes = ?acquire_schema(1, Config), 284 ?match(ok, mnesia:start([{backup_module, mnesia_config_backup}])), 285 ?match({atomic,ok}, 286 mnesia:create_table(test_table, 287 [{disc_copies, Nodes}, 288 {attributes, 289 record_info(fields,test_table)}])), 290 291 ?match({atomic,ok}, 292 mnesia:create_table(test_table2, 293 [{disc_copies, Nodes}, 294 {attributes, 295 record_info(fields,test_table2)}])), 296 %% Write in test table 297 ?trans(fun() -> mnesia:write(#test_table{i=1}) end), 298 ?trans(fun() -> mnesia:write(#test_table{i=2}) end), 299 300 %% Write in test table 2 301 ?trans(fun() -> mnesia:write(#test_table2{i=3}) end), 302 ?trans(fun() -> mnesia:write(#test_table2{i=4}) end), 303 mnesia_test_lib:sync_tables(Nodes, [test_table, test_table2]), 304 305 File = whow, 306 %% Now make a backup 307 ?match(ok, mnesia:backup(File)), 308 309 ?match(ok, mnesia:install_fallback(File)), 310 311 %% Now add things 312 ?trans(fun() -> mnesia:write(#test_table{i=2.5}) end), 313 ?trans(fun() -> mnesia:write(#test_table2{i=3.5}) end), 314 315 mnesia_test_lib:kill_mnesia(Nodes), 316 receive after 2000 -> ok end, 317 ?match([], mnesia_test_lib:start_mnesia(Nodes, [test_table, test_table2])), 318 319 %% Now check newly started tables 320 ?match({atomic, [1,2]}, 321 mnesia:transaction(fun() -> lists:sort(mnesia:all_keys(test_table)) end)), 322 ?match({atomic, [3,4]}, 323 mnesia:transaction(fun() -> lists:sort(mnesia:all_keys(test_table2)) end)), 324 325 %% Test some error cases 326 mnesia:set_debug_level(debug), 327 ?match({error, _}, mnesia:install_fallback("NonExisting.FILE")), 328 ?match({error, _}, mnesia:install_fallback(filename:join(mnesia_lib:dir(), "LATEST.LOG"))), 329 330 %% Cleanup 331 file:delete(File), 332 ?verify_mnesia(Nodes, []), 333 ?cleanup(1, Config), 334 ok. 335 336%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 337debug(doc) -> 338 ["Try out the four debug levels and ensure that the", 339 "expected events are generated."]; 340debug(suite) -> []; 341debug(Config) when is_list(Config) -> 342 Nodes = ?init(1, Config), 343 case application:get_env(mnesia,debug) of 344 undefined -> 345 ?match(none, mnesia:system_info(debug)); 346 {ok, false} -> 347 ?match(none, mnesia:system_info(debug)); 348 {ok, true} -> 349 ?match(debug, mnesia:system_info(debug)); 350 {ok, Env} -> 351 ?match(Env, mnesia:system_info(debug)) 352 end, 353 354 ?match(ok, mnesia:start([{debug, verbose}])), 355 ?match(verbose, mnesia:system_info(debug)), 356 mnesia_test_lib:kill_mnesia(Nodes), 357 receive after 2000 -> ok end, 358 359 ?match(ok, mnesia:start([{debug, debug}])), 360 ?match(debug, mnesia:system_info(debug)), 361 mnesia_test_lib:kill_mnesia(Nodes), 362 receive after 2000 -> ok end, 363 364 ?match(ok, mnesia:start([{debug, trace}])), 365 ?match(trace, mnesia:system_info(debug)), 366 mnesia_test_lib:kill_mnesia(Nodes), 367 receive after 2000 -> ok end, 368 369 ?match(ok, mnesia:start([{debug, true}])), 370 ?match(debug, mnesia:system_info(debug)), 371 mnesia_test_lib:kill_mnesia(Nodes), 372 receive after 2000 -> ok end, 373 374 ?match(ok, mnesia:start([{debug, false}])), 375 ?match(none, mnesia:system_info(debug)), 376 377 ?verify_mnesia(Nodes, []), 378 ?cleanup(1, Config), 379 ok. 380 381%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 382dir(doc) -> 383 ["Try to use alternate Mnesia directories"]; 384dir(suite) -> []; 385dir(Config) when is_list(Config) -> 386 Nodes = ?init(1, Config), 387 388 ?match(ok, mnesia:start([{dir, tuff}])), 389 Dir = filename:join([element(2, file:get_cwd()), "tuff"]), 390 ?match(Dir, mnesia:system_info(directory)), 391 mnesia_test_lib:kill_mnesia(Nodes), 392 393 ?cleanup(1, Config), 394 ok. 395 396%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 397dump_log_update_in_place(doc) -> 398 ["Change the update in place policy for the transaction log dumper."]; 399dump_log_update_in_place(suite) -> []; 400dump_log_update_in_place(Config) when is_list(Config) -> 401 Nodes = ?acquire(1, Config), 402 ?match(true, mnesia:system_info(dump_log_update_in_place)), 403 ?match({atomic,ok}, 404 mnesia:create_table(test_table, 405 [{disc_copies, Nodes}, 406 {attributes, 407 record_info(fields,test_table)}])), 408 409 mnesia_test_lib:kill_mnesia(Nodes), 410 receive after 2000 -> ok end, 411 412 ?match(ok, mnesia:start([{dump_log_update_in_place, false}])), 413 ?match(false, mnesia:system_info(dump_log_update_in_place)), 414 415 mnesia_test_lib:sync_tables(Nodes, [schema, test_table]), 416 417 %% Now provoke some log dumps 418 419 L = lists:map( 420 fun(Num) -> 421 %% Write something on one end ... 422 mnesia:transaction( 423 fun() -> 424 mnesia:write(#test_table{i=Num}) end 425 ) end, 426 lists:seq(1, 110)), 427 428 L2 = lists:duplicate(110, {atomic, ok}), 429 430 %% If this fails then some of the 110 writes above failed 431 ?match(true, L==L2), 432 if L==L2 -> ok; 433 true -> 434 ?verbose("***** List1 len: ~p, List2 len: ~p~n", 435 [length(L), length(L2)]), 436 ?verbose("L: ~p~nL2:~p~n", [L, L2]) 437 end, 438 439 %% If we still can write, then Mnesia is probably alive 440 ?trans(fun() -> mnesia:write(#test_table{i=115}) end), 441 442 ?verify_mnesia(Nodes, []), 443 ?cleanup(1, Config), 444 ok. 445 446%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 447 448%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 449dump_log_write_threshold(doc)-> 450 ["This test case must be rewritten.", 451 "Dump logs are tested by doing transactions, then killing Mnesia and ", 452 "then examining the table data files and see if they are correct.", 453 "The test_table is used as a counter, test_table. is stepped once ", 454 "for each transaction."]; 455dump_log_write_threshold(suite)->[]; 456dump_log_write_threshold(Config) when is_list(Config) -> 457 [N1] = ?acquire_schema(1, Config), 458 459 Threshold = 3, 460 ?match(ok,mnesia:start([{dump_log_write_threshold, Threshold}])), 461 462 ?match({atomic,ok}, 463 mnesia:create_table(test_table, 464 [{disc_copies, [N1]}, 465 {attributes, 466 record_info(fields,test_table)}])), 467 ?match(dumped, mnesia:dump_log()), 468 469 ?match(ok, do_trans(2)), % Shall not have dumped 470 check_logs(0), 471 472 ?match(ok, do_trans(Threshold - 2)), % Trigger a dump 473 receive after 1000 -> ok end, 474 check_logs(Threshold), 475 476 477 ?match(ok, do_trans(Threshold - 1)), 478 ?match(dumped, mnesia:dump_log()), %% This should trigger ets2dcd dump 479 check_logs(0), %% and leave no dcl file 480 481 ?match(stopped, mnesia:stop()), 482 483 %% Check bad threshold value 484 ?match({error,{bad_type,dump_log_write_threshold,0}}, 485 mnesia:start([{dump_log_write_threshold,0}])), 486 487 ?verify_mnesia([], [N1]), 488 ?cleanup(1, Config), 489 ok. 490 491 492%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 493dump_log_time_threshold(doc)-> 494 ["See doc on above."]; 495dump_log_time_threshold(suite)->[]; 496dump_log_time_threshold(Config) when is_list(Config) -> 497 Nodes = ?acquire_schema(1, Config), 498 Time = 4000, 499 500 %% Check bad threshold value 501 ?match({error,{bad_type,dump_log_time_threshold,0}}, 502 mnesia:start([{dump_log_time_threshold,0}])), 503 504 505 ?match(ok,mnesia:start([{dump_log_write_threshold,100}, 506 {dump_log_time_threshold, Time}])), 507 508 ?match({atomic,ok},mnesia:create_table(test_table, 509 [{disc_copies, Nodes}, 510 {attributes, 511 record_info(fields, 512 test_table)}])), 513 514 %% Check that nothing is dumped when within time threshold 515 ?match(ok, do_trans(1)), 516 check_logs(0), 517 518 ?match(Time, mnesia:system_info(dump_log_time_threshold)), 519 520 %% Check that things get dumped when time threshold exceeded 521 ?match(ok, do_trans(5)), 522 receive after Time+2000 -> ok end, 523 check_logs(6), 524 525 ?verify_mnesia([node()], []), 526 ?cleanup(1, Config), 527 ok. 528 529%%%%%%%% 530%% 531%% Help functions for dump log 532 533%% Do a transaction N times 534do_trans(0) -> ok; 535do_trans(N) -> 536 Fun = fun() -> 537 XX=incr(), 538 mnesia:write(#test_table{i=XX}) 539 end, 540 {atomic, ok} = mnesia:transaction(Fun), 541 do_trans(N-1). 542 543%% An increasing number 544incr() -> 545 case get(bloody_counter) of 546 undefined -> put(bloody_counter, 2), 1; 547 Num -> put(bloody_counter, Num+1) 548 end. 549 550%% 551%% Check that the correct number of transactions have been recorded. 552%%-record(test_table,{i,a1,a2,a3}). 553check_logs(N) -> 554 File = mnesia_lib:tab2dcl(test_table), 555 Args = [{file, File}, {name, testing}, {repair, true}, {mode, read_only}], 556 557 if N == 0 -> 558 ?match(false, mnesia_lib:exists(File)); 559 true -> 560 ?match(true, mnesia_lib:exists(File)), 561 ?match({ok, _Log}, disk_log:open(Args)), 562 563 {Cont, Terms} = disk_log:chunk(testing, start), 564 ?match(eof, disk_log:chunk(testing, Cont)), 565 %%?verbose("N: ~p, L: ~p~n", [N, L]), 566 disk_log:close(testing), 567 568 %% Correct number of records in file 569 ?match({N, N}, {N, length(Terms) -1 }) %% Ignore Header 570 end. 571 572%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 573 574dump_log_load_regulation(doc) -> 575 ["Test the load regulation of the dumper"]; 576dump_log_load_regulation(suite) -> 577 []; 578dump_log_load_regulation(Config) when is_list(Config) -> 579 Nodes = ?acquire_nodes(1, Config), 580 Param = dump_log_load_regulation, 581 582 %% Normal 583 NoReg = false, 584 ?match(NoReg, mnesia:system_info(Param)), 585 ?match([], mnesia_test_lib:stop_mnesia(Nodes)), 586 587 %% Bad 588 Bad = arne_anka, 589 ?match({error, {bad_type, Param, Bad}}, 590 mnesia:start([{Param, Bad}])), 591 592 %% Regulation activated 593 Reg = true, 594 ?match(ok,mnesia:start([{Param, Reg}])), 595 ?match(Reg, mnesia:system_info(Param)), 596 597 Args = 598 [{db_nodes, Nodes}, 599 {driver_nodes, Nodes}, 600 {replica_nodes, Nodes}, 601 {n_drivers_per_node, 5}, 602 {n_branches, length(Nodes) * 10}, 603 {n_accounts_per_branch, 5}, 604 {replica_type, disc_copies}, 605 {stop_after, timer:seconds(15)}, 606 {report_interval, timer:seconds(3)}, 607 {use_running_mnesia, true}, 608 {reuse_history_id, true}], 609 610 ?match({ok, _}, mnesia_tpcb:start(Args)), 611 612 ?verify_mnesia(Nodes, []), 613 ?cleanup(1, Config), 614 ok. 615 616%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 617 618%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 619 620max_wait_for_decision(doc) -> 621 ["Provoke Mnesia to make a forced decision of the outome", 622 "of a heavy weight transaction."]. 623 624%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 625 626send_compressed(doc) -> []; 627send_compressed(suite) -> []; 628send_compressed(Config) -> 629 [N1,N2] = Nodes = ?acquire_nodes(2, Config), 630 ?match({atomic,ok}, mnesia:create_table(t0, [{ram_copies,[N1,N2]}])), 631 ?match({atomic,ok}, mnesia:create_table(t1, [{disc_copies,[N1,N2]}])), 632 ?match({atomic,ok}, mnesia:create_table(t2, [{disc_only_copies,[N1,N2]}])), 633 634 Max = 1000, 635 Create = fun(Tab) -> [mnesia:write({Tab, N, {N, "FILLER-123490878345asdasd"}}) 636 || N <- lists:seq(1, Max)], 637 ok 638 end, 639 640 ?match([], mnesia_test_lib:kill_mnesia([N2])), 641 sys:get_status(mnesia_monitor), %% sync N1 642 ?match([], mnesia_test_lib:kill_mnesia([N1])), 643 ?match(ok, mnesia:start([{send_compressed, 9}])), 644 ?match(ok, mnesia:wait_for_tables([t0,t1,t2], 25000)), 645 646 ?match({atomic, ok}, mnesia:transaction(Create, [t0])), 647 ?match({atomic, ok}, mnesia:transaction(Create, [t1])), 648 ?match({atomic, ok}, mnesia:transaction(Create, [t2])), 649 650 ?match([], mnesia_test_lib:start_mnesia([N2], [t0,t1,t2])), 651 652 Verify = fun(Tab) -> 653 [ [{Tab,N,{N,_}}] = mnesia:read(Tab, N) || N <- lists:seq(1, Max)], 654 ok 655 end, 656 ?match({atomic, ok}, rpc:call(N1, mnesia, transaction, [Verify, [t0]])), 657 ?match({atomic, ok}, rpc:call(N1, mnesia, transaction, [Verify, [t1]])), 658 ?match({atomic, ok}, rpc:call(N1, mnesia, transaction, [Verify, [t2]])), 659 660 ?match({atomic, ok}, rpc:call(N2, mnesia, transaction, [Verify, [t0]])), 661 ?match({atomic, ok}, rpc:call(N2, mnesia, transaction, [Verify, [t1]])), 662 ?match({atomic, ok}, rpc:call(N2, mnesia, transaction, [Verify, [t2]])), 663 664 ?verify_mnesia(Nodes, []), 665 ?cleanup(1, Config), 666 ok. 667 668app_test(doc) -> []; 669app_test(suite) -> []; 670app_test(_Config) -> 671 ?match(ok,test_server:app_test(mnesia)), 672 ok. 673 674%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 675 676event_module(doc) -> 677 ["Replace the event module with another module and use it as", 678 "receiver of the various system and table events. Provoke", 679 "coverage of all kinds of events."]; 680event_module(suite) -> []; 681event_module(Config) when is_list(Config) -> 682 Filter = fun({mnesia_system_event,{mnesia_info, _, _}}) -> false; 683 (_) -> true 684 end, 685 686 [_N1, N2]=Nodes=?acquire_schema(2, Config), 687 688 Def = case mnesia_test_lib:diskless(Config) of 689 true -> [{event_module, mnesia_config_event}, 690 {extra_db_nodes, Nodes}]; 691 false -> 692 [{event_module, mnesia_config_event}] 693 end, 694 695 ?match({[ok, ok], []}, rpc:multicall(Nodes, mnesia, start, [Def])), 696 receive after 2000 -> ok end, 697 mnesia_event ! {get_log, self()}, 698 DebugLog1 = receive 699 {log, L1} -> L1 700 after 10000 -> [timeout] 701 end, 702 ?match([{mnesia_system_event,{mnesia_up,N2}}], 703 lists:filter(Filter, DebugLog1)), 704 mnesia_test_lib:kill_mnesia([N2]), 705 receive after 2000 -> ok end, 706 707 ?match({[ok], []}, rpc:multicall([N2], mnesia, start, [])), 708 709 receive after 2000 -> ok end, 710 mnesia_event ! {get_log, self()}, 711 DebugLog = receive 712 {log, L} -> L 713 after 10000 -> [timeout] 714 end, 715 ?match([{mnesia_system_event,{mnesia_up,N2}}, 716 {mnesia_system_event,{mnesia_down,N2}}, 717 {mnesia_system_event,{mnesia_up, N2}}], 718 lists:filter(Filter, DebugLog)), 719 ?verify_mnesia(Nodes, []), 720 ?cleanup(1, Config), 721 ok. 722 723%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 725start_one_disc_full_then_one_disc_less(doc)-> 726 ["Start a disk node and then a disk less one. Distribute some", 727 "tables between them."]; 728start_one_disc_full_then_one_disc_less(suite) -> []; 729start_one_disc_full_then_one_disc_less(Config) when is_list(Config) -> 730 [N1, N2] = ?init(2, Config), 731 ?match(ok, mnesia:create_schema([N1])), 732 ?match([], mnesia_test_lib:start_mnesia([N1])), 733 734 ?match({atomic, ok}, mnesia:add_table_copy(schema, N2, ram_copies)), 735 736 ?match(ok, rpc:call(N2, mnesia, start, [[{schema_location, ram}, 737 {extra_db_nodes, [N1]}]])), 738 mnesia_test_lib:sync_tables([N1, N2], [schema]), 739 740 %% Now create some tables 741 ?match({atomic,ok}, 742 mnesia:create_table(test_table, 743 [{ram_copies, [N1, N2]}, 744 {attributes, 745 record_info(fields,test_table)}])), 746 747 ?match({atomic,ok}, 748 rpc:call( 749 N2, mnesia,create_table, [test_table2, 750 [{ram_copies, [N1, N2]}, 751 {attributes, 752 record_info(fields,test_table2)}]])), 753 754 %% Write something on one end ... 755 Rec = #test_table{i=55}, 756 ?match({atomic, ok}, 757 mnesia:transaction(fun() -> mnesia:write(Rec) end)), 758 759 %% ... and read it in the other 760 ?match({atomic, [Rec]}, 761 rpc:call(N2, mnesia, transaction, 762 [fun() -> mnesia:read({test_table, 55}) end])), 763 764 765 %% Then do the same but start at the other end 766 Rec2 = #test_table2{i=155}, 767 ?match({atomic, ok}, 768 rpc:call(N2, mnesia, transaction, 769 [fun() -> 770 mnesia:write(Rec2) end 771 ])), 772 773 ?match({atomic, [Rec2]}, 774 mnesia:transaction(fun() -> mnesia:read({test_table2, 155}) end)), 775 776 ?verify_mnesia([N1, N2], []), 777 ?cleanup(2, Config), 778 ok. 779 780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 781start_first_one_disc_less_then_one_disc_full(doc)-> 782 ["no_doc"]; 783start_first_one_disc_less_then_one_disc_full(suite) -> []; 784start_first_one_disc_less_then_one_disc_full(Config) when is_list(Config) -> 785 [N1, N2] = Nodes = ?init(2, Config), 786 ?match(ok, mnesia:create_schema([N1])), 787 ?match([], mnesia_test_lib:start_mnesia([N1])), 788 789 ?match({atomic, ok}, mnesia:add_table_copy(schema, N2, ram_copies)), 790 791 ?match(ok, rpc:call(N2, mnesia, start, [[{schema_location, ram}, 792 {extra_db_nodes, Nodes}]])), 793 794 mnesia_test_lib:sync_tables([N1, N2], [schema]), 795 796 mnesia_test_lib:kill_mnesia(Nodes), 797 receive after 2000 -> ok end, 798 ?match([], mnesia_test_lib:start_mnesia(Nodes)), 799 800 mnesia_test_lib:sync_tables([N1, N2], [schema]), 801 802 %% Now create some tables 803 ?match({atomic,ok}, 804 rpc:call( 805 N1, mnesia,create_table, [test_table, 806 [%%{disc_copies, [node()]}, 807 {ram_copies, [N1, N2]}, 808 {attributes, 809 record_info(fields,test_table)}]])), 810 mnesia_test_lib:sync_tables([N1, N2], [test_table]), 811 812 ?match({atomic,ok}, 813 rpc:call( 814 N2, mnesia,create_table, [test_table2, 815 [%%{disc_copies, [node()]}, 816 {ram_copies, [N1, N2]}, 817 {attributes, 818 record_info(fields,test_table2)}]])), 819 820 mnesia_test_lib:sync_tables([N1, N2], [test_table, test_table2]), 821 822 %% Assure tables loaded 823 ?match({[ok, ok], []}, 824 rpc:multicall([N1, N2], mnesia, wait_for_tables, 825 [[schema, test_table, test_table2], 10000])), 826 827 %% Write something on one end ... 828 Rec = #test_table{i=55}, 829 ?match({atomic, ok}, 830 rpc:call(N1, mnesia, transaction, 831 [fun() -> mnesia:write(Rec) end])), 832 833 %% ... and read it in the other 834 ?match({atomic, [Rec]}, 835 rpc:call(N2, mnesia, transaction, 836 [fun() -> mnesia:read({test_table, 55}) end])), 837 838 %% Then do the same but start at the other end 839 Rec2 = #test_table2{i=155}, 840 ?match({atomic, ok}, 841 rpc:call(N2, mnesia, transaction, 842 [fun() -> 843 mnesia:write(Rec2) end 844 ])), 845 846 ?match({atomic, [Rec2]}, 847 rpc:call(N1, mnesia, transaction, 848 [fun() -> mnesia:read({test_table2, 155}) end])), 849 850 ?verify_mnesia(Nodes, []), 851 ?cleanup(1, Config), 852 ok. 853 854%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 855start_first_one_disc_less_then_two_more_disc_less(doc)-> 856 ["no doc"]; 857start_first_one_disc_less_then_two_more_disc_less(suite) -> []; 858start_first_one_disc_less_then_two_more_disc_less(Config) when is_list(Config) -> 859 Nodes = [N1, N2, N3] = ?init(3, Config), 860 861 ?match(ok, rpc:call(N1, mnesia, start, [[{schema_location, ram}]])), 862 863 %% Really should use test_lib:mnesia_start for these ones but ... 864 ?match({atomic, ok}, 865 rpc:call(N1, mnesia,add_table_copy, [schema, N2, ram_copies])), 866 ?match({atomic, ok}, 867 rpc:call(N1, mnesia,add_table_copy, [schema, N3, ram_copies])), 868 869 ?match(ok, rpc:call(N2, mnesia, start, [[{schema_location, ram}, 870 {extra_db_nodes, [N1]}]])), 871 ?match(ok, rpc:call(N3, mnesia, start, [[{schema_location, ram}, 872 {extra_db_nodes, [N1, N2]}]])), 873 874 %% Now create some tables 875 ?match({atomic,ok}, 876 rpc:call( 877 N1, mnesia,create_table, [test_table, 878 [%%{disc_copies, [node()]}, 879 {ram_copies, [N1, N2, N3]}, 880 {attributes, 881 record_info(fields,test_table)}]])), 882 883 %% Assure tables loaded 884 ?match({[ok, ok, ok], []}, 885 rpc:multicall([N1, N2, N3], mnesia, wait_for_tables, 886 [[test_table], 1000])), 887 888 %% Write something on one end ... 889 ?match({atomic, ok}, 890 rpc:call(N1, mnesia, transaction, 891 [fun() -> mnesia:write(#test_table{i=44}) end])), 892 893 %% Force synchronicity 894 ?match({atomic, ok}, 895 rpc:call(N1, mnesia, transaction, 896 [fun() -> mnesia:write_lock_table(test_table) end])), 897 898 %% ... and read it in the others 899 ?match({[{atomic, [{test_table, 44, _, _, _}]}, 900 {atomic, [{test_table, 44, _, _, _}]}], []}, 901 rpc:multicall([N2, N3], mnesia, transaction, 902 [fun() -> mnesia:read({test_table, 44}) end])), 903 904 %% Then do the other way around 905 ?match({atomic, ok}, 906 rpc:call(N3, mnesia, transaction, 907 [fun() -> mnesia:write(#test_table{i=33}) end])), 908 %% Force synchronicity 909 ?match({atomic, ok}, 910 rpc:call(N3, mnesia, transaction, 911 [fun() -> mnesia:write_lock_table(test_table) end])), 912 913 ?match({[{atomic, [{test_table, 44, _, _, _}]}, 914 {atomic, [{test_table, 44, _, _, _}]}], []}, 915 rpc:multicall([N1, N2], mnesia, transaction, 916 [fun() -> mnesia:read({test_table, 44}) end])), 917 918 mnesia_test_lib:reload_appls([mnesia], Nodes), 919 ok. 920 921 922%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 923schema_location_and_extra_db_nodes_combinations(doc)-> 924 ["Test schema loaction and extra_db_nodes combinations."]; 925schema_location_and_extra_db_nodes_combinations(suite) -> []; 926schema_location_and_extra_db_nodes_combinations(Config) when is_list(Config) -> 927 [N1, N2] = Nodes = ?init(2, Config), 928 ?match(ok, mnesia:create_schema([N1])), 929 ?match([], mnesia_test_lib:start_mnesia([N1])), 930 931 %% Really should use test_lib:mnesia_start for these ones but ... 932 ?match({atomic, ok}, 933 rpc:call(N1, mnesia,add_table_copy, [schema, N2, ram_copies])), 934 935 ?match(ok, rpc:call(N2, mnesia, start, [[{schema_location, ram}, 936 {extra_db_nodes, [N1]}]])), 937 938 %% Assure tables loaded 939 ?match({[ok, ok], []}, 940 rpc:multicall([N1, N2], mnesia, wait_for_tables, 941 [[schema], 10000])), 942 943 ?verify_mnesia(Nodes, []), 944 ?cleanup(2, Config), 945 ok. 946 947 948%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 949table_load_to_disc_less_nodes(doc)-> 950 ["Load tables to disc less nodes"]; 951table_load_to_disc_less_nodes(suite) -> []; 952table_load_to_disc_less_nodes(Config) when is_list(Config) -> 953 [N1, N2] = ?init(2, Config), 954 955 ?match(ok, rpc:call(N1, mnesia, start, [[{schema_location, ram}]])), 956 957 %% Really should use test_lib:mnesia_start for these ones but ... 958 ?match({atomic, ok}, 959 rpc:call(N1, mnesia,add_table_copy, [schema, N2, ram_copies])), 960 961 ?match(ok, rpc:call(N2, mnesia, start, [[{schema_location, ram}, 962 {extra_db_nodes, [N1]}]])), 963 964 %% Now create some tables 965 ?match({atomic,ok}, 966 rpc:call( 967 N1, mnesia,create_table, [test_table, 968 [%%{disc_copies, [node()]}, 969 {ram_copies, [N1, N2]}, 970 {attributes, 971 record_info(fields,test_table)}]])), 972 973 %% Assure tables loaded 974 ?match({[ok, ok], []}, 975 rpc:multicall([N1, N2], mnesia, wait_for_tables, 976 [[test_table], 1000])), 977 978 %% Write something on one end ... 979 ?match({atomic, ok}, 980 rpc:call(N1, mnesia, transaction, 981 [fun() -> mnesia:write(#test_table{i=44}) end])), 982 983 %% Force synchronicity 984 ?match({atomic, ok}, 985 rpc:call(N1, mnesia, transaction, 986 [fun() -> mnesia:write_lock_table(test_table) end])), 987 988 %% ... and read it in the others 989 ?match({atomic, [{test_table, 44, _, _, _}]}, 990 rpc:call(N2, mnesia, transaction, 991 [fun() -> mnesia:read({test_table, 44}) end])), 992 993 ?cleanup(2, Config), 994 ok. 995 996%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 997schema_merge(doc) -> 998 ["Provoke various schema merge situations.", 999 "Perform various schema updates while some nodes are down,", 1000 "stop the started nodes, start the stopped nodes and perform", 1001 "schema updates. Now we have a situation were some of the table", 1002 "definitions have been changed on two or more nodes independently", 1003 "of each other and when Mnesia on the nodes tries to connect", 1004 "to each other at restart the schema will be merged.", 1005 "Do also try to provoke schema merge situations were the", 1006 "schema cannot be merged."]; 1007 1008schema_merge(suite) -> []; 1009 1010schema_merge(Config) when is_list(Config) -> 1011 [N1, N2]=Nodes=?acquire(2,Config), 1012 1013 mnesia_test_lib:kill_mnesia([N2]), 1014 receive after 1000 -> ok end, 1015 1016 Storage = mnesia_test_lib:storage_type(disc_copies, Config), 1017 ?match({atomic,ok}, 1018 rpc:call( 1019 N1, mnesia,create_table, 1020 [test_table, 1021 [{Storage, [N1]}, 1022 {attributes, 1023 record_info(fields,test_table)}]])), 1024 1025 ?match({atomic, ok}, 1026 rpc:call(N1, mnesia, transaction, 1027 [fun() -> mnesia:write(#test_table{i=44}) end])), 1028 1029 mnesia_test_lib:kill_mnesia([N1]), 1030 receive after 2000 -> ok end, 1031 %% Can't use std start because it waits for schema 1032 ?match(ok, rpc:call(N2, mnesia, start, [])), 1033 1034 ?match({atomic,ok}, 1035 rpc:call( 1036 N2, mnesia,create_table, 1037 [test_table2, 1038 [{Storage, [N2]}, 1039 {attributes, 1040 record_info(fields,test_table2)}]])), 1041 1042 receive after 5000 -> ok end, 1043 1044 ?match({atomic, ok}, 1045 rpc:call(N2, mnesia, transaction, 1046 [fun() -> mnesia:write(#test_table2{i=33}) end])), 1047 1048 %% Can't use std start because it waits for schema 1049 ?match(ok, rpc:call(N1, mnesia, start, [])), 1050 1051 %% Assure tables loaded 1052 ?match({[ok, ok], []}, 1053 rpc:multicall([N1, N2], mnesia, wait_for_tables, 1054 [[schema, test_table, test_table2], 10000])), 1055 1056 %% ... and read it in the others 1057 ?match({[{atomic, [{test_table, 44, _, _, _}]}, 1058 {atomic, [{test_table, 44, _, _, _}]}], []}, 1059 rpc:multicall([N1, N2], mnesia, transaction, 1060 [fun() -> mnesia:read({test_table, 44}) end])), 1061 1062 ?match({[{atomic, [{test_table2, 33, _}]}, 1063 {atomic, [{test_table2, 33, _}]}], []}, 1064 rpc:multicall([N1, N2], mnesia, transaction, 1065 [fun() -> mnesia:read({test_table2, 33}) end])), 1066 1067 ?verify_mnesia(Nodes, []), 1068 ?cleanup(2, Config), 1069 ok. 1070 1071 1072-define(connect(Nodes), mnesia:change_config(extra_db_nodes, Nodes)). 1073-define(rpc_connect(From, Nodes), 1074 rpc:call(From, mnesia, change_config, [extra_db_nodes, Nodes])). 1075 1076 1077sort({ok, NS}) -> 1078 {ok, lists:sort(NS)}; 1079sort(Ns) when is_tuple(Ns) -> 1080 Ns; 1081sort(NS) when is_list(NS) -> 1082 lists:sort(NS). 1083 1084 1085 1086 1087dynamic_basic(suite) -> []; 1088dynamic_basic(Config) when is_list(Config) -> 1089 Nodes = [N1, N2, N3] = ?acquire_nodes(3, Config), 1090 SNs = lists:sort(Nodes), 1091 1092 ?match({atomic, ok}, mnesia:create_table(tab1, [{ram_copies, Nodes--[N1]}, {disc_copies, [N1]}])), 1093 ?match({atomic, ok}, mnesia:create_table(tab2, [{disc_copies, Nodes}])), 1094 1095 ?match({ok, SNs}, sort(?rpc_connect(N1, Nodes))), %% What shall happen? 1096 ?match({ok, []}, sort(?rpc_connect(N1, [nonode@nothosted]))), %% What shall happen? 1097 1098 ?match([], mnesia_test_lib:kill_mnesia([N2])), 1099 ?match(ok, mnesia:delete_schema([N2])), 1100 1101 ?match(ok, mnesia:dirty_write({tab1, 1, 1})), 1102 ?match(ok, mnesia:dirty_write({tab2, 1, 1})), 1103 1104 ?match(ok, rpc:call(N2, mnesia, start, [[{extra_db_nodes, [N1]}, {schema, ?BACKEND}]])), 1105 ?match(ok, rpc:call(N2, mnesia, wait_for_tables, [[tab1,tab2],5000])), 1106 io:format("Here ~p ~n",[?LINE]), 1107 check_storage(N2, N1, [N3]), 1108 ?match(SNs, sort(rpc:call(N1, mnesia, system_info, [running_db_nodes]))), 1109 ?match(SNs, sort(rpc:call(N2, mnesia, system_info, [running_db_nodes]))), 1110 1111 ?match([], mnesia_test_lib:kill_mnesia([N3])), 1112 ?match(ok, mnesia:delete_schema([N3])), 1113 1114 io:format("T1 ~p ~n",[rpc:call(N3,?MODULE,c_nodes,[])]), 1115 ?match(ok, rpc:call(N3, mnesia, start, [[{schema, ?BACKEND}]])), 1116 io:format("T2 ~p ~n",[rpc:call(N3,?MODULE,c_nodes,[])]), 1117 timer:sleep(2000), 1118 io:format("T3 ~p ~n",[rpc:call(N3,?MODULE,c_nodes,[])]), 1119 ?match({ok, [N1]}, sort(?rpc_connect(N3, [N1]))), 1120 io:format("T4 ~p ~n",[rpc:call(N3,?MODULE,c_nodes,[])]), 1121 ?match(ok, rpc:call(N3, mnesia, wait_for_tables, [[tab1,tab2],5000])), 1122 io:format("Here ~p ~n",[?LINE]), 1123 check_storage(N3, N1, [N2]), 1124 ?match(SNs, sort(rpc:call(N1, mnesia, system_info, [running_db_nodes]))), 1125 ?match(SNs, sort(rpc:call(N2, mnesia, system_info, [running_db_nodes]))), 1126 1127 ?match([], mnesia_test_lib:kill_mnesia([N3])), 1128 ?match(ok, mnesia:delete_schema([N3])), 1129 1130 ?match(ok, rpc:call(N3, mnesia, start, [[{schema, ?BACKEND}]])), 1131 ?match({ok, [N3]}, sort(?rpc_connect(N1, [N3]))), 1132 ?match(ok, rpc:call(N3, mnesia, wait_for_tables, [[tab1,tab2],5000])), 1133 io:format("Here ~p ~n",[?LINE]), 1134 check_storage(N3, N1, [N2]), 1135 ?match(SNs, sort(rpc:call(N1, mnesia, system_info, [running_db_nodes]))), 1136 ?match(SNs, sort(rpc:call(N2, mnesia, system_info, [running_db_nodes]))), 1137 1138 mnesia_test_lib:kill_mnesia([N2]), 1139 ?match(ok, mnesia:delete_schema([N2])), 1140 ?match({atomic, ok}, mnesia:del_table_copy(schema, N2)), 1141 1142 % Ok, we have now removed references to node N2 from the other nodes 1143 % mnesia should come up now. 1144 ?match({atomic, ok}, mnesia:add_table_copy(tab1, N2, ram_copies)), 1145 1146 ?match(ok, rpc:call(N2, mnesia, start, [[{schema, ?BACKEND}]])), 1147 ?match({ok, _}, sort(?rpc_connect(N2, [N3]))), 1148 1149 ?match(SNs, sort(rpc:call(N1, mnesia, system_info, [running_db_nodes]))), 1150 ?match(SNs, sort(rpc:call(N2, mnesia, system_info, [running_db_nodes]))), 1151 ?match(SNs, sort(rpc:call(N3, mnesia, system_info, [running_db_nodes]))), 1152 1153 ?match(ok, rpc:call(N2, mnesia, wait_for_tables, [[tab1], 1000])), 1154 ?match([{tab1, 1, 1}], rpc:call(N2, mnesia, dirty_read, [tab1, 1])), 1155 1156 mnesia_test_lib:kill_mnesia([N2]), 1157 1158 %%% SYNC!!! 1159 timer:sleep(1000), 1160 sys:get_status(mnesia_monitor), 1161 1162 ?match([N3,N1], sort(rpc:call(N1, mnesia, system_info, [running_db_nodes]))), 1163 ?match([N3,N1], sort(rpc:call(N3, mnesia, system_info, [running_db_nodes]))), 1164 1165 ?match(ok, rpc:call(N2, mnesia, start, [[{schema, ?BACKEND}]])), 1166 ?match({ok, _}, sort(?rpc_connect(N3, [N2]))), 1167 1168 ?match(SNs, sort(rpc:call(N1, mnesia, system_info, [running_db_nodes]))), 1169 ?match(SNs, sort(rpc:call(N2, mnesia, system_info, [running_db_nodes]))), 1170 ?match(SNs, sort(rpc:call(N3, mnesia, system_info, [running_db_nodes]))), 1171 1172 ?match(ok, rpc:call(N2, mnesia, wait_for_tables, [[tab1], 1000])), 1173 ?match([{tab1, 1, 1}], rpc:call(N2, mnesia, dirty_read, [tab1, 1])), 1174 1175 ?verify_mnesia(Nodes, []), 1176%% ?cleanup(3, Config). 1177 ok. 1178 1179c_nodes() -> 1180 {mnesia_lib:val({current, db_nodes}),mnesia_lib:val(recover_nodes)}. 1181 1182 1183dynamic_ext(suite) -> []; 1184dynamic_ext(Config) when is_list(Config) -> 1185 Ns = [N1,N2] = ?acquire_nodes(2, Config), 1186 SNs = lists:sort([N1,N2]), 1187 1188 ?match({atomic, ok}, mnesia:create_table(tab0, [{disc_copies, [N1,N2]}])), 1189 ?match({atomic, ok}, mnesia:create_table(tab1, [{ram_copies, [N2]}])), 1190 ?match({atomic, ok}, mnesia:create_table(tab2, [{disc_copies, [N2]}])), 1191 ?match({atomic, ok}, mnesia:create_table(tab3, [{disc_only_copies, [N2]}])), 1192 1193 mnesia_test_lib:kill_mnesia([N2]), 1194 ?match(ok, mnesia:delete_schema([N2])), 1195 ?match(ok, rpc:call(N2, mnesia, start, [[{extra_db_nodes, [N1]}, {schema, ?BACKEND}]])), 1196 1197 ?match(SNs, sort(rpc:call(N1, mnesia, system_info, [running_db_nodes]))), 1198 ?match(SNs, sort(rpc:call(N2, mnesia, system_info, [running_db_nodes]))), 1199 1200 ?match(ok, rpc:call(N2, mnesia, wait_for_tables, [[tab0,tab1,tab2,tab3], 2000])), 1201 1202 Check = fun({Tab,Storage}) -> 1203 ?match(Storage, rpc:call(N2, mnesia, table_info, [Tab, storage_type])), 1204 ?match([{N2,Storage}], 1205 lists:sort(rpc:call(N2, mnesia, table_info, [Tab, where_to_commit]))) 1206 end, 1207 [Check(Test) || Test <- [{tab1, ram_copies},{tab2, disc_copies},{tab3, disc_only_copies}]], 1208 1209 T = erlang:unique_integer(), 1210 ?match(ok, mnesia:dirty_write({tab0, 42, T})), 1211 ?match(ok, mnesia:dirty_write({tab1, 42, T})), 1212 ?match(ok, mnesia:dirty_write({tab2, 42, T})), 1213 ?match(ok, mnesia:dirty_write({tab3, 42, T})), 1214 1215 ?match(stopped, rpc:call(N2, mnesia, stop, [])), 1216 ?match(ok, rpc:call(N2, mnesia, start, [[{schema, ?BACKEND}]])), 1217 ?match(SNs, sort(rpc:call(N2, mnesia, system_info, [running_db_nodes]))), 1218 ?match(ok, mnesia:wait_for_tables([tab0,tab1,tab2,tab3], 10000)), 1219 ?match(ok, rpc:call(N2, mnesia, wait_for_tables, [[tab1,tab2,tab3], 100])), 1220 ?match([], mnesia:dirty_read({tab1, 41})), 1221 ?match([{tab2,42,T}], mnesia:dirty_read({tab2, 42})), 1222 ?match([{tab3,42,T}], mnesia:dirty_read({tab3, 42})), 1223 1224 mnesia_test_lib:kill_mnesia([N2]), 1225 ?match(ok, mnesia:delete_schema([N2])), 1226 1227 ?match(stopped, rpc:call(N1, mnesia, stop, [])), 1228 1229 ?match(ok, rpc:call(N2, mnesia, start, [[{extra_db_nodes,[N1,N2]}, {schema, ?BACKEND}]])), 1230 ?match({timeout,[tab0]}, rpc:call(N2, mnesia, wait_for_tables, [[tab0], 500])), 1231 1232 ?match(ok, rpc:call(N1, mnesia, start, [[{extra_db_nodes, [N1,N2]}]])), 1233 ?match(ok, rpc:call(N1, mnesia, wait_for_tables, [[tab0], 1500])), 1234 ?match(ok, rpc:call(N2, mnesia, wait_for_tables, [[tab0], 1500])), 1235 ?match([{tab0,42,T}], mnesia:dirty_read({tab0, 42})), 1236 ?match([{tab0,42,T}], rpc:call(N2, mnesia,dirty_read,[{tab0,42}])), 1237 1238 ?match(stopped, rpc:call(N1, mnesia, stop, [])), 1239 mnesia_test_lib:kill_mnesia([N2]), 1240 ?match(ok, mnesia:delete_schema([N2])), 1241 ?match(ok, rpc:call(N1, mnesia, start, [[{extra_db_nodes, [N1,N2]}, {schema, ?BACKEND}]])), 1242 ?match({timeout,[tab0]}, rpc:call(N1, mnesia, wait_for_tables, [[tab0], 500])), 1243 1244 ?match(ok, rpc:call(N2, mnesia, start, [[{extra_db_nodes,[N1,N2]}]])), 1245 ?match(ok, rpc:call(N1, mnesia, wait_for_tables, [[tab0], 1500])), 1246 ?match(ok, rpc:call(N2, mnesia, wait_for_tables, [[tab0], 1500])), 1247 ?match([{tab0,42,T}], mnesia:dirty_read({tab0, 42})), 1248 ?match([{tab0,42,T}], rpc:call(N2,mnesia,dirty_read,[{tab0,42}])), 1249 1250 ?verify_mnesia(Ns, []), 1251 ok. 1252 1253check_storage(Me, Orig, Other) -> 1254 io:format("Nodes ~p ~p ~p~n",[Me,Orig,Other]), 1255 rpc:multicall(Other, sys, status, [mnesia_locker]), 1256 rpc:call(Me, sys, status, [mnesia_locker]), 1257 rpc:call(Orig, sys, status, [mnesia_locker]), 1258 rpc:multicall(Other, sys, status, [mnesia_controller]), 1259 rpc:call(Me, sys, status, [mnesia_controller]), 1260 rpc:call(Orig, sys, status, [mnesia_controller]), 1261 %% Verify disc_copies 1262 W2C = lists:sort([{Node,disc_copies} || Node <- [Me,Orig|Other]]), 1263 W2W = lists:sort([Me,Orig|Other]), 1264 ?match(disc_copies, rpc:call(Orig, mnesia, table_info, [schema, storage_type])), 1265 ?match(disc_copies, rpc:call(Me, mnesia, table_info, [schema, storage_type])), 1266 ?match(W2C, lists:sort(rpc:call(Orig, mnesia, table_info, [schema, where_to_commit]))), 1267 ?match(W2C, lists:sort(rpc:call(Me, mnesia, table_info, [schema, where_to_commit]))), 1268 1269 ?match(disc_copies, rpc:call(Orig, mnesia, table_info, [tab2, storage_type])), 1270 ?match(disc_copies, rpc:call(Me, mnesia, table_info, [tab2, storage_type])), 1271 ?match(W2W, lists:sort(rpc:call(Me, mnesia, table_info, [tab2, where_to_write]))), 1272 ?match(Me, rpc:call(Me, mnesia, table_info, [tab2, where_to_read])), 1273 1274 ?match(W2C, lists:sort(rpc:call(Orig, mnesia, table_info, [tab2, where_to_commit]))), 1275 ?match(W2C, lists:sort(rpc:call(Me, mnesia, table_info, [tab2, where_to_commit]))), 1276 1277 ?match([{tab1,1,1}], mnesia:dirty_read(tab1,1)), 1278 ?match([{tab2,1,1}], mnesia:dirty_read(tab2,1)), 1279 ?match([{tab1,1,1}], rpc:call(Me, mnesia, dirty_read, [tab1,1])), 1280 ?match([{tab2,1,1}], rpc:call(Me, mnesia, dirty_read, [tab2,1])), 1281 1282 ?match(true, rpc:call(Me, mnesia_monitor, use_dir, [])), 1283 ?match(disc_copies, rpc:call(Me, mnesia_lib, val, [{schema, storage_type}])), 1284 1285 mnesia_test_lib:kill_mnesia([Orig]), 1286 mnesia_test_lib:kill_mnesia(Other), 1287 T = erlang:unique_integer(), 1288 ?match(ok, rpc:call(Me, mnesia, dirty_write, [{tab2, 42, T}])), 1289 ?match(stopped, rpc:call(Me, mnesia, stop, [])), 1290 ?match(ok, rpc:call(Me, mnesia, start, [])), 1291 ?match([], mnesia_test_lib:start_mnesia([Orig|Other], [tab1,tab2])), 1292 ?match([{tab2,42,T}], rpc:call(Me, mnesia, dirty_read, [{tab2, 42}])), 1293 ?match([{tab2,42,T}], rpc:call(Orig, mnesia, dirty_read, [{tab2, 42}])), 1294 1295 ?match([{tab1,1,1}], mnesia:dirty_read(tab1,1)), 1296 ?match([{tab2,1,1}], mnesia:dirty_read(tab2,1)), 1297 ?match([{tab1,1,1}], rpc:call(Me, mnesia, dirty_read, [tab1,1])), 1298 ?match([{tab2,1,1}], rpc:call(Me, mnesia, dirty_read, [tab2,1])), 1299 ok. 1300 1301 1302dynamic_bad(suite) -> []; 1303dynamic_bad(Config) when is_list(Config) -> 1304 Ns = [N1, N2, N3] = ?acquire_nodes(3, Config), 1305 SNs = lists:sort([N2,N3]), 1306 1307 ?match({atomic, ok}, mnesia:change_table_copy_type(schema, N2, ram_copies)), 1308 ?match({atomic, ok}, mnesia:change_table_copy_type(schema, N3, ram_copies)), 1309 ?match({atomic, ok}, mnesia:create_table(tab1, [{ram_copies, Ns -- [N1]}, 1310 {disc_copies, [N1]}])), 1311 ?match(ok, mnesia:dirty_write({tab1, 1, 1})), 1312 1313 mnesia_test_lib:kill_mnesia(Ns), 1314 ?match({[ok, ok], []}, rpc:multicall(Ns -- [N1], mnesia, start, [])), 1315 ?match({ok, [N2]}, ?rpc_connect(N3, [N2])), 1316 ?match(SNs, sort(rpc:call(N2, mnesia, system_info, [running_db_nodes]))), 1317 ?match(SNs, sort(rpc:call(N3, mnesia, system_info, [running_db_nodes]))), 1318 ?match({badrpc, {'EXIT', {aborted, {no_exists, _, _}}}}, 1319 rpc:call(N2, mnesia, table_info, [tab1, where_to_read])), 1320 1321 ?match(ok, mnesia:start()), 1322 ?match(ok, rpc:call(N2, mnesia, wait_for_tables, [[tab1], 1000])), 1323 ?match(N2, rpc:call(N2, mnesia, table_info, [tab1, where_to_read])), 1324 ?match([{tab1, 1, 1}], rpc:call(N2, mnesia, dirty_read, [tab1, 1])), 1325 1326 mnesia_test_lib:kill_mnesia(Ns), 1327 ?match({[ok, ok], []}, rpc:multicall(Ns -- [N1], mnesia, start, [])), 1328 ?match({ok, [N2]}, ?rpc_connect(N3, [N2])), 1329 % Make a merge conflict 1330 ?match({atomic, ok}, rpc:call(N3, mnesia, create_table, [tab1, []])), 1331 1332 io:format("We expect a mnesia crash here~n", []), 1333 ?match({error,{_, _}}, mnesia:start()), 1334 1335 ?verify_mnesia(Ns -- [N1], []), 1336 ok. 1337 1338 1339%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1340unknown_config(doc) -> 1341 ["Try some unknown configuration parameters and see that expected", 1342 "things happens."]; 1343unknown_config(suite)-> []; 1344unknown_config(Config) when is_list(Config) -> 1345 ?init(1, Config), 1346 %% NOTE: case 1 & 2 below do not respond the same 1347 ?match({error, Res} when element(1, Res) == bad_type, 1348 mnesia:start([{undefined_config,[]}])), 1349 %% Below does not work, but the "correct" behaviour would be to have 1350 %% case 1 above to behave as the one below. 1351 1352 %% in mnesia-1.3 {error,{bad_type,{[],undefined_config}}} 1353 ?match({error, Res} when element(1, Res) == bad_type, 1354 mnesia:start([{[],undefined_config}])), 1355 ?cleanup(1, Config), 1356 ok. 1357 1358 1359%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1360inconsistent_database(doc) -> 1361 ["Replace the event module with another module and use it as", 1362 "receiver of the various system and table events. Provoke", 1363 "coverage of all kinds of events."]; 1364inconsistent_database(suite) -> []; 1365inconsistent_database(Config) when is_list(Config) -> 1366 Nodes = mnesia_test_lib:prepare_test_case([{init_test_case, [mnesia]}], 1367 2, Config, ?FILE, ?LINE), 1368 KillAfter = length(Nodes) * timer:minutes(5), 1369 ?acquire_schema(2, Config ++ [{tc_timeout, KillAfter}]), 1370 1371 Ok = [ok || _N <- Nodes], 1372 StartArgs = [{event_module, mnesia_inconsistent_database_test}], 1373 ?match({Ok, []}, rpc:multicall(Nodes, mnesia, start, [StartArgs])), 1374 ?match([], mnesia_test_lib:kill_mnesia(Nodes)), 1375 1376 ?match(ok, mnesia_meter:go(ram_copies, Nodes)), 1377 1378 mnesia_test_lib:reload_appls([mnesia], Nodes), 1379 ok. 1380 1381