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-module(compiler_1). 21-compile([export_all]). 22 23compiler_1() -> ok. 24 25-define(log(Format,Args),mnesia_test_lib:log(Format,Args,?FILE,?LINE)). 26-define(warning(Format,Args),?log("<WARNING> " ++ Format,Args)). 27-define(error(Format,Args), 28 mnesia_test_lib:note_error(Format,Args,?FILE,?LINE), 29 ?log("<ERROR> " ++ Format,Args)). 30 31-define(match(ExpectedRes,Expr), 32 fun() -> 33 AcTuAlReS = (catch (Expr)), 34 case AcTuAlReS of 35 ExpectedRes -> 36 ?log("ok, result as expected: ~p~n",[AcTuAlReS]), 37 {success,AcTuAlReS}; 38 _ -> 39 ?error("actual result was: ~p~n",[AcTuAlReS]), 40 {fail,AcTuAlReS} 41 end 42 end()). 43 44-define(match_inverse(NotExpectedRes,Expr), 45 fun() -> 46 AcTuAlReS = (catch (Expr)), 47 case AcTuAlReS of 48 NotExpectedRes -> 49 ?error("actual result was: ~p~n",[AcTuAlReS]), 50 {fail,AcTuAlReS}; 51 _ -> 52 ?log("ok, result as expected: ~p~n",[AcTuAlReS]), 53 {success,AcTuAlReS} 54 end 55 end()). 56 57-define(match_receive(ExpectedMsg), 58 ?match(ExpectedMsg,mnesia_test_lib:pick_msg())). 59 60%% ExpectedMsgs must be completely bound 61-define(match_multi_receive(ExpectedMsgs), 62 fun() -> 63 TmPeXpCtEdMsGs = lists:sort(ExpectedMsgs), 64 ?match(TmPeXpCtEdMsGs, 65 lists:sort(lists:map(fun(_) -> 66 mnesia_test_lib:pick_msg() 67 end, 68 TmPeXpCtEdMsGs))) 69 end()). 70 71-define(setup(), mnesia_test_lib:setup(?FILE,?LINE)). 72 73-define(start_activities(Nodes), 74 fun() -> 75 AcTiViTyPiDs = 76 lists:map(fun(Node) -> 77 spawn_link(Node, 78 mnesia_test_lib, 79 activity_evaluator, 80 [self()]) 81 end, 82 Nodes), 83 ?match_multi_receive(AcTiViTyPiDs) 84 end()). 85 86-define(start_transactions(Pids), 87 ?match_multi_receive(lists:map(fun(Pid) -> 88 Pid ! begin_trans, 89 {Pid,begin_trans} 90 end, 91 Pids))). 92 93-define(acquire_nodes(N,Nodes), 94 mnesia_test_lib:acquire_nodes(N,Nodes,?FILE,?LINE)). 95 96 97 98%%% Copyright (C) 1996, Ellemtel Telecommunications Systems Laboratories 99%%% Author: Hakan Mattsson hakan@erix.ericsson.se 100%%% Purpose: Evil usage of the API 101%%% 102%%% Invoke all functions in the API and try to cover all legal uses 103%%% cases as well the illegal dito. This is a complement to the 104%%% other more explicit test cases. 105%%% 106%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 107%%% 108%%% show/0 109%%% 110%%% Prints out the complete test case structure 111%%% 112%%% show/1 113%%% 114%%% Prints out parts of the test case structure 115%%% 116%%% test/0 117%%% 118%%% Run the complete test suite. 119%%% Reads Nodes from nodes.profile and starts them if neccessary. 120%%% Kills Mnesia and wipes out the Mnesia directories as a starter. 121%%% 122%%% test/1 123%%% 124%%% Run parts of the test suite. 125%%% Reads Nodes from nodes.profile and starts them if neccessary. 126%%% Kills Mnesia and wipes out the Mnesia directories as a starter. 127%%% 128%%% test/2 129%%% 130%%% Run parts of the test suite on the given Nodes, 131%%% assuming that the nodes are up and running. 132%%% Kills Mnesia and wipes out the Mnesia directories as a starter. 133%%% 134%%% test/3 135%%% 136%%% Run parts of the test suite on permutations of the given Nodes, 137%%% assuming that the nodes are up and running. Uses test/2. 138%%% Kills Mnesia and wipes out the Mnesia directories as a starter. 139%%% 140%%% See the module mnesia_test_lib for further information. 141%%% 142%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 143 144show() -> mnesia_test_lib:show([{?MODULE,all}]). 145show(TestCases) -> mnesia_test_lib:show([{?MODULE,TestCases}]). 146test() -> mnesia_test_lib:test([{?MODULE,all}]). 147test(TestCases) -> mnesia_test_lib:test([{?MODULE,TestCases}]). 148test(TestCases,Nodes) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes). 149test(TestCases,Nodes,Config) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes,Config). 150 151%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 152 153old_all(suite) -> 154 [ 155 system_info, table_info, error_description, 156 db_node_lifecycle, start_and_stop, transaction, checkpoint, backup, 157 table_lifecycle, replica_management, replica_location, index_lifecycle, 158 trans_access, dirty_access, table_sync, snmp_access, debug_support 159 ]. 160 161trans_access(suite) -> 162 [ {mnesia_dirty_access_test,all} ]. 163 164dirty_access(suite) -> 165 [ {mnesia_trans_access_test,all} ]. 166 167%% Get meta info about Mnesia 168system_info(suite) -> []; 169system_info(Nodes) -> 170 ?match(yes,mnesia:system_info(is_running)), 171 ?match(Nodes,mnesia:system_info(db_nodes)), 172 ?match(Nodes,mnesia:system_info(running_db_nodes)), 173 ?match(true,mnesia:system_info(have_disc)), 174 ?match(A when atom(A),mnesia:system_info(debug)), 175 ?match(L when list(L),mnesia:system_info(directory)), 176 ?match(L when list(L),mnesia:system_info(log_version)), 177 ?match({_,_},mnesia:system_info(schema_version)), 178 ?match(L when list(L),mnesia:system_info(tables)), 179 ?match(L when list(L),mnesia:system_info(local_tables)), 180 ?match(L when list(L),mnesia:system_info(held_locks)), 181 ?match(L when list(L),mnesia:system_info(lock_queue)), 182 ?match(L when list(L),mnesia:system_info(transactions)), 183 ?match(I when integer(I),mnesia:system_info(transaction_failures)), 184 ?match(I when integer(I),mnesia:system_info(transaction_commits)), 185 ?match(I when integer(I),mnesia:system_info(transaction_restarts)), 186 ?match(L when list(L),mnesia:system_info(checkpoints)), 187 ?match(A when atom(A),mnesia:system_info(backup_module)), 188 ?match(true,mnesia:system_info(auto_repair)), 189 ?match({_,_},mnesia:system_info(dump_log_interval)), 190 ?match(A when atom(A),mnesia:system_info(dump_log_update_in_place)), 191 ?match(I when integer(I),mnesia:system_info(transaction_log_writes)), 192 ?match({'EXIT',{aborted,badarg}},mnesia:system_info(ali_baba)), 193 done. 194 195%% Get meta info about table 196table_info(suite) -> []; 197table_info(Nodes) -> 198 [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), 199 200 Tab = table_info, 201 Type = bag, 202 ValPos = 3, 203 Attrs = [k,v], 204 Arity = length(Attrs) +1, 205 Schema = [{name,Tab},{type,Type},{attributes,Attrs},{index,[ValPos]}, 206 {disc_only_copies,[Node1]},{ram_copies,[Node2]},{disc_copies,[Node3]}], 207 ?match({atomic,ok}, mnesia:create_table(Schema)), 208 209 Size = 10, 210 Keys = lists:seq(1,Size), 211 Records = [{Tab,A,7} || A <- Keys], 212 lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records), 213 ?match(Mem when integer(Mem),mnesia:table_info(Tab,memory)), 214 ?match(Size,mnesia:table_info(Tab,size)), 215 ?match(Type,mnesia:table_info(Tab,type)), 216 ?match([Node3],mnesia:table_info(Tab,disc_copies)), 217 ?match([Node2],mnesia:table_info(Tab,ram_copies)), 218 ?match([Node1],mnesia:table_info(Tab,disc_only_copies)), 219 Read = [Node1,Node2,Node3], 220 ?match(true,lists:member(mnesia:table_info(Tab,where_to_read),Read)), 221 Write = lists:sort([Node1,Node2,Node3]), 222 ?match(Write,lists:sort(mnesia:table_info(Tab,where_to_write))), 223 WriteLock = lists:sort([Node2,Node3]), 224 ?match([ValPos],mnesia:table_info(Tab,index)), 225 ?match(Arity,mnesia:table_info(Tab,arity)), 226 ?match(Attrs,mnesia:table_info(Tab,attributes)), 227 ?match({Tab,'_','_'},mnesia:table_info(Tab,wild_pattern)), 228 ?match({atomic,Attrs}, mnesia:transaction(fun() -> 229 mnesia:table_info(Tab,attributes) end)), 230 231 done. 232 233%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 234%% Add and drop db nodes 235 236db_node_lifecycle(suite) -> []; 237db_node_lifecycle(Nodes) -> 238 [Node1,Node2] = ?acquire_nodes(2,Nodes), 239 Tab = db_node_lifecycle, 240 241 Schema = [{name,Tab},{ram_copies,[Node1,Node2]}], 242 ?match({atomic,ok}, mnesia:create_table(Schema)), 243 ?match({aborted,active}, rpc:call(Node1,mnesia,del_db_node,[Node2])), 244 245 ?match([], mnesia_test_lib:stop_mnesia(Nodes)), 246 ?match(ok, mnesia:delete_schema(Nodes)), 247 ?match({error,_}, mnesia:create_schema(foo)), 248 ?match({error,_}, mnesia:create_schema([foo])), 249 ?match({error,_}, mnesia:create_schema([foo@bar])), 250 ?match({error,_}, mnesia:start()), 251 252 ?match(ok, mnesia:create_schema(Nodes)), 253 ?match([],mnesia_test_lib:start_mnesia(Nodes)), 254 ?match({atomic,ok}, rpc:call(Node1,mnesia,del_db_node,[Node2])), 255 ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[Node2])), 256 ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo])), 257 ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo@bar])), 258 259 ?match([], mnesia_test_lib:stop_mnesia([Node2])), 260 ?match(ok,mnesia:delete_schema([Node2])), 261 AddFun = fun() -> ?match({aborted,nested_transaction}, 262 mnesia:add_db_node(Node2)), ok end, 263 ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[AddFun])), 264 DelFun = fun() -> ?match({aborted,nested_transaction}, 265 mnesia:del_db_node(Node2)), ok end, 266 ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[DelFun])), 267 268 ?match({atomic,ok}, rpc:call(Node1,mnesia,add_db_node,[Node2])), 269 ?match({aborted,already_exists}, rpc:call(Node1,mnesia,add_db_node,[Node2])), 270 ?match([],mnesia_test_lib:start_mnesia([Node2])), 271 ?match({atomic,ok}, mnesia:create_table(Schema)), 272 done. 273 274%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 275%% Start and stop the system 276 277start_and_stop(suite) -> []; 278start_and_stop(Nodes) -> 279 [Node1] = ?acquire_nodes(1,Nodes), 280 281 ?match(stopped, rpc:call(Node1,mnesia,stop,[])), 282 ?match(stopped, rpc:call(Node1,mnesia,stop,[])), 283 ?match({started,_}, rpc:call(Node1,mnesia,start,[])), 284 ?match({started,_}, rpc:call(Node1,mnesia,start,[])), 285 ?match(stopped, rpc:call(Node1,mnesia,stop,[])), 286 ?match([],mnesia_test_lib:start_mnesia(Nodes)), 287 done. 288 289%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 290%% Checkpoints and backup management 291 292checkpoint(suite) -> []; 293checkpoint(Nodes) -> 294 OneNode = ?acquire_nodes(1,Nodes), 295 checkpoint(OneNode,Nodes), 296 TwoNodes = ?acquire_nodes(2,Nodes), 297 checkpoint(TwoNodes,Nodes). 298 299checkpoint(TabNodes,Nodes) -> 300 [Node1] = ?acquire_nodes(1,TabNodes), 301 CreateTab = fun(Type,N,Ns) -> 302 Tab0 = lists:concat(["local_checkpoint_",Type,N]), 303 Tab = list_to_atom(Tab0), 304 Schema = [{name,Tab},{Type,Ns}], 305 ?match({atomic,ok},mnesia:delete_table(Tab)), 306 ?match({atomic,ok},mnesia:create_table(Schema)), 307 Tab 308 end, 309 CreateTabs = fun(Type) -> 310 CreateTab(Type,1,hd(TabNodes)), 311 CreateTab(Type,2,TabNodes), 312 CreateTab(Type,3,lists:last(TabNodes)) 313 end, 314 Types = [ram_copies,disc_copies,disc_only_copies], 315 Tabs = lists:append(lists:map(CreateTabs,Types)), 316 Recs = lists:sort([{T,N,N} || T <- Tabs,N <- lists:seq(1,10)]), 317 lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs), 318 319 CpName = a_checkpoint_name, 320 MinArgs = [{name,CpName},{min,Tabs},{allow_remote,false}], 321 ?match({ok,CpName,[Node1]}, 322 rpc:call(Node1,mnesia,activate_checkpoint,[MinArgs])), 323 ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), 324 325 MaxArgs = [{name,CpName},{max,Tabs},{allow_remote,true}], 326 ?match({ok,CpName,[Node1]}, 327 rpc:call(Node1,mnesia,activate_checkpoint,[MaxArgs])), 328 ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), 329 330 Args = [{name,CpName},{min,Tabs},{allow_remote,false}], 331 ?match({ok,CpName,[Node1]}, 332 rpc:call(Node1,mnesia,activate_checkpoint,[Args])), 333 Recs2 = lists:sort([{T,K,0} || {T,K,_} <- Recs]), 334 lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs2), 335 ?match({atomic,ok},rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), 336 337 ?match({error,no_exists},mnesia:deactivate_checkpoint(CpName)), 338 ?match({error,badarg},mnesia:activate_checkpoint(foo)), 339 ?match({error,badarg},mnesia:activate_checkpoint([{foo,foo}])), 340 ?match({error,badarg},mnesia:activate_checkpoint([{max,foo}])), 341 ?match({error,badarg},mnesia:activate_checkpoint([{min,foo}])), 342 ?match({error,no_exists},mnesia:activate_checkpoint([{min,[foo@bar]}])), 343 ?match({error,badarg},mnesia:activate_checkpoint([{allow_remote,foo}])), 344 345 Fun = fun(Tab) -> ?match({atomic,ok},mnesia:delete_table(Tab)) end, 346 lists:foreach(Fun,Tabs), 347 done. 348 349backup(suite) -> 350 [ 351 backup_schema, restore_schema, backup_checkpoint, restore_tables 352 ]. 353 354%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 355%% Use and misuse transactions 356 357transaction(suite) -> []; 358transaction(Nodes) -> 359 [Node1] = ?acquire_nodes(1,Nodes), 360 ?match({atomic,ali_baba}, mnesia:transaction(fun() -> ali_baba end)), 361 ?match({aborted,_}, mnesia:transaction(no_fun)), 362 ?match({aborted,_}, mnesia:transaction(?MODULE,no_fun,[foo])), 363 364 {success,[A,B,C,D,E,F,G,H]} = ?start_activities(lists:duplicate(8,Node1)), 365 ?start_transactions([A,B,C,D,E,F,G,H]), 366 367 A ! fun() -> mnesia:abort(abort_bad_trans) end, 368 ?match_receive({A,{aborted,abort_bad_trans}}), 369 370 B ! fun() -> 1 = 2 end, 371 ?match_receive({B,{aborted,_}}), 372 373 C ! fun() -> throw(throw_bad_trans) end, 374 ?match_receive({C,{aborted,{throw,throw_bad_trans}}}), 375 376 D ! fun() -> exit(exit_bad_trans) end, 377 ?match_receive({D,{aborted,exit_bad_trans}}), 378 379 E ! fun() -> exit(normal) end, 380 ?match_receive({E,{aborted,normal}}), 381 382 F ! fun() -> exit(abnormal) end, 383 ?match_receive({F,{aborted,abnormal}}), 384 385 G ! fun() -> exit(G,abnormal) end, 386 ?match_receive({'EXIT',G,abnormal}), 387 388 H ! fun() -> exit(H,kill) end, 389 ?match_receive({'EXIT',H,killed}), 390 391 ?match({atomic,ali_baba}, 392 mnesia:transaction(fun() -> ali_baba end,infinity)), 393 ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,1)), 394 ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,0)), 395 ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,-1)), 396 ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,foo)), 397 Fun = fun() -> ?match({aborted,nested_transaction}, 398 mnesia:transaction(fun() -> ok end)), ok end, 399 ?match({atomic,ok},mnesia:transaction(Fun)), 400 done. 401 402%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 403%% Create and delete tables 404 405%% Get meta info about table 406 407replica_location(suite) -> []; 408replica_location(Nodes) -> 409 [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), 410 Tab = replica_location, 411 412 %% Create three replicas 413 Schema = [{name,Tab},{disc_only_copies,[Node1]}, 414 {ram_copies,[Node2]},{disc_copies,[Node3]}], 415 ?match({atomic,ok}, mnesia:create_table(Schema)), 416 mnesia_test_lib:verify_replica_location(Tab,[Node1],[Node2],[Node3],Nodes), 417 418 %% Delete one replica 419 ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)), 420 mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node3],Nodes), 421 422 %% Move one replica 423 ?match({atomic,ok}, mnesia:move_table_copy(Tab, Node1, Node2)), 424 mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node3],Nodes), 425 426 %% Change replica type 427 ?match({atomic,ok}, mnesia:change_table_copy_type(Tab, Node2,ram_copies)), 428 mnesia_test_lib:verify_replica_location(Tab,[],[Node2],[Node3],Nodes), 429 430 done. 431 432table_lifecycle(suite) -> []; 433table_lifecycle(Nodes) -> 434 [Node1,Node2] = ?acquire_nodes(2,Nodes), 435 436 ?match({atomic,ok}, mnesia:create_table([{type,bag}, 437 {ram_copies,[Node1]}, 438 {attributes,[rajtan,tajtan]}, 439 {name,order_of_args}])), 440 ?match([],mnesia:dirty_read({order_of_args,4711})), 441 ?match({atomic,ok}, mnesia:create_table([{name,already_exists}, 442 {ram_copies,[Node1]}])), 443 ?match({aborted,already_exists}, 444 mnesia:create_table([{name,already_exists},{ram_copies,[Node1]}])), 445 ?match({aborted,not_a_db_node}, 446 mnesia:create_table([{name,no_node},{ram_copies,[foo]}])), 447 ?match({aborted,not_a_db_node}, 448 mnesia:create_table([{name,no_host},{ram_copies,[foo@bar]}])), 449 ?match({aborted,badarg}, 450 mnesia:create_table([{name,zero_arity},{attributes,[]}])), 451 ?match({aborted,badarg}, mnesia:create_table([])), 452 ?match({aborted,badarg}, mnesia:create_table(atom)), 453 ?match({aborted,badarg}, 454 mnesia:create_table({cstruct,table_name_as_atom})), 455 ?match({aborted,bad_type}, 456 mnesia:create_table([{name,no_host},{ram_copies,foo}])), 457 ?match({aborted,bad_type}, 458 mnesia:create_table([{name,no_host},{disc_only_copies,foo}])), 459 ?match({aborted,bad_type}, 460 mnesia:create_table([{name,no_host},{disc_copies,foo}])), 461 462 CreateFun = 463 fun() -> ?match({aborted,nested_transaction}, 464 mnesia:create_table([{name,nested_trans}])), ok 465 end, 466 ?match({atomic,ok},mnesia:transaction(CreateFun)), 467 ?match({atomic,ok},mnesia:create_table([{name,remote_tab}, 468 {ram_copies,[Node2]}])), 469 470 ?match({atomic,ok}, mnesia:create_table([{name,a_brand_new_tab}, 471 {ram_copies,[Node1]}])), 472 ?match([],mnesia:dirty_read({a_brand_new_tab,4711})), 473 ?match({atomic,ok}, mnesia:delete_table(a_brand_new_tab)), 474 ?match({'EXIT',{aborted,no_exists}}, 475 mnesia:dirty_read({a_brand_new_tab,4711})), 476 ?match({aborted,no_exists}, mnesia:delete_table(a_brand_new_tab)), 477 ?match({aborted,badarg}, mnesia:create_table([])), 478 479 ?match({atomic,ok}, mnesia:create_table([{name,nested_del_trans}, 480 {ram_copies,[Node1]}])), 481 DeleteFun = fun() -> ?match({aborted,nested_transaction}, 482 mnesia:delete_table(nested_del_trans)), ok end, 483 ?match({atomic,ok}, mnesia:transaction(DeleteFun)), 484 485 ?match({aborted,bad_type}, 486 mnesia:create_table([{name,create_with_index},{index,2}])), 487 ?match({aborted,bad_index}, 488 mnesia:create_table([{name,create_with_index},{index,[-1]}])), 489 ?match({aborted,bad_index}, 490 mnesia:create_table([{name,create_with_index},{index,[0]}])), 491 ?match({aborted,bad_index}, 492 mnesia:create_table([{name,create_with_index},{index,[1]}])), 493 ?match({aborted,bad_index}, 494 mnesia:create_table([{name,create_with_index},{index,[2]}])), 495 ?match({atomic,ok}, 496 mnesia:create_table([{name,create_with_index},{index,[3]}, 497 {ram_copies,[Node1]}])), 498 done. 499 500%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 501%% Add, drop and move replicas, change storage types 502%% Change table layout (only arity change supported) 503 504replica_management(suite) -> []; 505replica_management(Nodes) -> 506 %% add_table_copy/3, del_table_copy/2, move_table_copy/3, 507 %% change_table_copy_type/3, transform_table/3 508 509 [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), 510 511 Tab = replica_management, 512 Attrs = [k,v], 513 514 %% 515 %% Add, delete and change replicas 516 %% 517 ?match({atomic,ok}, 518 mnesia:create_table([{name,Tab},{attributes,Attrs}, 519 {ram_copies,[Node1]}])), 520 mnesia_test_lib:verify_replica_location(Tab,[],[Node1],[],Nodes), 521 %% R - - 522 ?match({aborted,combine_error}, 523 mnesia:add_table_copy(Tab, Node2, disc_copies)), 524 ?match({aborted,combine_error}, 525 mnesia:change_table_copy_type(Tab, Node1, disc_copies)), 526 ?match({atomic,ok}, mnesia:del_table_copy(Tab,Node1)), 527 mnesia_test_lib:verify_replica_location(Tab,[],[],[],Nodes), 528 %% - - - 529 ?match({aborted,no_exists}, 530 mnesia:add_table_copy(Tab, Node3, ram_copies)), 531 532 ?match({atomic,ok}, mnesia:create_table([{name,Tab}, 533 {attributes,Attrs}, 534 {disc_copies,[Node1]}])), 535 mnesia_test_lib:verify_replica_location(Tab,[],[],[Node1],Nodes), 536 %% D - - 537 ?match({aborted,badarg}, 538 mnesia:add_table_copy(Tab, Node2, bad_storage_type)), 539 ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node2, disc_only_copies)), 540 mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node1],Nodes), 541 %% D DO - 542 ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node3, ram_copies)), 543 mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes), 544 %% D DO R 545 ?match({atomic,ok}, 546 mnesia:change_table_copy_type(Tab, Node1, disc_only_copies)), 547 mnesia_test_lib:verify_replica_location(Tab,[Node1,Node2],[Node3],[],Nodes), 548 %% DO DO R 549 ?match({aborted,already_exists}, 550 mnesia:add_table_copy(Tab, Node3, ram_copies)), 551 ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node1)), 552 mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[],Nodes), 553 %% - DO R 554 ?match({aborted,_}, mnesia:del_table_copy(Tab, Node1)), 555 ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node1, disc_copies)), 556 mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes), 557 %% D DO R 558 ?match({atomic,ok}, 559 mnesia:change_table_copy_type(Tab, Node3, disc_only_copies)), 560 mnesia_test_lib:verify_replica_location(Tab,[Node2,Node3],[],[Node1],Nodes), 561 %% D DO DO 562 ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)), 563 mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node1],Nodes), 564 %% D - DO 565 ?match({aborted,already_exists}, 566 mnesia:change_table_copy_type(Tab, Node1, disc_copies)), 567 568 %% 569 %% Move replica 570 %% 571 ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node1,Node2)), 572 mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2],Nodes), 573 %% - D DO 574 ?match({aborted,_}, mnesia:move_table_copy(Tab,Node1,Node2)), 575 ?match([], mnesia_test_lib:stop_mnesia([Node3])), 576 mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2], 577 Nodes -- [Node3]), 578 %% - D DO 579 ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node3,Node1)), 580 mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2], 581 Nodes -- [Node3]), 582 %% DO D - 583 ?match([],mnesia_test_lib:start_mnesia([Node3])), 584 mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2],Nodes), 585 %% DO D - 586 587 %% 588 %% Transformer 589 %% 590 591 NewAttrs = Attrs ++ [extra], 592 Transformer = 593 fun(Rec) -> list_to_tuple(tuple_to_list(Rec) ++ [initial_value]) end, 594 ?match({atomic,ok}, mnesia:transform_table(Tab, Transformer,NewAttrs)), 595 ?match({atomic,ok}, mnesia:transform_table(Tab, fun(R) -> R end, Attrs)), 596 ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, 0)), 597 ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, -1)), 598 ?match({aborted,badarg}, mnesia:transform_table(Tab, Transformer, [])), 599 ?match({aborted,bad_type}, mnesia:transform_table(Tab, no_fun, NewAttrs)), 600 601 NestedFun = 602 fun() -> 603 ?match({aborted,_}, 604 mnesia:move_table_copy(Tab,Node1,Node2)), 605 ?match({aborted,_}, 606 mnesia:add_table_copy(Tab,Node1,ram_copies)), 607 ?match({aborted,_}, 608 mnesia:del_table_copy(Tab,Node1)), 609 T = fun(_) -> 4711 end, 610 ?match({aborted,_}, 611 mnesia:transform_table(Tab,Transformer, T)), 612 ok 613 end, 614 ?match({atomic,ok},mnesia:transaction(NestedFun)), 615 done. 616 617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 618%% Add and drop indecies 619 620index_lifecycle(suite) -> 621 [ add_table_index, create_live_table_index, del_table_index ]. 622 623%% Add table index 624 625add_table_index(suite) -> []; 626add_table_index(Nodes) -> 627 [Node1] = ?acquire_nodes(1,Nodes), 628 Tab = add_table_index, 629 Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], 630 ?match({atomic,ok}, mnesia:create_table(Schema)), 631 ValPos = 3, 632 BadValPos = ValPos + 1, 633 ?match({aborted,bad_index}, mnesia:add_table_index(Tab,BadValPos)), 634 ?match({aborted,bad_index}, mnesia:add_table_index(Tab,2)), 635 ?match({aborted,bad_index}, mnesia:add_table_index(Tab,1)), 636 ?match({aborted,bad_index}, mnesia:add_table_index(Tab,0)), 637 ?match({aborted,bad_index}, mnesia:add_table_index(Tab,-1)), 638 ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), 639 ?match({aborted,already_exists}, mnesia:add_table_index(Tab,ValPos)), 640 641 NestedFun = fun() -> 642 ?match({aborted,nested_transaction}, 643 mnesia:add_table_index(Tab,ValPos)), 644 645 ok 646 end, 647 ?match({atomic,ok},mnesia:transaction(NestedFun)), 648 done. 649 650create_live_table_index(suite) -> []; 651create_live_table_index(Nodes) -> 652 [Node1] = ?acquire_nodes(1,Nodes), 653 Tab = create_live_table_index, 654 Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], 655 ?match({atomic,ok}, mnesia:create_table(Schema)), 656 ValPos = 3, 657 mnesia:dirty_write({Tab,1,2}), 658 659 Fun = fun() -> 660 ?match(ok, mnesia:write({Tab,2,2})), 661 ok 662 end, 663 ?match({atomic,ok},mnesia:transaction(Fun)), 664 ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), 665 done. 666 667%% Drop table index 668 669del_table_index(suite) ->[]; 670del_table_index(Nodes) -> 671 [Node1] = ?acquire_nodes(1,Nodes), 672 Tab = del_table_index, 673 Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], 674 ?match({atomic,ok}, mnesia:create_table(Schema)), 675 ValPos = 3, 676 BadValPos = ValPos + 1, 677 ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), 678 ?match({aborted,no_exists}, 679 mnesia:del_table_index(Tab,BadValPos)), 680 ?match({atomic,ok}, mnesia:del_table_index(Tab,ValPos)), 681 682 NestedFun = 683 fun() -> 684 ?match({aborted,nested_transaction}, 685 mnesia:del_table_index(Tab,ValPos)), 686 ok 687 end, 688 ?match({atomic,ok},mnesia:transaction(NestedFun)), 689 done. 690 691%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 692%% Syncronize table with log or disc 693%% 694table_sync(suite) -> 695 [ dump_tables, dump_log, change_dump_log_config, wait_for_tables, force_load_table ]. 696 697%% Dump ram tables on disc 698dump_tables(suite) -> []; 699dump_tables(Nodes) -> 700 [Node1,Node2] = ?acquire_nodes(2,Nodes), 701 Tab = dump_tables, 702 Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node2]}], 703 ?match({atomic,ok}, mnesia:create_table(Schema)), 704 705 %% Dump 10 records 706 Size = 10, 707 Keys = lists:seq(1,Size), 708 Records = [{Tab,A,7} || A <- Keys], 709 lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records), 710 AllKeys = fun() -> lists:sort(mnesia:all_keys(Tab)) end, 711 712 ?match({atomic,Keys}, mnesia:transaction(AllKeys)), 713 ?match(ok, mnesia:dump_tables(Tab)), 714 715 %% Delete one record 716 ?match(ok,mnesia:dirty_delete({Tab,5})), 717 Keys2 = lists:delete(5,Keys), 718 ?match({atomic,Keys2}, mnesia:transaction(AllKeys)), 719 720 %% Check that all 10 is restored after a stop 721 ?match([], mnesia_test_lib:stop_mnesia([Node1,Node2])), 722 ?match([],mnesia_test_lib:start_mnesia([Node1,Node2])), 723 ?match(ok,mnesia:wait_for_tables([Tab],infinity)), 724 ?match({atomic,Keys}, mnesia:transaction(AllKeys)), 725 726 ?match(ok, mnesia:dump_tables([foo])), 727 done. 728 729%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 730%% Make Mnesia table accessible via SNMP 731 732snmp_access(suite) -> 733 [ 734 snmp_open_table, snmp_close_table, 735 snmp_get_row, snmp_get_next_index, snmp_get_mnesia_key 736 ]. 737 738%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 739%% Check that the debug support has not decayed 740 741debug_support(suite) -> 742 [ info, schema, schema, kill, lkill ]. 743 744