diff options
Diffstat (limited to 'lib/cosTransactions/test/transactions_SUITE.erl')
-rw-r--r-- | lib/cosTransactions/test/transactions_SUITE.erl | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/lib/cosTransactions/test/transactions_SUITE.erl b/lib/cosTransactions/test/transactions_SUITE.erl new file mode 100644 index 0000000000..8385d5a0fb --- /dev/null +++ b/lib/cosTransactions/test/transactions_SUITE.erl @@ -0,0 +1,395 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1999-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(transactions_SUITE). + +%%--------------- INCLUDES ----------------------------------- +-include_lib("orber/include/corba.hrl"). +-include_lib("orber/include/ifr_types.hrl"). + +%% Local +-include_lib("cosTransactions/src/ETraP_Common.hrl"). +-include_lib("cosTransactions/include/CosTransactions.hrl"). +-include("etrap_test_lib.hrl"). + +-include("test_server.hrl"). + +-define(default_timeout, ?t:minutes(20)). + + +%%----------------------------------------------------------------- +%% External exports +%%----------------------------------------------------------------- +-export([all/1, cases/0, init_all/1, finish_all/1, resource_api/1, etrap_api/1, + init_per_testcase/2, fin_per_testcase/2, app_test/1]). + +%%----------------------------------------------------------------- +%% Func: all/1 +%% Args: +%% Returns: +%%----------------------------------------------------------------- +all(doc) -> ["API tests for the cosTransactions interfaces", ""]; +all(suite) -> {req, + [mnesia, orber], + {conf, init_all, cases(), finish_all}}. + +cases() -> + [etrap_api, resource_api, app_test]. + + + +%%----------------------------------------------------------------- +%% Init and cleanup functions. +%%----------------------------------------------------------------- + +init_per_testcase(_Case, Config) -> + Path = code:which(?MODULE), + code:add_pathz(filename:join(filename:dirname(Path), "idl_output")), + 'oe_CosTransactions':'oe_register'(), + 'oe_etrap_test':'oe_register'(), + ?line Dog=test_server:timetrap(?default_timeout), + [{watchdog, Dog}|Config]. + + +fin_per_testcase(_Case, Config) -> + 'oe_etrap_test':'oe_unregister'(), + 'oe_CosTransactions':'oe_unregister'(), + Path = code:which(?MODULE), + code:del_path(filename:join(filename:dirname(Path), "idl_output")), + Dog = ?config(watchdog, Config), + test_server:timetrap_cancel(Dog), + ok. + +init_all(Config) -> + mnesia:delete_schema([node()]), + mnesia:create_schema([node()]), + orber:install([node()]), + application:start(mnesia), + application:start(orber), + if + is_list(Config) -> + Config; + true -> + exit("Config not a list") + end. + +finish_all(Config) -> + application:stop(orber), + application:stop(mnesia), + mnesia:delete_schema([node()]), + Config. + +%%----------------------------------------------------------------- +%% Tests app file +%%----------------------------------------------------------------- +app_test(doc) -> []; +app_test(suite) -> []; +app_test(_Config) -> + ok=test_server:app_test(cosTransactions), + ok. + +%%----------------------------------------------------------------- +%% API tests +%%----------------------------------------------------------------- +etrap_api(doc) -> ["ETraP_Server tests", ""]; +etrap_api(suite) -> []; +etrap_api(_Config) -> + ?line ?match(ok, application:start(cosTransactions), + "Starting the cosTransactions application"), + ?line TrFac = cosTransactions:start_factory(), + %% Start a new transaction: + %% RootCoord + %% / \ + %% SubCoord1 SubCoord2 + Control = 'CosTransactions_TransactionFactory':create(TrFac, 0), + Term = 'CosTransactions_Control':get_terminator(Control), + Coord = 'CosTransactions_Control':get_coordinator(Control), + SubCont1 = 'CosTransactions_Coordinator':create_subtransaction(Coord), + SubCont2 = 'CosTransactions_Coordinator':create_subtransaction(Coord), + SubCoord1 = 'CosTransactions_Control':get_coordinator(SubCont1), + SubCoord2 = 'CosTransactions_Control':get_coordinator(SubCont2), + + + %%------ Test CosTransactions::Coordinator ------ + ?line ?match(true, + 'CosTransactions_Coordinator':is_same_transaction(Coord, Coord), + "'CosTransactions_Coordinator':is_same_transaction"), + ?line ?match(false, + 'CosTransactions_Coordinator':is_same_transaction(Coord, SubCoord1), + "'CosTransactions_Coordinator':is_same_transaction"), + ?line ?match(true, + 'CosTransactions_Coordinator':is_descendant_transaction(Coord, Coord), + "'CosTransactions_Coordinator':is_descendant_transaction"), + ?line ?match(false, + 'CosTransactions_Coordinator':is_descendant_transaction(Coord, SubCoord1), + "'CosTransactions_Coordinator':is_descendant_transaction"), + ?line ?match(true, + 'CosTransactions_Coordinator':is_descendant_transaction(SubCoord1, Coord), + "'CosTransactions_Coordinator':is_descendant_transaction"), + ?line ?match(false, + 'CosTransactions_Coordinator':is_descendant_transaction(SubCoord1, SubCoord2), + "'CosTransactions_Coordinator':is_descendant_transaction"), + ?line ?match(true, + 'CosTransactions_Coordinator':is_top_level_transaction(Coord), + "'CosTransactions_Coordinator':is_top_level_transaction"), + ?line ?match(false, + 'CosTransactions_Coordinator':is_top_level_transaction(SubCoord2), + "'CosTransactions_Coordinator':is_top_level_transaction"), + + RootHash = 'CosTransactions_Coordinator':hash_transaction(Coord), + RepeatHash= 'CosTransactions_Coordinator':hash_transaction(Coord), + RootHash2 = 'CosTransactions_Coordinator':hash_top_level_tran(SubCoord1), + RootHash3 = 'CosTransactions_Coordinator':hash_top_level_tran(Coord), + _SubHash = 'CosTransactions_Coordinator':hash_transaction(SubCoord2), + ?line ?match(RootHash, RepeatHash, + "'CosTransactions_Coordinator':hash_transaction"), + ?line ?match(RootHash, RootHash2, + "'CosTransactions_Coordinator':hash_top_level_tran"), + ?line ?match(RootHash, RootHash3, + "'CosTransactions_Coordinator':hash_top_level_tran"), +% ?line ?match_inverse(RootHash, SubHash, +% "'CosTransactions_Coordinator':hash_transaction"), + + ?line ?match('StatusActive', + 'CosTransactions_Coordinator':get_status(Coord), + "'CosTransactions_Coordinator':get_status"), + ?line ?match('StatusActive', + 'CosTransactions_Coordinator':get_status(SubCoord1), + "'CosTransactions_Coordinator':get_status"), + ?line ?match('StatusActive', + 'CosTransactions_Coordinator':get_parent_status(Coord), + "'CosTransactions_Coordinator':get_parent_status"), + ?line ?match('StatusActive', + 'CosTransactions_Coordinator':get_parent_status(SubCoord1), + "'CosTransactions_Coordinator':get_parent_status"), + ?line ?match('StatusActive', + 'CosTransactions_Coordinator':get_top_level_status(Coord), + "'CosTransactions_Coordinator':get_top_level_status"), + ?line ?match('StatusActive', + 'CosTransactions_Coordinator':get_top_level_status(SubCoord1), + "'CosTransactions_Coordinator':get_top_level_status"), + + %% Create a CosTransactions::Resource to experiments with. + %% Start a new transaction: + %% RootCoord + %% / \ + %% SubCoord1 SubCoord2 + %% / + %% Resource + N1 = 'ETraP_Common':create_name("test"), + O1 = etrap_test_server:oe_create(?nop, {global, N1}), + _RC1 = 'CosTransactions_Coordinator':register_resource(SubCoord1, O1), +% 'CosTransactions_Coordinator':register_synchronization(SubCoord1, O1), + + ?line ?match('VoteCommit', + 'CosTransactions_Resource':prepare(SubCoord1), + "'CosTransactions_Coordinator':prepare"), + %% The Transaction are no longer in 'StatusActive' state. No new + %% "members" allowed. + ?line ?match('StatusPrepared', + 'CosTransactions_Coordinator':get_status(SubCoord1), + "'CosTransactions_Coordinator':get_status"), +% ?line ?match({'EXCEPTION', ?tr_inactive}, +% 'CosTransactions_Coordinator':register_synchronization(SubCoord1, O1), +% "'CosTransactions_Coordinator':register_synchronization"), + ?line ?match({'EXCEPTION', ?tr_inactive}, + 'CosTransactions_Coordinator':register_resource(SubCoord1, O1), + "'CosTransactions_Coordinator':register_resource"), + ?line ?match({'EXCEPTION', ?tr_inactive}, + 'CosTransactions_Coordinator':create_subtransaction(SubCoord1), + "'CosTransactions_Coordinator':create_subtransaction"), + + catch corba:dispose(SubCoord1), + catch corba:dispose(SubCoord2), + catch corba:dispose(SubCont1), + catch corba:dispose(SubCont2), + catch corba:dispose(Term), + catch corba:dispose(Control), + catch corba:dispose(Coord), + catch corba:dispose(O1), + + ?line cosTransactions:stop_factory(TrFac), + ?line application:stop(cosTransactions), + ok. + +%%----------------------------------------------------------------- +%% API tests +%%----------------------------------------------------------------- +resource_api(doc) -> ["cosTransactions API tests", ""]; +resource_api(suite) -> []; +resource_api(_Config) -> + ?line ?match(ok, application:start(cosTransactions), + "Starting the cosTransactions application"), + ?line TrFac = cosTransactions:start_factory([{typecheck, true}]), + + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?prepare_rollback}), + "TESTCASE #1: Prepare rollback Resource 4"), + ?line ?match({'EXCEPTION', ?tr_mixed}, + run(TrFac, 0, {?nop, ?nop, ?commit_mix, ?nop}), + "TESTCASE #2: Heuristic Mixed exception Resource 3"), + ?line ?match(ok, + run(TrFac, 0, {?nop, ?nop, ?nop, ?nop}), + "TESTCASE #3: Normal completion. No errors."), + ?line ?match(ok, + run(TrFac, 0, {?nop, ?nop, ?nop, ?commit_cm}), + "TESTCASE #4: Heuristic Commit Exception Resource 4"), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + run(TrFac, 0, {?nop, ?rollback_rb, ?nop, ?prepare_rollback}), + "TESTCASE #5: Heuristic Rollbac Resource 2, Resource 4 reply 'VoteRollback'"), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + run(TrFac, 0, {?nop, ?nop, ?prepare_rollback, ?rollback_rb}), + "TESTCASE #6: Heuristic Rollbac Resource 4, Resource 3 reply 'VoteRollback'"), + ?line ?match(ok, + run(TrFac, 0, {?nop, ?nop, ?commit_delay, ?nop}), + "TESTCASE #7: Resource 3 delay during commit. No timeout."), + ?line ?match(ok, + run(TrFac, 0, {?nop, ?nop, ?prepare_delay, ?nop}), + "TESTCASE #8: Resource 3 delay during prepare. No timeout."), + ?line ?match(ok, + run(TrFac, ?TIMEOUT, {?nop, ?commit_delay, ?nop, ?nop}), + "TESTCASE #9: Resource 3 delay during commit. Timeout."), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + run(TrFac, ?TIMEOUT, {?nop, ?prepare_delay, ?nop, ?nop}), + "TESTCASE #10: Resource 3 delay during prepare. Timeout."), + case ?is_debug_compiled of + true -> + %% Testing the Coordinators (root and sub). + ?line ?match(ok, + run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop,?crash_transient(commit), ?nop]}), + "TESTCASE #11: SubCoord 3 crash transient during commit."), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop,?crash_transient(send_prepare), ?nop]}), + "TESTCASE #12: SubCoord 3 crash transient during send prepare."), + ?line ?match({'EXCEPTION', ?tr_hazard}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop,?crash_permanent(commit), ?nop]}), + "TESTCASE #13: SubCoord 3 crash permanent during commit."), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop,?crash_permanent(send_prepare), ?nop]}), + "TESTCASE #14: SubCoord 3 crash permanent during prepare."), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?crash_transient(send_prepare), ?crash_transient(commit), ?nop]}), + "TESTCASE #15: SubCoord 2 crash transient during prepare. SubCoord 3 crash transient during commit"), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?crash_transient(send_prepare), ?nop, ?nop, ?nop]}), + "TESTCASE #16: RootCoord crash transient during send prepare."), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{}}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?nop, [?nop, ?crash_transient(prepare1), ?nop, ?nop]}), + "TESTCASE #17: SubCoord 1 crash transient during prepare1."), + ?line ?match({'EXCEPTION', ?tr_mixed}, + run(TrFac, 0, {?nop, ?prepare_mix, ?nop, ?nop, [?nop, ?nop, ?crash_transient(prepare2), ?nop]}), + "TESTCASE #18: SubCoord 3 crash transient during prepare2. Resource 2 raise Heuristic Mixed during prepare"), + ?line ?match({'EXCEPTION', ?tr_mixed}, + run(TrFac, 0, {?nop, ?commit_mix, ?nop, ?nop, [?nop, ?nop, ?crash_transient(commit2), ?nop]}), + "TESTCASE #19: Resource 2 raise Heurist mixed during commit. SubCoord crash transient commit2"), + ?line ?match({'EXCEPTION', ?tr_mixed}, + run(TrFac, 0, {?nop, ?rollback_cm, ?nop, ?prepare_rollback, [?nop, ?crash_transient(rollback2), ?nop, ?nop]}), + "TESTCASE #20: Resource 2 raise Heuristic Commit during rollback. Resource 4 'VoteRollback'. SubCoord 2 crash transient rollback2."), + ?line ?match({'EXCEPTION', ?tr_mixed}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?commit_mix, [?nop, ?nop, ?crash_transient(send_forget1), ?nop]}), + "TESTCASE #21: Resource 4 raise Heuristic Mixed during commit. SubCoord 2 crash transient send_forget1."), + ?line ?match({'EXCEPTION', ?tr_mixed}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?commit_mix, [?crash_transient(send_forget1), ?nop, ?nop, ?nop]}), + "TESTCASE #22: Resource 4 raise Heuristic Mixed during commit. Root Coord crash transient send_forget1."), + ?line ?match({'EXCEPTION', ?tr_mixed}, + run(TrFac, 0, {?nop, ?nop, ?nop, ?commit_mix, [?crash_transient(send_forget3), ?nop, ?crash_transient(send_forget1), ?nop]}), + "TESTCASE #23: Resource 4 raise Heuristic Mixed during commit. Root Coord crash transient send_forget3. SubCoord 3 crash transient send_forget1."), + ?line ?match({'EXCEPTION', #'TRANSACTION_ROLLEDBACK'{completion_status=?COMPLETED_YES}}, + run(TrFac, ?TIMEOUT, {?nop, ?nop, ?nop, ?nop, [?delay_transient(root_delay, ?TIMEOUT*2), ?nop, ?nop, ?nop]}), + "TESTCASE #24: Delay RootCoord. Timeout."), + %% Testing the Terminator. + ?line ?match({'EXCEPTION', ?tr_mixed}, + run(TrFac, ?TIMEOUT, {?nop, ?prepare_mix, ?nop, ?nop, [?nop, ?nop, ?nop, ?crash_transient(commit_heuristic1)]}), + "TESTCASE #25: Terminator crash transient after received and logged Heuristic mix."), + ?line ?match(ok, + run(TrFac, ?TIMEOUT, {?nop, ?nop, ?nop, ?nop, [?nop, ?nop, ?nop, ?crash_transient(commit_ok2)]}), + "TESTCASE #26: Terminator crash transient after received and logged 'ok'."); + _ -> + ok + end, + + ?line cosTransactions:stop_factory(TrFac), + ?line application:stop(cosTransactions), + ok. + +%%----------------------------------------------------------------- +%% Internal functions +%%----------------------------------------------------------------- + +run(TrFac, Time, Spec) -> + Control = 'CosTransactions_TransactionFactory':create(TrFac, Time), + Term = 'CosTransactions_Control':get_terminator(Control), + Coord = 'CosTransactions_Control':get_coordinator(Control), + SubCont1 = 'CosTransactions_Coordinator':create_subtransaction(Coord), + SubCont2 = 'CosTransactions_Coordinator':create_subtransaction(Coord), + SubCoord1 = 'CosTransactions_Control':get_coordinator(SubCont1), + SubCoord2 = 'CosTransactions_Control':get_coordinator(SubCont2), + %% Start resources/participants. + {O1, O2, O3, O4, Ctx} = start_resources(Spec), + + %% Get generated names to use for debugging. + CoordN = 'CosTransactions_Coordinator':get_transaction_name(Coord), + SubC1N = 'CosTransactions_Coordinator':get_transaction_name(SubCoord1), + SubC2N = 'CosTransactions_Coordinator':get_transaction_name(SubCoord2), + + ?set_debug_context([CoordN, SubC1N, SubC2N, Term], Ctx), + + %% Register the resources as participants. + _RC1 = 'CosTransactions_Coordinator':register_resource(SubCoord1, O1), + _RC2 = 'CosTransactions_Coordinator':register_resource(SubCoord1, O2), + _RC3 = 'CosTransactions_Coordinator':register_resource(SubCoord2, O3), + _RC4 = 'CosTransactions_Coordinator':register_resource(SubCoord2, O4), + + 'CosTransactions_Coordinator':register_subtran_aware(SubCoord1, O4), +% 'CosTransactions_Coordinator':register_synchronization(SubCoord1, O2), + +% Reply = (catch 'CosTransactions_Terminator':commit(Term, true)), + Reply = (catch 'ETraP_Common':send_stubborn('CosTransactions_Terminator', + commit, [Term, true], + ?tr_max_retries, + ?tr_comm_failure_wait)), + + catch corba:dispose(SubCoord1), + catch corba:dispose(SubCoord2), + catch corba:dispose(SubCont1), + catch corba:dispose(SubCont2), + catch corba:dispose(Term), + catch corba:dispose(Control), + catch corba:dispose(Coord), + catch corba:dispose(O1), + catch corba:dispose(O2), + catch corba:dispose(O3), + catch corba:dispose(O4), + Reply. + + + +start_resources({A1, A2, A3, A4})-> + start_resources({A1, A2, A3, A4, ?no_context}); +start_resources({A1, A2, A3, A4, Ctx})-> + N1 = 'ETraP_Common':create_name("test"), + N2 = 'ETraP_Common':create_name("test"), + N3 = 'ETraP_Common':create_name("test"), + N4 = 'ETraP_Common':create_name("test"), + {_,_,O1} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST(A1, N1)), + {_,_,O2} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST(A2, N2)), +% {_,_,O2} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST([{sync,true}|A2], N2)), + {_,_,O3} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST(A3, N3)), + {_,_,O4} = supervisor:start_child(?SUPERVISOR_NAME, ?SUP_TEST(A4, N4)), + {O1, O2, O3, O4, Ctx}. |