Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

266 lines (236 sloc) 7.801 kb
%% ``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 via the world wide web 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.
%%
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
%% AB. All Rights Reserved.''
%%
%% @author Ulf Wiger <ulf.wiger@erlang-solutions.com>
%%
-module(gproc_tests).
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
reg_test_() ->
{setup,
fun() ->
application:start(gproc)
end,
fun(_) ->
application:stop(gproc)
end,
[
{spawn, ?_test(t_simple_reg())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_simple_prop())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_await())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_simple_mreg())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_gproc_crash())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_cancel_wait_and_register())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_give_away_to_pid())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_give_away_to_self())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_give_away_badarg())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_give_away_to_unknown())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_give_away_and_back())}
, ?_test(t_is_clean())
, {spawn, ?_test(t_select())}
, ?_test(t_is_clean())
]}.
t_simple_reg() ->
?assert(gproc:reg({n,l,name}) =:= true),
?assert(gproc:where({n,l,name}) =:= self()),
?assert(gproc:unreg({n,l,name}) =:= true),
?assert(gproc:where({n,l,name}) =:= undefined).
t_simple_prop() ->
?assert(gproc:reg({p,l,prop}) =:= true),
?assert(t_other_proc(fun() ->
?assert(gproc:reg({p,l,prop}) =:= true)
end) =:= ok),
?assert(gproc:unreg({p,l,prop}) =:= true).
t_other_proc(F) ->
{_Pid,Ref} = spawn_monitor(fun() -> exit(F()) end),
receive
{'DOWN',Ref,_,_,R} ->
R
after 10000 ->
erlang:error(timeout)
end.
t_await() ->
Me = self(),
{_Pid,Ref} = spawn_monitor(
fun() -> exit(?assert(gproc:await({n,l,t_await}) =:= {Me,val})) end),
?assert(gproc:reg({n,l,t_await},val) =:= true),
receive
{'DOWN', Ref, _, _, R} ->
?assertEqual(R, ok)
after 10000 ->
erlang:error(timeout)
end.
t_is_clean() ->
sys:get_status(gproc), % in order to synch
T = ets:tab2list(gproc),
?assert(T =:= []).
t_simple_mreg() ->
ok.
t_gproc_crash() ->
P = spawn_helper(),
?assert(gproc:where({n,l,P}) =:= P),
exit(whereis(gproc), kill),
give_gproc_some_time(100),
?assert(whereis(gproc) =/= undefined),
%%
%% Check that the registration is still there using an ets:lookup(),
%% Once we've killed the process, gproc will always return undefined
%% if the process is not alive, regardless of whether the registration
%% is still there. So, here, the lookup should find something...
%%
?assert(ets:lookup(gproc,{{n,l,P},n}) =/= []),
?assert(gproc:where({n,l,P}) =:= P),
exit(P, kill),
%% ...and here, it shouldn't.
%% (sleep for a while first to let gproc handle the EXIT
give_gproc_some_time(10),
?assert(ets:lookup(gproc,{{n,l,P},n}) =:= []).
t_cancel_wait_and_register() ->
Alias = {n, l, foo},
Me = self(),
P = spawn(fun() ->
{'EXIT',_} = (catch gproc:await(Alias, 100)),
?assert(element(1,sys:get_status(gproc)) == status),
Me ! {self(), go_ahead},
timer:sleep(infinity)
end),
receive
{P, go_ahead} ->
?assertEqual(gproc:reg(Alias, undefined), true),
exit(P, kill),
timer:sleep(500),
?assert(element(1,sys:get_status(gproc)) == status)
end.
t_give_away_to_pid() ->
From = {n, l, foo},
Me = self(),
P = spawn_link(fun t_loop/0),
?assertEqual(true, gproc:reg(From, undefined)),
?assertEqual(Me, gproc:where(From)),
?assertEqual(P, gproc:give_away(From, P)),
?assertEqual(P, gproc:where(From)),
?assertEqual(ok, t_call(P, die)).
t_give_away_to_self() ->
From = {n, l, foo},
Me = self(),
?assertEqual(true, gproc:reg(From, undefined)),
?assertEqual(Me, gproc:where(From)),
?assertEqual(Me, gproc:give_away(From, Me)),
?assertEqual(Me, gproc:where(From)),
?assertEqual(true, gproc:unreg(From)).
t_give_away_badarg() ->
From = {n, l, foo},
Me = self(),
?assertEqual(undefined, gproc:where(From)),
?assertError(badarg, gproc:give_away(From, Me)).
t_give_away_to_unknown() ->
From = {n, l, foo},
Unknown = {n, l, unknown},
Me = self(),
?assertEqual(true, gproc:reg(From, undefined)),
?assertEqual(Me, gproc:where(From)),
?assertEqual(undefined, gproc:where(Unknown)),
?assertEqual(undefined, gproc:give_away(From, Unknown)),
?assertEqual(undefined, gproc:where(From)).
t_give_away_and_back() ->
From = {n, l, foo},
Me = self(),
P = spawn_link(fun t_loop/0),
?assertEqual(true, gproc:reg(From, undefined)),
?assertEqual(Me, gproc:where(From)),
?assertEqual(P, gproc:give_away(From, P)),
?assertEqual(P, gproc:where(From)),
?assertEqual(ok, t_call(P, {give_away, From})),
?assertEqual(Me, gproc:where(From)),
?assertEqual(ok, t_call(P, die)).
t_select() ->
?assertEqual(true, gproc:reg({n, l, {n,1}}, x)),
?assertEqual(true, gproc:reg({n, l, {n,2}}, y)),
?assertEqual(true, gproc:reg({p, l, {p,1}}, x)),
?assertEqual(true, gproc:reg({p, l, {p,2}}, y)),
?assertEqual(true, gproc:reg({c, l, {c,1}}, 1)),
?assertEqual(true, gproc:reg({a, l, {c,1}}, undefined)),
%% local names
?assertEqual(
[{{n,l,{n,1}},self(),x},
{{n,l,{n,2}},self(),y}], gproc:select(
{local,names},
[{{{n,l,'_'},'_','_'},[],['$_']}])),
%% mactch local names on value
?assertEqual(
[{{n,l,{n,1}},self(),x}], gproc:select(
{local,names},
[{{{n,l,'_'},'_',x},[],['$_']}])),
%% match all on value
?assertEqual(
[{{n,l,{n,1}},self(),x},
{{p,l,{p,1}},self(),x}], gproc:select(
{all,all},
[{{{'_',l,'_'},'_',x},[],['$_']}])),
%% match all on pid
?assertEqual(
[{{a,l,{c,1}},self(),1},
{{c,l,{c,1}},self(),1},
{{n,l,{n,1}},self(),x},
{{n,l,{n,2}},self(),y},
{{p,l,{p,1}},self(),x},
{{p,l,{p,2}},self(),y}
], gproc:select(
{all,all},
[{{'_',self(),'_'},[],['$_']}])).
t_loop() ->
receive
{From, {give_away, Key}} ->
?assertEqual(From, gproc:give_away(Key, From)),
From ! {self(), ok},
t_loop();
{From, die} ->
From ! {self(), ok}
end.
t_call(P, Msg) ->
P ! {self(), Msg},
receive
{P, Reply} ->
Reply
end.
spawn_helper() ->
Parent = self(),
P = spawn(fun() ->
?assert(gproc:reg({n,l,self()}) =:= true),
Ref = erlang:monitor(process, Parent),
Parent ! {ok,self()},
receive
{'DOWN', Ref, _, _, _} ->
ok
end
end),
receive
{ok,P} ->
P
end.
give_gproc_some_time(T) ->
timer:sleep(T),
sys:get_status(gproc).
-endif.
Jump to Line
Something went wrong with that request. Please try again.