diff options
author | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
---|---|---|
committer | Erlang/OTP <[email protected]> | 2009-11-20 14:54:40 +0000 |
commit | 84adefa331c4159d432d22840663c38f155cd4c1 (patch) | |
tree | bff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/compiler/test/compile_SUITE_data/big.erl | |
download | otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2 otp-84adefa331c4159d432d22840663c38f155cd4c1.zip |
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/compiler/test/compile_SUITE_data/big.erl')
-rw-r--r-- | lib/compiler/test/compile_SUITE_data/big.erl | 742 |
1 files changed, 742 insertions, 0 deletions
diff --git a/lib/compiler/test/compile_SUITE_data/big.erl b/lib/compiler/test/compile_SUITE_data/big.erl new file mode 100644 index 0000000000..4cd8e15f13 --- /dev/null +++ b/lib/compiler/test/compile_SUITE_data/big.erl @@ -0,0 +1,742 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1997-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% +-module(big). +-compile([export_all]). + +compiler_1() -> ok. + +-define(log(Format,Args),mnesia_test_lib:log(Format,Args,?FILE,?LINE)). +-define(warning(Format,Args),?log("<WARNING> " ++ Format,Args)). +-define(error(Format,Args), + mnesia_test_lib:note_error(Format,Args,?FILE,?LINE), + ?log("<ERROR> " ++ Format,Args)). + +-define(match(ExpectedRes,Expr), + fun() -> + AcTuAlReS = (catch (Expr)), + case AcTuAlReS of + ExpectedRes -> + ?log("ok, result as expected: ~p~n",[AcTuAlReS]), + {success,AcTuAlReS}; + _ -> + ?error("actual result was: ~p~n",[AcTuAlReS]), + {fail,AcTuAlReS} + end + end()). + +-define(match_inverse(NotExpectedRes,Expr), + fun() -> + AcTuAlReS = (catch (Expr)), + case AcTuAlReS of + NotExpectedRes -> + ?error("actual result was: ~p~n",[AcTuAlReS]), + {fail,AcTuAlReS}; + _ -> + ?log("ok, result as expected: ~p~n",[AcTuAlReS]), + {success,AcTuAlReS} + end + end()). + +-define(match_receive(ExpectedMsg), + ?match(ExpectedMsg,mnesia_test_lib:pick_msg())). + +%% ExpectedMsgs must be completely bound +-define(match_multi_receive(ExpectedMsgs), + fun() -> + TmPeXpCtEdMsGs = lists:sort(ExpectedMsgs), + ?match(TmPeXpCtEdMsGs, + lists:sort(lists:map(fun(_) -> + mnesia_test_lib:pick_msg() + end, + TmPeXpCtEdMsGs))) + end()). + +-define(setup(), mnesia_test_lib:setup(?FILE,?LINE)). + +-define(start_activities(Nodes), + fun() -> + AcTiViTyPiDs = + lists:map(fun(Node) -> + spawn_link(Node, + mnesia_test_lib, + activity_evaluator, + [self()]) + end, + Nodes), + ?match_multi_receive(AcTiViTyPiDs) + end()). + +-define(start_transactions(Pids), + ?match_multi_receive(lists:map(fun(Pid) -> + Pid ! begin_trans, + {Pid,begin_trans} + end, + Pids))). + +-define(acquire_nodes(N,Nodes), + mnesia_test_lib:acquire_nodes(N,Nodes,?FILE,?LINE)). + + + +%%% Copyright (C) 1996, Ellemtel Telecommunications Systems Laboratories +%%% Author: Hakan Mattsson [email protected] +%%% Purpose: Evil usage of the API +%%% +%%% Invoke all functions in the API and try to cover all legal uses +%%% cases as well the illegal dito. This is a complement to the +%%% other more explicit test cases. +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%% +%%% show/0 +%%% +%%% Prints out the complete test case structure +%%% +%%% show/1 +%%% +%%% Prints out parts of the test case structure +%%% +%%% test/0 +%%% +%%% Run the complete test suite. +%%% Reads Nodes from nodes.profile and starts them if neccessary. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/1 +%%% +%%% Run parts of the test suite. +%%% Reads Nodes from nodes.profile and starts them if neccessary. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/2 +%%% +%%% Run parts of the test suite on the given Nodes, +%%% assuming that the nodes are up and running. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% test/3 +%%% +%%% Run parts of the test suite on permutations of the given Nodes, +%%% assuming that the nodes are up and running. Uses test/2. +%%% Kills Mnesia and wipes out the Mnesia directories as a starter. +%%% +%%% See the module mnesia_test_lib for further information. +%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +show() -> mnesia_test_lib:show([{?MODULE,all}]). +show(TestCases) -> mnesia_test_lib:show([{?MODULE,TestCases}]). +test() -> mnesia_test_lib:test([{?MODULE,all}]). +test(TestCases) -> mnesia_test_lib:test([{?MODULE,TestCases}]). +test(TestCases,Nodes) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes). +test(TestCases,Nodes,Config) -> mnesia_test_lib:test([{?MODULE,TestCases}],Nodes,Config). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +old_all(suite) -> + [ + system_info, table_info, error_description, + db_node_lifecycle, start_and_stop, transaction, checkpoint, backup, + table_lifecycle, replica_management, replica_location, index_lifecycle, + trans_access, dirty_access, table_sync, snmp_access, debug_support + ]. + +trans_access(suite) -> + [ {mnesia_dirty_access_test,all} ]. + +dirty_access(suite) -> + [ {mnesia_trans_access_test,all} ]. + +%% Get meta info about Mnesia +system_info(suite) -> []; +system_info(Nodes) -> + ?match(yes,mnesia:system_info(is_running)), + ?match(Nodes,mnesia:system_info(db_nodes)), + ?match(Nodes,mnesia:system_info(running_db_nodes)), + ?match(true,mnesia:system_info(have_disc)), + ?match(A when atom(A),mnesia:system_info(debug)), + ?match(L when list(L),mnesia:system_info(directory)), + ?match(L when list(L),mnesia:system_info(log_version)), + ?match({_,_},mnesia:system_info(schema_version)), + ?match(L when list(L),mnesia:system_info(tables)), + ?match(L when list(L),mnesia:system_info(local_tables)), + ?match(L when list(L),mnesia:system_info(held_locks)), + ?match(L when list(L),mnesia:system_info(lock_queue)), + ?match(L when list(L),mnesia:system_info(transactions)), + ?match(I when integer(I),mnesia:system_info(transaction_failures)), + ?match(I when integer(I),mnesia:system_info(transaction_commits)), + ?match(I when integer(I),mnesia:system_info(transaction_restarts)), + ?match(L when list(L),mnesia:system_info(checkpoints)), + ?match(A when atom(A),mnesia:system_info(backup_module)), + ?match(true,mnesia:system_info(auto_repair)), + ?match({_,_},mnesia:system_info(dump_log_interval)), + ?match(A when atom(A),mnesia:system_info(dump_log_update_in_place)), + ?match(I when integer(I),mnesia:system_info(transaction_log_writes)), + ?match({'EXIT',{aborted,badarg}},mnesia:system_info(ali_baba)), + done. + +%% Get meta info about table +table_info(suite) -> []; +table_info(Nodes) -> + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + + Tab = table_info, + Type = bag, + ValPos = 3, + Attrs = [k,v], + Arity = length(Attrs) +1, + Schema = [{name,Tab},{type,Type},{attributes,Attrs},{index,[ValPos]}, + {disc_only_copies,[Node1]},{ram_copies,[Node2]},{disc_copies,[Node3]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + + Size = 10, + Keys = lists:seq(1,Size), + Records = [{Tab,A,7} || A <- Keys], + lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records), + ?match(Mem when integer(Mem),mnesia:table_info(Tab,memory)), + ?match(Size,mnesia:table_info(Tab,size)), + ?match(Type,mnesia:table_info(Tab,type)), + ?match([Node3],mnesia:table_info(Tab,disc_copies)), + ?match([Node2],mnesia:table_info(Tab,ram_copies)), + ?match([Node1],mnesia:table_info(Tab,disc_only_copies)), + Read = [Node1,Node2,Node3], + ?match(true,lists:member(mnesia:table_info(Tab,where_to_read),Read)), + Write = lists:sort([Node1,Node2,Node3]), + ?match(Write,lists:sort(mnesia:table_info(Tab,where_to_write))), + WriteLock = lists:sort([Node2,Node3]), + ?match([ValPos],mnesia:table_info(Tab,index)), + ?match(Arity,mnesia:table_info(Tab,arity)), + ?match(Attrs,mnesia:table_info(Tab,attributes)), + ?match({Tab,'_','_'},mnesia:table_info(Tab,wild_pattern)), + ?match({atomic,Attrs}, mnesia:transaction(fun() -> + mnesia:table_info(Tab,attributes) end)), + + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add and drop db nodes + +db_node_lifecycle(suite) -> []; +db_node_lifecycle(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + Tab = db_node_lifecycle, + + Schema = [{name,Tab},{ram_copies,[Node1,Node2]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ?match({aborted,active}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + + ?match([], mnesia_test_lib:stop_mnesia(Nodes)), + ?match(ok, mnesia:delete_schema(Nodes)), + ?match({error,_}, mnesia:create_schema(foo)), + ?match({error,_}, mnesia:create_schema([foo])), + ?match({error,_}, mnesia:create_schema([foo@bar])), + ?match({error,_}, mnesia:start()), + + ?match(ok, mnesia:create_schema(Nodes)), + ?match([],mnesia_test_lib:start_mnesia(Nodes)), + ?match({atomic,ok}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[Node2])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo])), + ?match({aborted,no_exists}, rpc:call(Node1,mnesia,del_db_node,[foo@bar])), + + ?match([], mnesia_test_lib:stop_mnesia([Node2])), + ?match(ok,mnesia:delete_schema([Node2])), + AddFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:add_db_node(Node2)), ok end, + ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[AddFun])), + DelFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:del_db_node(Node2)), ok end, + ?match({atomic,ok},rpc:call(Node1,mnesia,transaction,[DelFun])), + + ?match({atomic,ok}, rpc:call(Node1,mnesia,add_db_node,[Node2])), + ?match({aborted,already_exists}, rpc:call(Node1,mnesia,add_db_node,[Node2])), + ?match([],mnesia_test_lib:start_mnesia([Node2])), + ?match({atomic,ok}, mnesia:create_table(Schema)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Start and stop the system + +start_and_stop(suite) -> []; +start_and_stop(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match({started,_}, rpc:call(Node1,mnesia,start,[])), + ?match({started,_}, rpc:call(Node1,mnesia,start,[])), + ?match(stopped, rpc:call(Node1,mnesia,stop,[])), + ?match([],mnesia_test_lib:start_mnesia(Nodes)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Checkpoints and backup management + +checkpoint(suite) -> []; +checkpoint(Nodes) -> + OneNode = ?acquire_nodes(1,Nodes), + checkpoint(OneNode,Nodes), + TwoNodes = ?acquire_nodes(2,Nodes), + checkpoint(TwoNodes,Nodes). + +checkpoint(TabNodes,Nodes) -> + [Node1] = ?acquire_nodes(1,TabNodes), + CreateTab = fun(Type,N,Ns) -> + Tab0 = lists:concat(["local_checkpoint_",Type,N]), + Tab = list_to_atom(Tab0), + Schema = [{name,Tab},{Type,Ns}], + ?match({atomic,ok},mnesia:delete_table(Tab)), + ?match({atomic,ok},mnesia:create_table(Schema)), + Tab + end, + CreateTabs = fun(Type) -> + CreateTab(Type,1,hd(TabNodes)), + CreateTab(Type,2,TabNodes), + CreateTab(Type,3,lists:last(TabNodes)) + end, + Types = [ram_copies,disc_copies,disc_only_copies], + Tabs = lists:append(lists:map(CreateTabs,Types)), + Recs = lists:sort([{T,N,N} || T <- Tabs,N <- lists:seq(1,10)]), + lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs), + + CpName = a_checkpoint_name, + MinArgs = [{name,CpName},{min,Tabs},{allow_remote,false}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[MinArgs])), + ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + MaxArgs = [{name,CpName},{max,Tabs},{allow_remote,true}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[MaxArgs])), + ?match(ok,rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + Args = [{name,CpName},{min,Tabs},{allow_remote,false}], + ?match({ok,CpName,[Node1]}, + rpc:call(Node1,mnesia,activate_checkpoint,[Args])), + Recs2 = lists:sort([{T,K,0} || {T,K,_} <- Recs]), + lists:foreach(fun(R) -> ?match(ok,mnesia:dirty_write(R)) end,Recs2), + ?match({atomic,ok},rpc:call(Node1,mnesia,deactivate_checkpoint,[CpName])), + + ?match({error,no_exists},mnesia:deactivate_checkpoint(CpName)), + ?match({error,badarg},mnesia:activate_checkpoint(foo)), + ?match({error,badarg},mnesia:activate_checkpoint([{foo,foo}])), + ?match({error,badarg},mnesia:activate_checkpoint([{max,foo}])), + ?match({error,badarg},mnesia:activate_checkpoint([{min,foo}])), + ?match({error,no_exists},mnesia:activate_checkpoint([{min,[foo@bar]}])), + ?match({error,badarg},mnesia:activate_checkpoint([{allow_remote,foo}])), + + Fun = fun(Tab) -> ?match({atomic,ok},mnesia:delete_table(Tab)) end, + lists:foreach(Fun,Tabs), + done. + +backup(suite) -> + [ + backup_schema, restore_schema, backup_checkpoint, restore_tables + ]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Use and misuse transactions + +transaction(suite) -> []; +transaction(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + ?match({atomic,ali_baba}, mnesia:transaction(fun() -> ali_baba end)), + ?match({aborted,_}, mnesia:transaction(no_fun)), + ?match({aborted,_}, mnesia:transaction(?MODULE,no_fun,[foo])), + + {success,[A,B,C,D,E,F,G,H]} = ?start_activities(lists:duplicate(8,Node1)), + ?start_transactions([A,B,C,D,E,F,G,H]), + + A ! fun() -> mnesia:abort(abort_bad_trans) end, + ?match_receive({A,{aborted,abort_bad_trans}}), + + B ! fun() -> 1 = 2 end, + ?match_receive({B,{aborted,_}}), + + C ! fun() -> throw(throw_bad_trans) end, + ?match_receive({C,{aborted,{throw,throw_bad_trans}}}), + + D ! fun() -> exit(exit_bad_trans) end, + ?match_receive({D,{aborted,exit_bad_trans}}), + + E ! fun() -> exit(normal) end, + ?match_receive({E,{aborted,normal}}), + + F ! fun() -> exit(abnormal) end, + ?match_receive({F,{aborted,abnormal}}), + + G ! fun() -> exit(G,abnormal) end, + ?match_receive({'EXIT',G,abnormal}), + + H ! fun() -> exit(H,kill) end, + ?match_receive({'EXIT',H,killed}), + + ?match({atomic,ali_baba}, + mnesia:transaction(fun() -> ali_baba end,infinity)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,1)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,0)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,-1)), + ?match({atomic,ali_baba},mnesia:transaction(fun() -> ali_baba end,foo)), + Fun = fun() -> ?match({aborted,nested_transaction}, + mnesia:transaction(fun() -> ok end)), ok end, + ?match({atomic,ok},mnesia:transaction(Fun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Create and delete tables + +%% Get meta info about table + +replica_location(suite) -> []; +replica_location(Nodes) -> + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + Tab = replica_location, + + %% Create three replicas + Schema = [{name,Tab},{disc_only_copies,[Node1]}, + {ram_copies,[Node2]},{disc_copies,[Node3]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[Node2],[Node3],Nodes), + + %% Delete one replica + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node3],Nodes), + + %% Move one replica + ?match({atomic,ok}, mnesia:move_table_copy(Tab, Node1, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node3],Nodes), + + %% Change replica type + ?match({atomic,ok}, mnesia:change_table_copy_type(Tab, Node2,ram_copies)), + mnesia_test_lib:verify_replica_location(Tab,[],[Node2],[Node3],Nodes), + + done. + +table_lifecycle(suite) -> []; +table_lifecycle(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + + ?match({atomic,ok}, mnesia:create_table([{type,bag}, + {ram_copies,[Node1]}, + {attributes,[rajtan,tajtan]}, + {name,order_of_args}])), + ?match([],mnesia:dirty_read({order_of_args,4711})), + ?match({atomic,ok}, mnesia:create_table([{name,already_exists}, + {ram_copies,[Node1]}])), + ?match({aborted,already_exists}, + mnesia:create_table([{name,already_exists},{ram_copies,[Node1]}])), + ?match({aborted,not_a_db_node}, + mnesia:create_table([{name,no_node},{ram_copies,[foo]}])), + ?match({aborted,not_a_db_node}, + mnesia:create_table([{name,no_host},{ram_copies,[foo@bar]}])), + ?match({aborted,badarg}, + mnesia:create_table([{name,zero_arity},{attributes,[]}])), + ?match({aborted,badarg}, mnesia:create_table([])), + ?match({aborted,badarg}, mnesia:create_table(atom)), + ?match({aborted,badarg}, + mnesia:create_table({cstruct,table_name_as_atom})), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{ram_copies,foo}])), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{disc_only_copies,foo}])), + ?match({aborted,bad_type}, + mnesia:create_table([{name,no_host},{disc_copies,foo}])), + + CreateFun = + fun() -> ?match({aborted,nested_transaction}, + mnesia:create_table([{name,nested_trans}])), ok + end, + ?match({atomic,ok},mnesia:transaction(CreateFun)), + ?match({atomic,ok},mnesia:create_table([{name,remote_tab}, + {ram_copies,[Node2]}])), + + ?match({atomic,ok}, mnesia:create_table([{name,a_brand_new_tab}, + {ram_copies,[Node1]}])), + ?match([],mnesia:dirty_read({a_brand_new_tab,4711})), + ?match({atomic,ok}, mnesia:delete_table(a_brand_new_tab)), + ?match({'EXIT',{aborted,no_exists}}, + mnesia:dirty_read({a_brand_new_tab,4711})), + ?match({aborted,no_exists}, mnesia:delete_table(a_brand_new_tab)), + ?match({aborted,badarg}, mnesia:create_table([])), + + ?match({atomic,ok}, mnesia:create_table([{name,nested_del_trans}, + {ram_copies,[Node1]}])), + DeleteFun = fun() -> ?match({aborted,nested_transaction}, + mnesia:delete_table(nested_del_trans)), ok end, + ?match({atomic,ok}, mnesia:transaction(DeleteFun)), + + ?match({aborted,bad_type}, + mnesia:create_table([{name,create_with_index},{index,2}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[-1]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[0]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[1]}])), + ?match({aborted,bad_index}, + mnesia:create_table([{name,create_with_index},{index,[2]}])), + ?match({atomic,ok}, + mnesia:create_table([{name,create_with_index},{index,[3]}, + {ram_copies,[Node1]}])), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add, drop and move replicas, change storage types +%% Change table layout (only arity change supported) + +replica_management(suite) -> []; +replica_management(Nodes) -> + %% add_table_copy/3, del_table_copy/2, move_table_copy/3, + %% change_table_copy_type/3, transform_table/3 + + [Node1,Node2,Node3] = ?acquire_nodes(3,Nodes), + + Tab = replica_management, + Attrs = [k,v], + + %% + %% Add, delete and change replicas + %% + ?match({atomic,ok}, + mnesia:create_table([{name,Tab},{attributes,Attrs}, + {ram_copies,[Node1]}])), + mnesia_test_lib:verify_replica_location(Tab,[],[Node1],[],Nodes), + %% R - - + ?match({aborted,combine_error}, + mnesia:add_table_copy(Tab, Node2, disc_copies)), + ?match({aborted,combine_error}, + mnesia:change_table_copy_type(Tab, Node1, disc_copies)), + ?match({atomic,ok}, mnesia:del_table_copy(Tab,Node1)), + mnesia_test_lib:verify_replica_location(Tab,[],[],[],Nodes), + %% - - - + ?match({aborted,no_exists}, + mnesia:add_table_copy(Tab, Node3, ram_copies)), + + ?match({atomic,ok}, mnesia:create_table([{name,Tab}, + {attributes,Attrs}, + {disc_copies,[Node1]}])), + mnesia_test_lib:verify_replica_location(Tab,[],[],[Node1],Nodes), + %% D - - + ?match({aborted,badarg}, + mnesia:add_table_copy(Tab, Node2, bad_storage_type)), + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node2, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[],[Node1],Nodes), + %% D DO - + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node3, ram_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes), + %% D DO R + ?match({atomic,ok}, + mnesia:change_table_copy_type(Tab, Node1, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node1,Node2],[Node3],[],Nodes), + %% DO DO R + ?match({aborted,already_exists}, + mnesia:add_table_copy(Tab, Node3, ram_copies)), + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node1)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[],Nodes), + %% - DO R + ?match({aborted,_}, mnesia:del_table_copy(Tab, Node1)), + ?match({atomic,ok}, mnesia:add_table_copy(Tab, Node1, disc_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2],[Node3],[Node1],Nodes), + %% D DO R + ?match({atomic,ok}, + mnesia:change_table_copy_type(Tab, Node3, disc_only_copies)), + mnesia_test_lib:verify_replica_location(Tab,[Node2,Node3],[],[Node1],Nodes), + %% D DO DO + ?match({atomic,ok}, mnesia:del_table_copy(Tab, Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node1],Nodes), + %% D - DO + ?match({aborted,already_exists}, + mnesia:change_table_copy_type(Tab, Node1, disc_copies)), + + %% + %% Move replica + %% + ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node1,Node2)), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2],Nodes), + %% - D DO + ?match({aborted,_}, mnesia:move_table_copy(Tab,Node1,Node2)), + ?match([], mnesia_test_lib:stop_mnesia([Node3])), + mnesia_test_lib:verify_replica_location(Tab,[Node3],[],[Node2], + Nodes -- [Node3]), + %% - D DO + ?match({atomic,ok}, mnesia:move_table_copy(Tab,Node3,Node1)), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2], + Nodes -- [Node3]), + %% DO D - + ?match([],mnesia_test_lib:start_mnesia([Node3])), + mnesia_test_lib:verify_replica_location(Tab,[Node1],[],[Node2],Nodes), + %% DO D - + + %% + %% Transformer + %% + + NewAttrs = Attrs ++ [extra], + Transformer = + fun(Rec) -> list_to_tuple(tuple_to_list(Rec) ++ [initial_value]) end, + ?match({atomic,ok}, mnesia:transform_table(Tab, Transformer,NewAttrs)), + ?match({atomic,ok}, mnesia:transform_table(Tab, fun(R) -> R end, Attrs)), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, 0)), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, Transformer, -1)), + ?match({aborted,badarg}, mnesia:transform_table(Tab, Transformer, [])), + ?match({aborted,bad_type}, mnesia:transform_table(Tab, no_fun, NewAttrs)), + + NestedFun = + fun() -> + ?match({aborted,_}, + mnesia:move_table_copy(Tab,Node1,Node2)), + ?match({aborted,_}, + mnesia:add_table_copy(Tab,Node1,ram_copies)), + ?match({aborted,_}, + mnesia:del_table_copy(Tab,Node1)), + T = fun(_) -> 4711 end, + ?match({aborted,_}, + mnesia:transform_table(Tab,Transformer, T)), + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Add and drop indecies + +index_lifecycle(suite) -> + [ add_table_index, create_live_table_index, del_table_index ]. + +%% Add table index + +add_table_index(suite) -> []; +add_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = add_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + BadValPos = ValPos + 1, + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,BadValPos)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,2)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,1)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,0)), + ?match({aborted,bad_index}, mnesia:add_table_index(Tab,-1)), + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + ?match({aborted,already_exists}, mnesia:add_table_index(Tab,ValPos)), + + NestedFun = fun() -> + ?match({aborted,nested_transaction}, + mnesia:add_table_index(Tab,ValPos)), + + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +create_live_table_index(suite) -> []; +create_live_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = create_live_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + mnesia:dirty_write({Tab,1,2}), + + Fun = fun() -> + ?match(ok, mnesia:write({Tab,2,2})), + ok + end, + ?match({atomic,ok},mnesia:transaction(Fun)), + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + done. + +%% Drop table index + +del_table_index(suite) ->[]; +del_table_index(Nodes) -> + [Node1] = ?acquire_nodes(1,Nodes), + Tab = del_table_index, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node1]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + ValPos = 3, + BadValPos = ValPos + 1, + ?match({atomic,ok}, mnesia:add_table_index(Tab,ValPos)), + ?match({aborted,no_exists}, + mnesia:del_table_index(Tab,BadValPos)), + ?match({atomic,ok}, mnesia:del_table_index(Tab,ValPos)), + + NestedFun = + fun() -> + ?match({aborted,nested_transaction}, + mnesia:del_table_index(Tab,ValPos)), + ok + end, + ?match({atomic,ok},mnesia:transaction(NestedFun)), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Syncronize table with log or disc +%% +table_sync(suite) -> + [ dump_tables, dump_log, change_dump_log_config, wait_for_tables, force_load_table ]. + +%% Dump ram tables on disc +dump_tables(suite) -> []; +dump_tables(Nodes) -> + [Node1,Node2] = ?acquire_nodes(2,Nodes), + Tab = dump_tables, + Schema = [{name,Tab},{attributes,[k,v]},{ram_copies,[Node2]}], + ?match({atomic,ok}, mnesia:create_table(Schema)), + + %% Dump 10 records + Size = 10, + Keys = lists:seq(1,Size), + Records = [{Tab,A,7} || A <- Keys], + lists:foreach(fun(Rec) -> ?match(ok,mnesia:dirty_write(Rec)) end,Records), + AllKeys = fun() -> lists:sort(mnesia:all_keys(Tab)) end, + + ?match({atomic,Keys}, mnesia:transaction(AllKeys)), + ?match(ok, mnesia:dump_tables(Tab)), + + %% Delete one record + ?match(ok,mnesia:dirty_delete({Tab,5})), + Keys2 = lists:delete(5,Keys), + ?match({atomic,Keys2}, mnesia:transaction(AllKeys)), + + %% Check that all 10 is restored after a stop + ?match([], mnesia_test_lib:stop_mnesia([Node1,Node2])), + ?match([],mnesia_test_lib:start_mnesia([Node1,Node2])), + ?match(ok,mnesia:wait_for_tables([Tab],infinity)), + ?match({atomic,Keys}, mnesia:transaction(AllKeys)), + + ?match(ok, mnesia:dump_tables([foo])), + done. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Make Mnesia table accessible via SNMP + +snmp_access(suite) -> + [ + snmp_open_table, snmp_close_table, + snmp_get_row, snmp_get_next_index, snmp_get_mnesia_key + ]. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Check that the debug support has not decayed + +debug_support(suite) -> + [ info, schema, schema, kill, lkill ]. + |