aboutsummaryrefslogblamecommitdiffstats
path: root/lib/hipe/test/basic_SUITE_data/basic_receive.erl
blob: 20e3f350e88a41be01450007df94910432369d68 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14













                                                                      
                        









































                                                                      























































































                                                                          
%%% -*- erlang-indent-level: 2 -*-
%%%-------------------------------------------------------------------
%%% Author: Kostis Sagonas
%%%
%%% Contains code examples that test correct handling of receives.
%%%-------------------------------------------------------------------
-module(basic_receive).

-export([test/0]).

test() ->
  ok = test_wait_timeout(),
  ok = test_double_timeout(),
  ok = test_reschedule(),
  ok = test_recv_mark(),
  ok.

%%--------------------------------------------------------------------

test_wait_timeout() ->
  receive after 42 -> ok end.

%%--------------------------------------------------------------------

test_double_timeout() ->
  self() ! foo,
  self() ! another_foo,
  receive
    non_existent -> weird
  after 0 -> timeout
  end,
  receive
    foo -> ok
  after 1000 -> timeout
  end.

%%--------------------------------------------------------------------
%% Check that RESCHEDULE returns from BIFs work.

test_reschedule() ->
  erts_debug:set_internal_state(available_internal_state, true),
  First = self(),
  Second = spawn(fun() -> doit(First) end),
  receive
    Second -> ok
  end,
  receive
  after 42 -> ok
  end,
  erts_debug:set_internal_state(hipe_test_reschedule_resume, Second),
  ok.

doit(First) ->
  First ! self(),
  erts_debug:set_internal_state(hipe_test_reschedule_suspend, 1).

%%--------------------------------------------------------------------
%% Check that we cannot cause a recv_mark,recv_set pair to misbehave and
%% deadlock the process.

test_recv_mark() ->
  ok = test_recv_mark(fun disturber_nop/0),
  ok = test_recv_mark(fun disturber_receive/0),
  ok = test_recv_mark(fun disturber_other/0),
  ok = test_recv_mark(fun disturber_recurse/0),
  ok = test_recv_mark_after(self(), fun disturber_after_recurse/0, false),
  ok = test_recv_mark(fun disturber_other_recurse/0),
  ok = test_recv_mark(fun disturber_other_after/0),
  ok = test_recv_mark_nested().

test_recv_mark(Disturber) ->
  Ref = make_ref(),
  self() ! Ref,
  Disturber(),
  receive Ref -> ok
  after 0 -> error(failure)
  end.

disturber_nop() -> ok.

disturber_receive() ->
  self() ! message,
  receive message -> ok end.

disturber_other() ->
  Ref = make_ref(),
  self() ! Ref,
  receive Ref -> ok end.

disturber_recurse() ->
  aborted = (catch test_recv_mark(fun() -> throw(aborted) end)),
  ok.

test_recv_mark_after(Recipient, Disturber, IsInner) ->
  Ref = make_ref(),
  Recipient ! Ref,
  Disturber(),
  receive
      Ref -> ok
  after 0 ->
          case IsInner of
              true -> expected;
              false -> error(failure)
          end
  end.

disturber_after_recurse() ->
  NoOp = fun() -> ok end,
  BlackHole = spawn(NoOp),
  expected = test_recv_mark_after(BlackHole, NoOp, true),
  ok.

disturber_other_recurse() ->
  aborted = (catch disturber_other_recurse(fun() -> throw(aborted) end)),
  ok.

disturber_other_recurse(InnerD) ->
  Ref = make_ref(),
  self() ! Ref,
  InnerD(),
  receive Ref -> ok
  after 0 -> error(failure)
  end.

disturber_other_after() ->
  BlackHole = spawn(fun() -> ok end),
  Ref = make_ref(),
  BlackHole ! Ref,
  receive Ref -> error(imposible)
  after 0 -> ok
  end.

test_recv_mark_nested() ->
  Ref1 = make_ref(),
  self() ! Ref1,
  begin
    Ref2 = make_ref(),
    self() ! Ref2,
    receive Ref2 -> ok end
  end,
  receive Ref1 -> ok
  after 0 -> error(failure)
  end.

%%--------------------------------------------------------------------