1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 1997-2011. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: 20: -module(after_SUITE). 21: 22: %% Tests receive after. 23: 24: -include_lib("test_server/include/test_server.hrl"). 25: 26: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 27: init_per_group/2,end_per_group/2, 28: t_after/1, receive_after/1, receive_after_big/1, 29: receive_after_errors/1, receive_var_zero/1, receive_zero/1, 30: multi_timeout/1, receive_after_32bit/1]). 31: 32: -export([init_per_testcase/2, end_per_testcase/2]). 33: 34: %% Internal exports. 35: 36: -export([timeout_g/0]). 37: 38: suite() -> [{ct_hooks,[ts_install_cth]}]. 39: 40: all() -> 41: [t_after, receive_after, receive_after_big, 42: receive_after_errors, receive_var_zero, receive_zero, 43: multi_timeout, receive_after_32bit]. 44: 45: groups() -> 46: []. 47: 48: init_per_suite(Config) -> 49: Config. 50: 51: end_per_suite(_Config) -> 52: ok. 53: 54: init_per_group(_GroupName, Config) -> 55: Config. 56: 57: end_per_group(_GroupName, Config) -> 58: Config. 59: 60: 61: init_per_testcase(Func, Config) when is_atom(Func), is_list(Config) -> 62: Dog=?t:timetrap(?t:minutes(3)), 63: [{watchdog, Dog}|Config]. 64: 65: end_per_testcase(_Func, Config) -> 66: Dog=?config(watchdog, Config), 67: ?t:timetrap_cancel(Dog). 68: 69: %% Tests for an old round-off error in 'receive after'." 70: t_after(Config) when is_list(Config) -> 71: ?line spawn(fun frequent_process/0), 72: ?line Period = test_server:minutes(1), 73: ?line Before = erlang:now(), 74: receive 75: after Period -> 76: ?line After = erlang:now(), 77: ?line report(Period, Before, After) 78: end. 79: 80: 81: report(Period, Before, After) -> 82: ?line Elapsed = (element(1, After)*1000000000 83: +element(2, After)*1000 84: +element(3, After) div 1000) - 85: (element(1,Before)*1000000000 86: + element(2,Before)*1000 + element(3,Before) div 1000), 87: ?line case Elapsed*100 / Period of 88: Percent when Percent > 100.10 -> 89: ?line test_server:fail({too_inaccurate, Percent}); 90: Percent when Percent < 100.0 -> 91: ?line test_server:fail({too_early, Percent}); 92: Percent -> 93: ?line Comment = io_lib:format("Elapsed/expected: ~.2f %", 94: [Percent]), 95: {comment, lists:flatten(Comment)} 96: end. 97: 98: frequent_process() -> 99: receive 100: after 100 -> 101: ?line frequent_process() 102: end. 103: 104: receive_after(doc) -> 105: "Test that 'receive after' works (doesn't hang). " 106: "The test takes 10 seconds to complete."; 107: receive_after(Config) when is_list(Config) -> 108: ?line receive_after1(5000). 109: 110: receive_after1(1) -> 111: ?line io:format("Testing: receive after ~p~n", [1]), 112: ?line receive after 1 -> ok end; 113: receive_after1(N) -> 114: ?line io:format("Testing: receive after ~p~n", [N]), 115: ?line receive after N -> receive_after1(N div 2) end. 116: 117: receive_after_big(Config) when is_list(Config) -> 118: %% Test that 'receive after' with a 32 bit number works. 119: receive_after_big1(16#f7654321), 120: receive_after_big2(). 121: 122: receive_after_big1(Timeout) -> 123: Self = self(), 124: erlang:yield(), 125: spawn(fun() -> Self ! here_is_a_message end), 126: ok = receive 127: here_is_a_message -> 128: ok 129: after Timeout -> 130: %% We test that the timeout can be set, 131: %% not that an timeout occurs after the appropriate delay 132: %% (48 days, 56 minutes, 48 seconds)! 133: timeout 134: end. 135: 136: receive_after_big2() -> 137: Self = self(), 138: erlang:yield(), 139: spawn(fun() -> Self ! here_is_a_message end), 140: ok = receive 141: here_is_a_message -> 142: ok 143: after 16#f7999977 -> 144: %% We only test that the timeout can be set. 145: timeout 146: end. 147: 148: -define(TryAfter(Timeout), 149: {'EXIT',{timeout_value,_}} = (catch receive mission -> exit(impossible) after Timeout -> ok end), 150: {'EXIT',{timeout_value,_}} = (catch receive after Timeout -> ok end), 151: try_after(Timeout)). 152: 153: %% Test error cases for 'receive after'. 154: receive_after_errors(Config) when is_list(Config) -> 155: ?line ?TryAfter(-1), 156: ?line ?TryAfter(0.0), 157: ?line ?TryAfter(3.14), 158: ?line ?TryAfter(16#100000000), 159: ?line ?TryAfter(392347129847294724972398472984729847129874), 160: ?line ?TryAfter(16#3fffffffffffffff), 161: ?line ?TryAfter(16#ffffffffffffffff), 162: ?line ?TryAfter(-16#100000000), 163: ?line ?TryAfter(-3891278094774921784123987129848), 164: ?line ?TryAfter(xxx), 165: ok. 166: 167: try_after(Timeout) -> 168: {'EXIT',{timeout_value,_}} = (catch receive after Timeout -> ok end). 169: 170: receive_var_zero(doc) -> "Test 'after Z', when Z == 0."; 171: receive_var_zero(Config) when is_list(Config) -> 172: self() ! x, 173: self() ! y, 174: Z = zero(), 175: timeout = receive 176: z -> ok 177: after Z -> timeout 178: end, 179: timeout = receive 180: after Z -> timeout 181: end, 182: self() ! w, 183: receive 184: x -> ok; 185: Other -> 186: ?line ?t:fail({bad_message,Other}) 187: end. 188: 189: zero() -> 0. 190: 191: %% Test 'after 0'. 192: receive_zero(Config) when is_list(Config) -> 193: self() ! x, 194: self() ! y, 195: timeout = receive 196: z -> ok 197: after 0 -> 198: timeout 199: end, 200: self() ! w, 201: timeout = receive 202: after 0 -> timeout 203: end, 204: receive 205: x -> ok; 206: Other -> 207: ?line ?t:fail({bad_message,Other}) 208: end. 209: 210: multi_timeout(doc) -> 211: "Test for catching invalid assertion in erl_message.c (in queue_message)." 212: "This failed (dumped core) with debug-compiled emulator."; 213: multi_timeout(Config) when is_list(Config) -> 214: ?line P = spawn(?MODULE, timeout_g, []), 215: ?line P ! a, 216: ?line P ! b, 217: ?line receive 218: after 1000 -> ok 219: end, 220: ?line P ! c, 221: ?line receive 222: after 1000 -> ok 223: end, 224: ?line P ! d, 225: ok. 226: 227: timeout_g() -> 228: ?line receive 229: a -> ok 230: end, 231: ?line receive 232: after 100000 -> ok 233: end, 234: ok. 235: 236: %% OTP-7493: Timeout for 32 bit numbers (such as 16#ffffFFFF) could 237: %% timeout at once. 238: receive_after_32bit(Config) when is_list(Config) -> 239: T = 16#ffffFFFF, 240: Pids = [spawn_link(fun() -> recv_after_32bit(I, T) end) || 241: I <- lists:seq(1, 2048)], 242: 243: %% Wait two seconds for any of the processes to timeout too early. 244: receive after 2000 -> ok end, 245: 246: %% Kill the processes. 247: [begin unlink(Pid), exit(Pid, kill) end || Pid <- Pids], 248: ok. 249: 250: recv_after_32bit(I, T) when I rem 2 =:= 0 -> 251: receive after T -> exit(timeout) end; 252: recv_after_32bit(_, _) -> 253: receive after 16#ffffFFFF -> exit(timeout) end. 254: