diff options
author | Lukas Larsson <[email protected]> | 2011-02-17 17:07:05 +0100 |
---|---|---|
committer | Lukas Larsson <[email protected]> | 2011-02-17 17:09:38 +0100 |
commit | 53974a3517268389ae18fabee509ebf4bbfce747 (patch) | |
tree | 208575bf9ac4916c6b60e052c6f712986c3f0de9 /lib/common_test/src/ct_hooks_lock.erl | |
parent | b83388e78e72e66f4e0dae42083a6bcd9709922e (diff) | |
parent | d87708bf18d29c0a66f6654368b4553067e62394 (diff) | |
download | otp-53974a3517268389ae18fabee509ebf4bbfce747.tar.gz otp-53974a3517268389ae18fabee509ebf4bbfce747.tar.bz2 otp-53974a3517268389ae18fabee509ebf4bbfce747.zip |
Merge branch 'lukas/common_test/suite_callback/OTP-8851' into dev
* lukas/common_test/suite_callback/OTP-8851: (54 commits)
Update example cth spec to reflect the implementation
Cleanup code to fix dialyzer warning
Rename Suite Callback to Common Test hook in documentation
Rename Suite Callback to Common Test Hook in code and testcases
Fix bug where the state of an SCB was altered when no on_tc_* existed
Update SCBs to use a specific id/1 function for SCb overriding instead of returning it from init/1.
Add documentation for SCBs
Update suite callback test timeout so that beam debug test runs do not timeout
Update test support so that if common test fails to be stopped in a suite, the ct node is restarted and the test case fails
Add tests for SCB's with same id and fixed bug relating to it
Add test suites for failing in init/1 function
Added tests for starting SCB's with arguments and fixed a bug with how SCB's are parsed from the command line
Add so that failures in SCB:init/1 causes the entire scb scope to fail
Fix bug which caused scb to be added too much when initiated in the suite info function
Started work on documenting suite callbacks, this is a partial commit
Add locking mechanism for scb state when using parallel groups
Add state update tests for suite callbacks
Update ct_framework calls to allow manipulation of test results in end_tc without breaking backwards compatability (I hope)
Add test case for init_per_suite recover scenario
Add testcase for config updates
...
Diffstat (limited to 'lib/common_test/src/ct_hooks_lock.erl')
-rw-r--r-- | lib/common_test/src/ct_hooks_lock.erl | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/lib/common_test/src/ct_hooks_lock.erl b/lib/common_test/src/ct_hooks_lock.erl new file mode 100644 index 0000000000..98794201bb --- /dev/null +++ b/lib/common_test/src/ct_hooks_lock.erl @@ -0,0 +1,132 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2010. 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% +%% + +%%% @doc Common Test Framework test execution control module. +%%% +%%% <p>This module is a proxy for calling and handling locks in +%%% common test hooks.</p> + +-module(ct_hooks_lock). + +-behaviour(gen_server). + +%% API +-export([start/1, stop/1, request/0, release/0]). + +%% gen_server callbacks +-export([init/1, handle_call/3, handle_cast/2, handle_info/2, + terminate/2, code_change/3]). + +-define(SERVER, ?MODULE). + +-record(state, { id, locked = false, requests = [] }). + +%%%=================================================================== +%%% API +%%%=================================================================== + +%% @doc Starts the server +start(Id) -> + case gen_server:start({local, ?SERVER}, ?MODULE, Id, []) of + {error,{already_started, Pid}} -> + {ok,Pid}; + Else -> + Else + end. + +stop(Id) -> + try + gen_server:call(?SERVER, {stop,Id}) + catch exit:{noproc,_} -> + stopped + end. + +request() -> + try + gen_server:call(?SERVER,{request,self()},infinity) + catch exit:{noproc,_} -> + locked + end. + +release() -> + try + gen_server:call(?SERVER,{release,self()}) + catch exit:{noproc,_} -> + unlocked + end. + +%%%=================================================================== +%%% gen_server callbacks +%%%=================================================================== + +%% @doc Initiates the server +init(Id) -> + {ok, #state{ id = Id }}. + +%% @doc Handling call messages +handle_call({stop,Id}, _From, #state{ id = Id, requests = Reqs } = State) -> + [gen_server:reply(Req, locker_stopped) || {Req,_ReqId} <- Reqs], + {stop, normal, stopped, State}; +handle_call({stop,_Id}, _From, State) -> + {reply, stopped, State}; +handle_call({request, Pid}, _From, #state{ locked = false, + requests = [] } = State) -> + Ref = monitor(process, Pid), + {reply, locked, State#state{ locked = {true, Pid, Ref}} }; +handle_call({request, Pid}, From, #state{ requests = Reqs } = State) -> + {noreply, State#state{ requests = Reqs ++ [{From,Pid}] }}; +handle_call({release, Pid}, _From, #state{ locked = {true, Pid, Ref}, + requests = []} = State) -> + demonitor(Ref,[flush]), + {reply, unlocked, State#state{ locked = false }}; +handle_call({release, Pid}, _From, + #state{ locked = {true, Pid, Ref}, + requests = [{NextFrom,NextPid}|Rest]} = State) -> + demonitor(Ref,[flush]), + gen_server:reply(NextFrom,locked), + NextRef = monitor(process, NextPid), + {reply,unlocked,State#state{ locked = {true, NextPid, NextRef}, + requests = Rest } }; +handle_call({release, _Pid}, _From, State) -> + {reply, not_locked, State}. + +%% @doc Handling cast messages +handle_cast(_Msg, State) -> + {noreply, State}. + +%% @doc Handling all non call/cast messages +handle_info({'DOWN',Ref,process,Pid,_}, + #state{ locked = {true, Pid, Ref}, + requests = [{NextFrom,NextPid}|Rest] } = State) -> + gen_server:reply(NextFrom, locked), + NextRef = monitor(process, NextPid), + {noreply,State#state{ locked = {true, NextPid, NextRef}, + requests = Rest } }. + +%% @doc This function is called by a gen_server when it is about to terminate. +terminate(_Reason, _State) -> + ok. + +%% @doc Convert process state when code is changed +code_change(_OldVsn, State, _Extra) -> + {ok, State}. + +%% ------------------------------------------------------------------------- +%% Internal Functions +%% ------------------------------------------------------------------------- |