aboutsummaryrefslogtreecommitdiffstats
path: root/erts/test
diff options
context:
space:
mode:
Diffstat (limited to 'erts/test')
-rw-r--r--erts/test/Makefile81
-rw-r--r--erts/test/erl_print_SUITE.erl453
-rw-r--r--erts/test/erl_print_SUITE_data/Makefile.src45
-rw-r--r--erts/test/erl_print_SUITE_data/character_test.h586
-rw-r--r--erts/test/erl_print_SUITE_data/erl_print_tests.c560
-rw-r--r--erts/test/erl_print_SUITE_data/integer_64_test.h1106
-rw-r--r--erts/test/erl_print_SUITE_data/integer_test.h1106
-rw-r--r--erts/test/erl_print_SUITE_data/snprintf_test.h43
-rw-r--r--erts/test/erl_print_SUITE_data/string_test.h33
-rw-r--r--erts/test/erlc_SUITE.erl286
-rw-r--r--erts/test/erlc_SUITE_data/include/erl_test.hrl19
-rw-r--r--erts/test/erlc_SUITE_data/src/BAD-MIB.mib1
-rw-r--r--erts/test/erlc_SUITE_data/src/GOOD-MIB.mib39
-rw-r--r--erts/test/erlc_SUITE_data/src/erl_test_bad.erl22
-rw-r--r--erts/test/erlc_SUITE_data/src/erl_test_ok.erl29
-rw-r--r--erts/test/erlc_SUITE_data/src/start_bad.script1
-rw-r--r--erts/test/erlc_SUITE_data/src/start_ok.script207
-rw-r--r--erts/test/erlc_SUITE_data/src/yecc_test_bad.yrl32
-rw-r--r--erts/test/erlc_SUITE_data/src/yecc_test_ok.yrl29
-rw-r--r--erts/test/erlexec_SUITE.erl437
-rw-r--r--erts/test/erlexec_SUITE_data/Makefile.src37
-rw-r--r--erts/test/erlexec_SUITE_data/erlexec_tests.c110
-rw-r--r--erts/test/ethread_SUITE.erl365
-rw-r--r--erts/test/ethread_SUITE_data/Makefile.src41
-rw-r--r--erts/test/ethread_SUITE_data/ethread_tests.c2403
-rw-r--r--erts/test/ignore_cores.erl158
-rw-r--r--erts/test/nt_SUITE.erl551
-rw-r--r--erts/test/nt_SUITE_data/Makefile.src33
-rw-r--r--erts/test/nt_SUITE_data/nt_info.c176
-rw-r--r--erts/test/otp_SUITE.erl297
-rw-r--r--erts/test/run_erl_SUITE.erl270
-rw-r--r--erts/test/run_erl_SUITE_data/defuncter.pl31
-rw-r--r--erts/test/run_erl_SUITE_data/run_erl_test.pl41
-rw-r--r--erts/test/system.dynspec18
-rw-r--r--erts/test/system.spec1
-rw-r--r--erts/test/system.spec.vxworks2
-rw-r--r--erts/test/utils/gccifier.c316
-rw-r--r--erts/test/z_SUITE.erl315
38 files changed, 10280 insertions, 0 deletions
diff --git a/erts/test/Makefile b/erts/test/Makefile
new file mode 100644
index 0000000000..47e41a3625
--- /dev/null
+++ b/erts/test/Makefile
@@ -0,0 +1,81 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1997-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%
+#
+
+include $(ERL_TOP)/make/target.mk
+
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+EBIN = .
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ erlc_SUITE \
+ nt_SUITE \
+ otp_SUITE \
+ ethread_SUITE \
+ erl_print_SUITE \
+ run_erl_SUITE \
+ erlexec_SUITE \
+ z_SUITE
+
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES = $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/system_test
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+tests debug opt: $(TARGET_FILES)
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f core *~
+
+docs:
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec:
+
+release_tests_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)
+ $(INSTALL_DATA) system.spec system.dynspec system.spec.vxworks \
+ $(ERL_FILES) $(TARGET_FILES) $(RELSYSDIR)
+ chmod -f -R u+w $(RELSYSDIR)
+ tar cf - *_SUITE_data utils | (cd $(RELSYSDIR); tar xf -)
+
+release_docs_spec:
diff --git a/erts/test/erl_print_SUITE.erl b/erts/test/erl_print_SUITE.erl
new file mode 100644
index 0000000000..b1458d84d0
--- /dev/null
+++ b/erts/test/erl_print_SUITE.erl
@@ -0,0 +1,453 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-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%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : erl_print_SUITE.erl
+%%% Author : Rickard Green <[email protected]>
+%%% Description :
+%%%
+%%% Created : 10 Mar 2005 by Rickard Green <[email protected]>
+%%%-------------------------------------------------------------------
+-module(erl_print_SUITE).
+-author('[email protected]').
+
+
+%-define(line_trace, 1).
+
+-define(DEFAULT_TIMEOUT, ?t:minutes(10)).
+
+-export([all/1, init_per_testcase/2, fin_per_testcase/2]).
+
+-export([erlang_display/1, integer/1, float/1, string/1, character/1, snprintf/1, quote/1]).
+
+-include("test_server.hrl").
+
+all(doc) -> [];
+all(suite) -> test_cases().
+
+%%
+%%
+%% Test cases
+%%
+%%
+
+test_cases() ->
+ [erlang_display,
+ integer,
+ float,
+ string,
+ character,
+ snprintf,
+ quote].
+
+erlang_display(doc) -> [];
+erlang_display(suite) -> [];
+erlang_display(Config) when is_list(Config) ->
+ ?line put(erlang_display_test, ok),
+ OAIS = erts_debug:set_internal_state(available_internal_state, true),
+
+ %% atoms
+ ?line chk_display(atom, "atom"),
+ ?line chk_display(true, "true"),
+ ?line chk_display(false, "false"),
+ ?line chk_display('DOWN', "'DOWN'"),
+ ?line chk_display('EXIT', "'EXIT'"),
+ ?line chk_display('asdDofw $@{}][', "'asdDofw $@{}]['"),
+
+ %% integers
+ ?line chk_display(0, "0"),
+ ?line chk_display(1, "1"),
+ ?line chk_display(4711, "4711"),
+ ?line chk_display(((1 bsl 27) - 1), "134217727"),
+ ?line chk_display((1 bsl 27), "134217728"),
+ ?line chk_display((1 bsl 32), "4294967296"),
+ ?line chk_display(11111111111, "11111111111"),
+ ?line chk_display((1 bsl 59) - 1, "576460752303423487"),
+ ?line chk_display(1 bsl 59, "576460752303423488"),
+ ?line chk_display(111111111111111111111, "111111111111111111111"),
+ ?line chk_display(123456789012345678901234567890,
+ "123456789012345678901234567890"),
+ ?line chk_display(1 bsl 10000, str_1_bsl_10000()),
+ ?line chk_display(-1, "-1"),
+ ?line chk_display(-4711, "-4711"),
+ ?line chk_display(-(1 bsl 27), "-134217728"),
+ ?line chk_display(-((1 bsl 27) + 1), "-134217729"),
+ ?line chk_display(-(1 bsl 32), "-4294967296"),
+ ?line chk_display(-11111111111, "-11111111111"),
+ ?line chk_display(-(1 bsl 59), "-576460752303423488"),
+ ?line chk_display(-((1 bsl 59) + 1), "-576460752303423489"),
+ ?line chk_display(-111111111111111111111, "-111111111111111111111"),
+ ?line chk_display(-123456789012345678901234567890,
+ "-123456789012345678901234567890"),
+ ?line chk_display(-(1 bsl 10000), [$- | str_1_bsl_10000()]),
+
+ ?line MyCre = my_cre(),
+
+ %% pids
+ ?line chk_display(mk_pid_xstr({node(), MyCre}, 4711, 42)),
+ ?line chk_display(mk_pid_xstr({node(), oth_cre(MyCre)}, 4711, 42)),
+ ?line chk_display(mk_pid_xstr({node(), oth_cre(oth_cre(MyCre))}, 4711, 42)),
+
+ ?line chk_display(mk_pid_xstr({a@b, MyCre}, 4711, 42)),
+ ?line chk_display(mk_pid_xstr({a@b, oth_cre(MyCre)}, 4711, 42)),
+ ?line chk_display(mk_pid_xstr({a@b, oth_cre(oth_cre(MyCre))}, 4711, 42)),
+
+ %% ports
+ ?line chk_display(mk_port_xstr({node(), MyCre}, 4711)),
+ ?line chk_display(mk_port_xstr({node(), oth_cre(MyCre)}, 4711)),
+ ?line chk_display(mk_port_xstr({node(), oth_cre(oth_cre(MyCre))}, 4711)),
+
+ ?line chk_display(mk_port_xstr({c@d, MyCre}, 4711)),
+ ?line chk_display(mk_port_xstr({c@d, oth_cre(MyCre)}, 4711)),
+ ?line chk_display(mk_port_xstr({c@d, oth_cre(oth_cre(MyCre))}, 4711)),
+
+ %% refs
+ ?line chk_display(mk_ref_xstr({node(), MyCre}, [1,2,3])),
+ ?line chk_display(mk_ref_xstr({node(), oth_cre(MyCre)}, [1,2,3])),
+ ?line chk_display(mk_ref_xstr({node(), oth_cre(oth_cre(MyCre))}, [1,2,3])),
+
+ ?line chk_display(mk_ref_xstr({e@f, MyCre},[1,2,3] )),
+ ?line chk_display(mk_ref_xstr({e@f, oth_cre(MyCre)}, [1,2,3])),
+ ?line chk_display(mk_ref_xstr({e@f, oth_cre(oth_cre(MyCre))}, [1,2,3])),
+
+ %% Compund terms
+ ?line {Pid, PidStr} = mk_pid_xstr({x@y, oth_cre(MyCre)}, 4712, 41),
+ ?line {Port, PortStr} = mk_port_xstr({x@y, oth_cre(MyCre)}, 4712),
+ ?line {Ref, RefStr} = mk_ref_xstr({e@f, oth_cre(MyCre)}, [11,12,13]),
+
+ ?line chk_display({atom,-4711,Ref,{"hej",[Pid,222222222222222222222222,Port,4711]}},
+ "{atom,-4711,"++RefStr++",{\"hej\",["++PidStr++",222222222222222222222222,"++PortStr++",4711]}}"),
+ ?line chk_display({{{{{{{{{{{{{{{{{{{{{{{hi}}}}}}}}}}}}}}}}}}}}}}},
+ "{{{{{{{{{{{{{{{{{{{{{{{hi}}}}}}}}}}}}}}}}}}}}}}}"),
+ ?line chk_display([[[[[[[[[[[[[[[[[[[[[[[yo]]]]]]]]]]]]]]]]]]]]]]],
+ "[[[[[[[[[[[[[[[[[[[[[[[yo]]]]]]]]]]]]]]]]]]]]]]]"),
+ ?line chk_display({[{[{[{[{[{[{[{[{[{[{[{[ii]}]}]}]}]}]}]}]}]}]}]}]},
+ "{[{[{[{[{[{[{[{[{[{[{[{[ii]}]}]}]}]}]}]}]}]}]}]}]}"),
+ ?line chk_display([], "[]"), % Not really a compound term :)
+ ?line chk_display([a|b], "[a|b]"),
+ ?line chk_display([a,b,c|z], "[a,b,c|z]"),
+ ?line chk_display([a,b,c], "[a,b,c]"),
+ ?line chk_display([Pid,Port,Ref],
+ "["++PidStr++","++PortStr++","++RefStr++"]"),
+ ?line chk_display("abcdefghijklmnopqrstuvwxyz",
+ "\"abcdefghijklmnopqrstuvwxyz\""),
+ ?line chk_display("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+ "\"ABCDEFGHIJKLMNOPQRSTUVWXYZ\""),
+ ?line chk_display("H E J", "\"H E J\""),
+ ?line chk_display("asdDofw $@{}][", "\"asdDofw $@{}][\""),
+
+ %%
+ %% TODO: Check binaries, fun and floats...
+ %%
+
+ erts_debug:set_internal_state(available_internal_state, OAIS),
+ ?line ok = get(erlang_display_test).
+
+get_chnl_no(NodeName) when is_atom(NodeName) ->
+ erts_debug:get_internal_state({channel_number, NodeName}).
+
+chk_display(Term, Expect) when is_list(Expect) ->
+ Dstr = erts_debug:display(Term),
+ case Expect ++ io_lib:nl() of
+ Dstr ->
+ ?t:format("Test of \"~p\" succeeded.~n"
+ " Expected and got: ~s~n",
+ [Term, io_lib:write_string(Dstr)]);
+ DoExpect ->
+ ?t:format("***~n"
+ "*** Test of \"~p\" failed!~n"
+ "*** Expected: ~s~n"
+ "*** Got: ~s~n"
+ "***~n",
+ [Term,
+ io_lib:write_string(DoExpect),
+ io_lib:write_string(Dstr)]),
+ put(erlang_display_test, failed)
+ end.
+
+chk_display({Term, Expect}) ->
+ chk_display(Term, Expect).
+
+mk_pid_xstr({NodeName, Creation}, Number, Serial) ->
+ Pid = mk_pid({NodeName, Creation}, Number, Serial),
+ XStr = "<" ++ integer_to_list(get_chnl_no(NodeName))
+ ++ "." ++ integer_to_list(Number)
+ ++ "." ++ integer_to_list(Serial) ++ ">",
+ {Pid, XStr}.
+
+mk_port_xstr({NodeName, Creation}, Number) ->
+ Port = mk_port({NodeName, Creation}, Number),
+ XStr = "#Port<" ++ integer_to_list(get_chnl_no(NodeName))
+ ++ "." ++ integer_to_list(Number) ++ ">",
+ {Port, XStr}.
+
+mk_ref_xstr({NodeName, Creation}, Numbers) ->
+ Ref = mk_ref({NodeName, Creation}, Numbers),
+ XStr = "#Ref<" ++ integer_to_list(get_chnl_no(NodeName))
+ ++ ref_numbers_xstr(Numbers) ++ ">",
+ {Ref, XStr}.
+
+ref_numbers_xstr([]) ->
+ [];
+ref_numbers_xstr([N | Ns]) ->
+ ref_numbers_xstr(Ns) ++ "." ++ integer_to_list(N).
+
+-define(TESTCASE_IMPL(T), T(A) -> default_testcase_impl(A)).
+
+?TESTCASE_IMPL(integer).
+?TESTCASE_IMPL(float).
+?TESTCASE_IMPL(string).
+?TESTCASE_IMPL(character).
+?TESTCASE_IMPL(snprintf).
+?TESTCASE_IMPL(quote).
+
+%%
+%%
+%% Auxiliary functions
+%%
+%%
+
+default_testcase_impl(doc) -> [];
+default_testcase_impl(suite) -> [];
+default_testcase_impl(Config) when is_list(Config) -> ?line run_case(Config).
+
+init_per_testcase(Case, Config) ->
+ Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
+ [{testcase, Case}, {watchdog, Dog} |Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+-define(TESTPROG, "erl_print_tests").
+-define(FAILED_MARKER, $E,$P,$-,$T,$E,$S,$T,$-,$F,$A,$I,$L,$U,$R,$E).
+-define(SKIPPED_MARKER, $E,$P,$-,$T,$E,$S,$T,$-,$S,$K,$I,$P).
+-define(SUCCESS_MARKER, $E,$P,$-,$T,$E,$S,$T,$-,$S,$U,$C,$C,$E,$S,$S).
+-define(PID_MARKER, $E,$P,$-,$T,$E,$S,$T,$-,$P,$I,$D).
+
+port_prog_killer(EProc, OSProc) when is_pid(EProc), is_list(OSProc) ->
+ ?line process_flag(trap_exit, true),
+ ?line Ref = erlang:monitor(process, EProc),
+ ?line receive
+ {'DOWN', Ref, _, _, Reason} when is_tuple(Reason),
+ element(1, Reason)
+ == timetrap_timeout ->
+ ?line Cmd = "kill -9 " ++ OSProc,
+ ?line ?t:format("Test case timed out. "
+ "Trying to kill port program.~n"
+ " Executing: ~p~n", [Cmd]),
+ ?line case os:cmd(Cmd) of
+ [] ->
+ ok;
+ OsCmdRes ->
+ ?line ?t:format(" ~s", [OsCmdRes])
+ end;
+ {'DOWN', Ref, _, _, _} ->
+ %% OSProc is assumed to have terminated by itself
+ ?line ok
+ end.
+
+get_line(_Port, eol, Data) ->
+ ?line Data;
+get_line(Port, noeol, Data) ->
+ ?line receive
+ {Port, {data, {Flag, NextData}}} ->
+ ?line get_line(Port, Flag, Data ++ NextData);
+ {Port, eof} ->
+ ?line ?t:fail(port_prog_unexpectedly_closed)
+ end.
+
+read_case_data(Port, TestCase) ->
+ ?line receive
+ {Port, {data, {eol, [?SUCCESS_MARKER]}}} ->
+ ?line ok;
+ {Port, {data, {Flag, [?SUCCESS_MARKER | CommentStart]}}} ->
+ ?line {comment, get_line(Port, Flag, CommentStart)};
+ {Port, {data, {Flag, [?SKIPPED_MARKER | CommentStart]}}} ->
+ ?line {skipped, get_line(Port, Flag, CommentStart)};
+ {Port, {data, {Flag, [?FAILED_MARKER | ReasonStart]}}} ->
+ ?line ?t:fail(get_line(Port, Flag, ReasonStart));
+ {Port, {data, {eol, [?PID_MARKER | PidStr]}}} ->
+ ?line ?t:format("Port program pid: ~s~n", [PidStr]),
+ ?line CaseProc = self(),
+ ?line list_to_integer(PidStr), % Sanity check
+ spawn_opt(fun () ->
+ port_prog_killer(CaseProc, PidStr)
+ end,
+ [{priority, max}, link]),
+ read_case_data(Port, TestCase);
+ {Port, {data, {Flag, LineStart}}} ->
+ ?line ?t:format("~s~n", [get_line(Port, Flag, LineStart)]),
+ read_case_data(Port, TestCase);
+ {Port, eof} ->
+ ?line ?t:fail(port_prog_unexpectedly_closed)
+ end.
+
+run_case(Config) ->
+ run_case(Config, "").
+
+run_case(Config, TestArgs) ->
+ run_case(Config, TestArgs, fun (_Port) -> ok end).
+
+run_case(Config, TestArgs, Fun) ->
+ Test = atom_to_list(?config(testcase, Config)),
+ TestProg = filename:join([?config(data_dir, Config),
+ ?TESTPROG
+ ++ "."
+ ++ atom_to_list(erlang:system_info(threads))]),
+ Cmd = TestProg ++ " " ++ Test ++ " " ++ TestArgs,
+ case catch open_port({spawn, Cmd}, [stream,
+ use_stdio,
+ stderr_to_stdout,
+ eof,
+ {line, 1024}]) of
+ Port when is_port(Port) ->
+ ?line Fun(Port),
+ ?line CaseResult = read_case_data(Port, Test),
+ ?line receive
+ {Port, eof} ->
+ ?line ok
+ end,
+ ?line CaseResult;
+ Error ->
+ ?line ?t:fail({open_port_failed, Error})
+ end.
+
+
+-define(VERSION_MAGIC, 131).
+
+-define(ATOM_EXT, 100).
+-define(REFERENCE_EXT, 101).
+-define(PORT_EXT, 102).
+-define(PID_EXT, 103).
+-define(NEW_REFERENCE_EXT, 114).
+
+uint32_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 32 ->
+ [(Uint bsr 24) band 16#ff,
+ (Uint bsr 16) band 16#ff,
+ (Uint bsr 8) band 16#ff,
+ Uint band 16#ff];
+uint32_be(Uint) ->
+ exit({badarg, uint32_be, [Uint]}).
+
+
+uint16_be(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 16 ->
+ [(Uint bsr 8) band 16#ff,
+ Uint band 16#ff];
+uint16_be(Uint) ->
+ exit({badarg, uint16_be, [Uint]}).
+
+uint8(Uint) when is_integer(Uint), 0 =< Uint, Uint < 1 bsl 8 ->
+ Uint band 16#ff;
+uint8(Uint) ->
+ exit({badarg, uint8, [Uint]}).
+
+
+
+mk_pid({NodeName, Creation}, Number, Serial) when is_atom(NodeName) ->
+ mk_pid({atom_to_list(NodeName), Creation}, Number, Serial);
+mk_pid({NodeName, Creation}, Number, Serial) ->
+ case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
+ ?PID_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint32_be(Serial),
+ uint8(Creation)])) of
+ Pid when is_pid(Pid) ->
+ Pid;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_pid, [{NodeName, Creation}, Number, Serial]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
+ end.
+
+mk_port({NodeName, Creation}, Number) when is_atom(NodeName) ->
+ mk_port({atom_to_list(NodeName), Creation}, Number);
+mk_port({NodeName, Creation}, Number) ->
+ case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
+ ?PORT_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint8(Creation)])) of
+ Port when is_port(Port) ->
+ Port;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_port, [{NodeName, Creation}, Number]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
+ end.
+
+mk_ref({NodeName, Creation}, Numbers) when is_atom(NodeName),
+ is_integer(Creation),
+ is_list(Numbers) ->
+ mk_ref({atom_to_list(NodeName), Creation}, Numbers);
+mk_ref({NodeName, Creation}, [Number]) when is_list(NodeName),
+ is_integer(Creation),
+ is_integer(Number) ->
+ case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
+ ?REFERENCE_EXT,
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint32_be(Number),
+ uint8(Creation)])) of
+ Ref when is_reference(Ref) ->
+ Ref;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_ref, [{NodeName, Creation}, [Number]]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
+ end;
+mk_ref({NodeName, Creation}, Numbers) when is_list(NodeName),
+ is_integer(Creation),
+ is_list(Numbers) ->
+ case catch binary_to_term(list_to_binary([?VERSION_MAGIC,
+ ?NEW_REFERENCE_EXT,
+ uint16_be(length(Numbers)),
+ ?ATOM_EXT,
+ uint16_be(length(NodeName)),
+ NodeName,
+ uint8(Creation),
+ lists:map(fun (N) ->
+ uint32_be(N)
+ end,
+ Numbers)])) of
+ Ref when is_reference(Ref) ->
+ Ref;
+ {'EXIT', {badarg, _}} ->
+ exit({badarg, mk_ref, [{NodeName, Creation}, Numbers]});
+ Other ->
+ exit({unexpected_binary_to_term_result, Other})
+ end.
+
+my_cre() -> erlang:system_info(creation).
+
+oth_cre(0) -> 1;
+oth_cre(1) -> 2;
+oth_cre(2) -> 3;
+oth_cre(3) -> 1;
+oth_cre(N) -> exit({invalid_creation, N}).
+
+str_1_bsl_10000() ->
+ "19950631168807583848837421626835850838234968318861924548520089498529438830221946631919961684036194597899331129423209124271556491349413781117593785932096323957855730046793794526765246551266059895520550086918193311542508608460618104685509074866089624888090489894838009253941633257850621568309473902556912388065225096643874441046759871626985453222868538161694315775629640762836880760732228535091641476183956381458969463899410840960536267821064621427333394036525565649530603142680234969400335934316651459297773279665775606172582031407994198179607378245683762280037302885487251900834464581454650557929601414833921615734588139257095379769119277800826957735674444123062018757836325502728323789270710373802866393031428133241401624195671690574061419654342324638801248856147305207431992259611796250130992860241708340807605932320161268492288496255841312844061536738951487114256315111089745514203313820202931640957596464756010405845841566072044962867016515061920631004186422275908670900574606417856951911456055068251250406007519842261898059237118054444788072906395242548339221982707404473162376760846613033778706039803413197133493654622700563169937455508241780972810983291314403571877524768509857276937926433221599399876886660808368837838027643282775172273657572744784112294389733810861607423253291974813120197604178281965697475898164531258434135959862784130128185406283476649088690521047580882615823961985770122407044330583075869039319604603404973156583208672105913300903752823415539745394397715257455290510212310947321610753474825740775273986348298498340756937955646638621874569499279016572103701364433135817214311791398222983845847334440270964182851005072927748364550578634501100852987812389473928699540834346158807043959118985815145779177143619698728131459483783202081474982171858011389071228250905826817436220577475921417653715687725614904582904992461028630081535583308130101987675856234343538955409175623400844887526162643568648833519463720377293240094456246923254350400678027273837755376406726898636241037491410966718557050759098100246789880178271925953381282421954028302759408448955014676668389697996886241636313376393903373455801407636741877711055384225739499110186468219696581651485130494222369947714763069155468217682876200362777257723781365331611196811280792669481887201298643660768551639860534602297871557517947385246369446923087894265948217008051120322365496288169035739121368338393591756418733850510970271613915439590991598154654417336311656936031122249937969999226781732358023111862644575299135758175008199839236284615249881088960232244362173771618086357015468484058622329792853875623486556440536962622018963571028812361567512543338303270029097668650568557157505516727518899194129711337690149916181315171544007728650573189557450920330185304847113818315407324053319038462084036421763703911550639789000742853672196280903477974533320468368795868580237952218629120080742819551317948157624448298518461509704888027274721574688131594750409732115080498190455803416826949787141316063210686391511681774304792596709376".
diff --git a/erts/test/erl_print_SUITE_data/Makefile.src b/erts/test/erl_print_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..109d55e572
--- /dev/null
+++ b/erts/test/erl_print_SUITE_data/Makefile.src
@@ -0,0 +1,45 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2005-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%
+#
+
+include @erts_lib_include_internal_generated@@[email protected]
+
+CC = @CC@
+CFLAGS = @ERTS_CFLAGS@
+LIBS = @ERTS_LIBS@
+
+EPTF_CFLAGS = -Wall $(CFLAGS) @DEFS@ -I@erts_lib_include_internal@ -I@erts_lib_include_internal_generated@
+EPTF_LIBS = $(LIBS) -L@erts_lib_internal_path@ -lerts_internal@type_marker@
+
+EPTT_CFLAGS = -DTHREAD_SAFE $(ETHR_DEFS) $(EPTF_CFLAGS)
+EPTT_LIBS = $(LIBS) -L@erts_lib_internal_path@ -lerts_internal_r@type_marker@ $(ETHR_LIBS)
+
+GCC = .@DS@gccifier -CC"$(CC)"
+
+PROGS = erl_print_tests.@emu_threads@@exe@
+
+all: $(PROGS)
+
+gccifier@exe@: ..@DS@utils@[email protected]
+ $(CC) $(CFLAGS) -o gccifier@exe@ ..@DS@utils@[email protected] $(LIBS)
+
+erl_print_tests.false@exe@: gccifier@exe@ erl_print_tests.c
+ $(GCC) $(EPTF_CFLAGS) -o erl_print_tests.false@exe@ erl_print_tests.c $(EPTF_LIBS)
+
+erl_print_tests.true@exe@: gccifier@exe@ erl_print_tests.c
+ $(GCC) $(EPTT_CFLAGS) -o erl_print_tests.true@exe@ erl_print_tests.c $(EPTT_LIBS)
diff --git a/erts/test/erl_print_SUITE_data/character_test.h b/erts/test/erl_print_SUITE_data/character_test.h
new file mode 100644
index 0000000000..9c66618a71
--- /dev/null
+++ b/erts/test/erl_print_SUITE_data/character_test.h
@@ -0,0 +1,586 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2005-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%
+ */
+
+/*
+ * This file has been automatically generated. Do NOT edit it; instead,
+ * run 'erl_print_tests.false character save_expected_result'
+ */
+
+char *character_expected_result[] = {
+ "a",
+ "a ",
+ " a",
+ "a ",
+ " a",
+ "b",
+ "b ",
+ " b",
+ "b ",
+ " b",
+ "c",
+ "c ",
+ " c",
+ "c ",
+ " c",
+ "d",
+ "d ",
+ " d",
+ "d ",
+ " d",
+ "e",
+ "e ",
+ " e",
+ "e ",
+ " e",
+ "f",
+ "f ",
+ " f",
+ "f ",
+ " f",
+ "g",
+ "g ",
+ " g",
+ "g ",
+ " g",
+ "h",
+ "h ",
+ " h",
+ "h ",
+ " h",
+ "i",
+ "i ",
+ " i",
+ "i ",
+ " i",
+ "j",
+ "j ",
+ " j",
+ "j ",
+ " j",
+ "k",
+ "k ",
+ " k",
+ "k ",
+ " k",
+ "l",
+ "l ",
+ " l",
+ "l ",
+ " l",
+ "m",
+ "m ",
+ " m",
+ "m ",
+ " m",
+ "n",
+ "n ",
+ " n",
+ "n ",
+ " n",
+ "o",
+ "o ",
+ " o",
+ "o ",
+ " o",
+ "p",
+ "p ",
+ " p",
+ "p ",
+ " p",
+ "q",
+ "q ",
+ " q",
+ "q ",
+ " q",
+ "r",
+ "r ",
+ " r",
+ "r ",
+ " r",
+ "s",
+ "s ",
+ " s",
+ "s ",
+ " s",
+ "t",
+ "t ",
+ " t",
+ "t ",
+ " t",
+ "u",
+ "u ",
+ " u",
+ "u ",
+ " u",
+ "v",
+ "v ",
+ " v",
+ "v ",
+ " v",
+ "w",
+ "w ",
+ " w",
+ "w ",
+ " w",
+ "x",
+ "x ",
+ " x",
+ "x ",
+ " x",
+ "y",
+ "y ",
+ " y",
+ "y ",
+ " y",
+ "z",
+ "z ",
+ " z",
+ "z ",
+ " z",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "A",
+ "A ",
+ " A",
+ "A ",
+ " A",
+ "B",
+ "B ",
+ " B",
+ "B ",
+ " B",
+ "C",
+ "C ",
+ " C",
+ "C ",
+ " C",
+ "D",
+ "D ",
+ " D",
+ "D ",
+ " D",
+ "E",
+ "E ",
+ " E",
+ "E ",
+ " E",
+ "F",
+ "F ",
+ " F",
+ "F ",
+ " F",
+ "G",
+ "G ",
+ " G",
+ "G ",
+ " G",
+ "H",
+ "H ",
+ " H",
+ "H ",
+ " H",
+ "I",
+ "I ",
+ " I",
+ "I ",
+ " I",
+ "J",
+ "J ",
+ " J",
+ "J ",
+ " J",
+ "K",
+ "K ",
+ " K",
+ "K ",
+ " K",
+ "L",
+ "L ",
+ " L",
+ "L ",
+ " L",
+ "M",
+ "M ",
+ " M",
+ "M ",
+ " M",
+ "N",
+ "N ",
+ " N",
+ "N ",
+ " N",
+ "O",
+ "O ",
+ " O",
+ "O ",
+ " O",
+ "P",
+ "P ",
+ " P",
+ "P ",
+ " P",
+ "Q",
+ "Q ",
+ " Q",
+ "Q ",
+ " Q",
+ "R",
+ "R ",
+ " R",
+ "R ",
+ " R",
+ "S",
+ "S ",
+ " S",
+ "S ",
+ " S",
+ "T",
+ "T ",
+ " T",
+ "T ",
+ " T",
+ "U",
+ "U ",
+ " U",
+ "U ",
+ " U",
+ "V",
+ "V ",
+ " V",
+ "V ",
+ " V",
+ "X",
+ "X ",
+ " X",
+ "X ",
+ " X",
+ "Y",
+ "Y ",
+ " Y",
+ "Y ",
+ " Y",
+ "Z",
+ "Z ",
+ " Z",
+ "Z ",
+ " Z",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "1",
+ "1 ",
+ " 1",
+ "1 ",
+ " 1",
+ "2",
+ "2 ",
+ " 2",
+ "2 ",
+ " 2",
+ "3",
+ "3 ",
+ " 3",
+ "3 ",
+ " 3",
+ "4",
+ "4 ",
+ " 4",
+ "4 ",
+ " 4",
+ "5",
+ "5 ",
+ " 5",
+ "5 ",
+ " 5",
+ "6",
+ "6 ",
+ " 6",
+ "6 ",
+ " 6",
+ "7",
+ "7 ",
+ " 7",
+ "7 ",
+ " 7",
+ "8",
+ "8 ",
+ " 8",
+ "8 ",
+ " 8",
+ "9",
+ "9 ",
+ " 9",
+ "9 ",
+ " 9",
+ "0",
+ "0 ",
+ " 0",
+ "0 ",
+ " 0",
+ "(",
+ "( ",
+ " (",
+ "( ",
+ " (",
+ ")",
+ ") ",
+ " )",
+ ") ",
+ " )",
+ "[",
+ "[ ",
+ " [",
+ "[ ",
+ " [",
+ "]",
+ "] ",
+ " ]",
+ "] ",
+ " ]",
+ "{",
+ "{ ",
+ " {",
+ "{ ",
+ " {",
+ "}",
+ "} ",
+ " }",
+ "} ",
+ " }",
+ "+",
+ "+ ",
+ " +",
+ "+ ",
+ " +",
+ "-",
+ "- ",
+ " -",
+ "- ",
+ " -",
+ ";",
+ "; ",
+ " ;",
+ "; ",
+ " ;",
+ ",",
+ ", ",
+ " ,",
+ ", ",
+ " ,",
+ ":",
+ ": ",
+ " :",
+ ": ",
+ " :",
+ ".",
+ ". ",
+ " .",
+ ". ",
+ " .",
+ "@",
+ "@ ",
+ " @",
+ "@ ",
+ " @",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "$",
+ "$ ",
+ " $",
+ "$ ",
+ " $",
+ "!",
+ "! ",
+ " !",
+ "! ",
+ " !",
+ "\"",
+ "\" ",
+ " \"",
+ "\" ",
+ " \"",
+ "#",
+ "# ",
+ " #",
+ "# ",
+ " #",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "%",
+ "% ",
+ " %",
+ "% ",
+ " %",
+ "&",
+ "& ",
+ " &",
+ "& ",
+ " &",
+ "/",
+ "/ ",
+ " /",
+ "/ ",
+ " /",
+ "\\",
+ "\\ ",
+ " \\",
+ "\\ ",
+ " \\",
+ "=",
+ "= ",
+ " =",
+ "= ",
+ " =",
+ "?",
+ "? ",
+ " ?",
+ "? ",
+ " ?",
+ "'",
+ "' ",
+ " '",
+ "' ",
+ " '",
+ "`",
+ "` ",
+ " `",
+ "` ",
+ " `",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "^",
+ "^ ",
+ " ^",
+ "^ ",
+ " ^",
+ "~",
+ "~ ",
+ " ~",
+ "~ ",
+ " ~",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "|",
+ "| ",
+ " |",
+ "| ",
+ " |",
+ "<",
+ "< ",
+ " <",
+ "< ",
+ " <",
+ ">",
+ "> ",
+ " >",
+ "> ",
+ " >",
+ "�",
+ "� ",
+ " �",
+ "� ",
+ " �",
+ "*",
+ "* ",
+ " *",
+ "* ",
+ " *",
+ "_",
+ "_ ",
+ " _",
+ "_ ",
+ " _",
+ "\a",
+ "\a ",
+ " \a",
+ "\a ",
+ " \a",
+ "\b",
+ "\b ",
+ " \b",
+ "\b ",
+ " \b",
+ "\f",
+ "\f ",
+ " \f",
+ "\f ",
+ " \f",
+ "\n",
+ "\n ",
+ " \n",
+ "\n ",
+ " \n",
+ "\r",
+ "\r ",
+ " \r",
+ "\r ",
+ " \r",
+ "\t",
+ "\t ",
+ " \t",
+ "\t ",
+ " \t",
+ "\v",
+ "\v ",
+ " \v",
+ "\v ",
+ " \v",
+ NULL};
diff --git a/erts/test/erl_print_SUITE_data/erl_print_tests.c b/erts/test/erl_print_SUITE_data/erl_print_tests.c
new file mode 100644
index 0000000000..28ce78f4e1
--- /dev/null
+++ b/erts/test/erl_print_SUITE_data/erl_print_tests.c
@@ -0,0 +1,560 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2005-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%
+ */
+
+/*
+ * Description: Test suite for the ethread thread library.
+ * Author: Rickard Green
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <limits.h>
+#include <float.h>
+#ifndef __WIN32__
+#include <unistd.h>
+#endif
+
+#include "erl_printf.h"
+#ifdef THREAD_SAFE
+#include "ethread.h"
+#endif
+
+#ifdef __WIN32__
+#undef HAVE_VSNPRINTF
+#define HAVE_VSNPRINTF 1
+#define vsnprintf _vsnprintf
+#endif
+
+#ifdef __WIN32__
+#define signed_long_long LONGLONG
+#define unsigned_long_long ULONGLONG
+#else
+#define signed_long_long signed long long
+#define unsigned_long_long unsigned long long
+#endif
+
+/*
+ * Auxiliary functions
+ */
+
+#define PRINT_VA_LIST(FRMT) \
+do { \
+ if (FRMT && FRMT != '\0') { \
+ va_list args; \
+ va_start(args, FRMT); \
+ vfprintf(stderr, FRMT, args); \
+ va_end(args); \
+ } \
+} while (0)
+
+#define ASSERT(B) \
+do { \
+ if (!(B)) \
+ fail("%s:%d: Assertion \"%s\" failed!",__FILE__,__LINE__,#B); \
+} while (0)
+
+static void
+print_eol(void)
+{
+ fprintf(stderr, "\n");
+}
+
+static void print_line(char *frmt,...)
+{
+ PRINT_VA_LIST(frmt);
+ print_eol();
+}
+
+static void print(char *frmt,...)
+{
+ PRINT_VA_LIST(frmt);
+}
+
+static void fail(char *frmt,...)
+{
+ char *abrt_env;
+ print_eol();
+ fprintf(stderr, "EP-TEST-FAILURE");
+ PRINT_VA_LIST(frmt);
+ print_eol();
+ abrt_env = getenv("ERL_ABORT_ON_FAILURE");
+ if (abrt_env && strcmp("true", abrt_env) == 0)
+ abort();
+ else
+ exit(1);
+}
+
+static void skip(char *frmt,...)
+{
+ print_eol();
+ fprintf(stderr, "EP-TEST-SKIP");
+ PRINT_VA_LIST(frmt);
+ print_eol();
+ exit(0);
+}
+
+static void succeed(char *frmt,...)
+{
+ print_eol();
+ fprintf(stderr, "EP-TEST-SUCCESS");
+ PRINT_VA_LIST(frmt);
+ print_eol();
+ exit(0);
+}
+
+#if 0 /* Not used */
+
+static void
+do_sleep(unsigned secs)
+{
+#ifdef __WIN32__
+ Sleep((DWORD) secs*1000);
+#else
+ sleep(secs);
+#endif
+}
+
+#endif
+
+static void
+send_my_pid(void)
+{
+#ifndef __WIN32__
+ int pid = (int) getpid();
+ fprintf(stderr, "\nEP-TEST-PID%d\n", pid);
+#endif
+}
+
+#define BUF_SIZE (1024*1024)
+
+FILE *outfile = NULL;
+char **expected_result;
+
+#define FENCE_SIZE 512
+static void
+print_cmp_test(int n, char *frmt, ...)
+{
+ int res = -1;
+ static char clib_buf[BUF_SIZE];
+ static unsigned char the_erts_buf[BUF_SIZE];
+ char *erts_buf = (char *) &the_erts_buf[FENCE_SIZE];
+ va_list args;
+
+ if (outfile) {
+ char *fp, *tp;
+ va_start(args, frmt);
+ if (n < 0)
+ res = vsprintf(erts_buf, frmt, args);
+ else {
+#ifdef HAVE_VSNPRINTF
+ res = vsnprintf(erts_buf, (size_t) n, frmt, args);
+#else
+ fail("No vsnprintf()");
+#endif
+ }
+ va_end(args);
+ ASSERT(res >= 0);
+ fp = erts_buf;
+ tp = clib_buf;
+ while (*fp) {
+ switch (*fp) {
+ case '\a': *(tp++) = '\\'; *(tp++) = 'a'; break;
+ case '\b': *(tp++) = '\\'; *(tp++) = 'b'; break;
+ case '\f': *(tp++) = '\\'; *(tp++) = 'f'; break;
+ case '\n': *(tp++) = '\\'; *(tp++) = 'n'; break;
+ case '\r': *(tp++) = '\\'; *(tp++) = 'r'; break;
+ case '\t': *(tp++) = '\\'; *(tp++) = 't'; break;
+ case '\v': *(tp++) = '\\'; *(tp++) = 'v'; break;
+ case '\"': *(tp++) = '\\'; *(tp++) = '\"'; break;
+ case '\\': *(tp++) = '\\'; *(tp++) = '\\'; break;
+ default: *(tp++) = *fp; break;
+ }
+ fp++;
+ }
+ *tp = '\0';
+ res = fprintf(outfile, "\t\"%s\",\n", clib_buf);
+ ASSERT(res >= 0);
+ }
+ else {
+ char *xres;
+ va_start(args, frmt);
+ if (n < 0)
+ res = erts_vsprintf(erts_buf, frmt, args);
+ else {
+ int i;
+ int chk_sz = 2*FENCE_SIZE + n;
+ for (i = 0; i < chk_sz; i++)
+ the_erts_buf[i] = 0xeb;
+ res = erts_vsnprintf(erts_buf, (size_t) n, frmt, args);
+ for (i = 0; i < chk_sz; i++)
+ if ((((char *) &the_erts_buf[i]) < erts_buf
+ || erts_buf + n <= ((char *) &the_erts_buf[i]))
+ && the_erts_buf[i] != 0xeb) {
+ int j;
+ for (j = 0; j < chk_sz; j++)
+ print(j ? ",%x(%d)" : "%x(%d)",
+ (unsigned) the_erts_buf[j], j - FENCE_SIZE);
+ print_eol();
+ fail("Garbage written out of bounds (%d,%d)",
+ i - FENCE_SIZE, n);
+ }
+ }
+ va_end(args);
+ ASSERT(res >= 0);
+
+ if (expected_result) {
+ ASSERT(*expected_result);
+ xres = *expected_result;
+ expected_result++;
+ }
+ else {
+ va_start(args, frmt);
+ if (n < 0)
+ res = vsprintf(clib_buf, frmt, args);
+ else {
+#ifdef HAVE_VSNPRINTF
+ res = vsnprintf(clib_buf, (size_t) n, frmt, args);
+#else
+ fail("No vsnprintf()");
+#endif
+ }
+ va_end(args);
+ ASSERT(res >= 0);
+ xres = clib_buf;
+ }
+
+ if (strcmp(xres, erts_buf) != 0) {
+ print_line("expected result : \"%s\"", xres);
+ print_line("erts_buf : \"%s\"", erts_buf);
+ fail("\"%s\" != \"%s\" (format=\"%s\")", xres, erts_buf, frmt);
+ }
+
+ print_line("Checked format \"%s\" with result: \"%s\"", frmt, erts_buf);
+ }
+}
+
+/*
+ * The test-cases
+ */
+
+#include "integer_64_test.h"
+#include "integer_test.h"
+
+#define INT_SUB_BATCH_TEST(FRMT, TYPE) \
+ print_cmp_test(-1, FRMT, ((TYPE) 4711)); \
+ print_cmp_test(-1, FRMT, ~((TYPE) 4711)); \
+ print_cmp_test(-1, FRMT, (~((TYPE) 0))/2 + (~((TYPE) 0))/4);\
+ print_cmp_test(-1, FRMT, ((TYPE) - 1)); \
+ print_cmp_test(-1, FRMT, ((TYPE) 1)); \
+ print_cmp_test(-1, FRMT, ((TYPE) ((long) 0xabcdef01))); \
+
+#define INT_BATCH_TEST(P, X, S) \
+ print_line("%s:%d",__FILE__,__LINE__); \
+ INT_SUB_BATCH_TEST("%" P "h" X, S char); \
+ INT_SUB_BATCH_TEST("%" P "h" X, S short); \
+ INT_SUB_BATCH_TEST("%" P X, S int); \
+ INT_SUB_BATCH_TEST("%" P "l" X, S long); \
+ INT_SUB_BATCH_TEST("%" P "ll" X, S ## _long_long); \
+
+static void
+integer_test(void)
+{
+ /* This testcase should be rewritten. It assumes the following
+ sizes of types... */
+ if (sizeof(char) != 1
+ || sizeof(short) != 2
+ || sizeof(int) != 4
+ || sizeof(long) != (sizeof(void *) == 8 ? 8 : 4)
+ || sizeof(signed_long_long) != 8)
+ skip("Unexpected size of primitive datatype:"
+ " sizeof(char) == %d (expected 1);"
+ " sizeof(short) == %d (expected 2);"
+ " sizeof(int) == %d (expected 4);"
+ " sizeof(long) == %d (expected %d);"
+ " sizeof(signed_long_long) == %d (expected 8)",
+ sizeof(char),
+ sizeof(short),
+ sizeof(int),
+ sizeof(long), sizeof(void *) == 8 ? 8 : 4,
+ sizeof(signed_long_long));
+
+ expected_result = (sizeof(void *) == 8
+ ? integer_64_expected_result
+ : integer_expected_result);
+
+ INT_BATCH_TEST("", "i", signed);
+ INT_BATCH_TEST("", "d", signed);
+ INT_BATCH_TEST("", "u", unsigned);
+ INT_BATCH_TEST("", "o", unsigned);
+ INT_BATCH_TEST("", "x", unsigned);
+ INT_BATCH_TEST("", "X", unsigned);
+ INT_BATCH_TEST("010.5", "i", signed);
+ INT_BATCH_TEST("010.5", "d", signed);
+ INT_BATCH_TEST("010.5", "u", unsigned);
+ INT_BATCH_TEST("010.5", "o", unsigned);
+ INT_BATCH_TEST("010.5", "x", unsigned);
+ INT_BATCH_TEST("010.5", "X", unsigned);
+ INT_BATCH_TEST("-+29", "i", signed);
+ INT_BATCH_TEST("-+29", "d", signed);
+ INT_BATCH_TEST("-29", "u", unsigned);
+ INT_BATCH_TEST("-29", "o", unsigned);
+ INT_BATCH_TEST("-29", "x", unsigned);
+ INT_BATCH_TEST("-29", "X", unsigned);
+ INT_BATCH_TEST("22.8", "i", signed);
+ INT_BATCH_TEST("22.8", "d", signed);
+ INT_BATCH_TEST("22.8", "u", unsigned);
+ INT_BATCH_TEST("22.8", "o", unsigned);
+ INT_BATCH_TEST("22.8", "x", unsigned);
+ INT_BATCH_TEST("22.8", "X", unsigned);
+ INT_BATCH_TEST("-22.8", "i", signed);
+ INT_BATCH_TEST("-22.8", "d", signed);
+ INT_BATCH_TEST("-22.8", "u", unsigned);
+ INT_BATCH_TEST("-22.8", "o", unsigned);
+ INT_BATCH_TEST("-22.8", "x", unsigned);
+ INT_BATCH_TEST("-22.8", "X", unsigned);
+ INT_BATCH_TEST("-823.193", "i", signed);
+ INT_BATCH_TEST("-823.193", "d", signed);
+ INT_BATCH_TEST("-823.193", "u", unsigned);
+ INT_BATCH_TEST("-823.193", "o", unsigned);
+ INT_BATCH_TEST("-823.193", "x", unsigned);
+ INT_BATCH_TEST("-823.193", "X", unsigned);
+
+}
+
+static void
+float_test(void)
+{
+ expected_result = NULL;
+ print_cmp_test(-1, "%70.10f", DBL_MAX);
+ print_cmp_test(-1, "%500.10f", DBL_MAX);
+ print_cmp_test(-1, "%-500.10f", DBL_MAX);
+ print_cmp_test(-1, "%500.10e", DBL_MAX);
+ print_cmp_test(-1, "%-500.10e", DBL_MAX);
+ print_cmp_test(-1, "%500.10E", DBL_MAX);
+ print_cmp_test(-1, "%-500.10E", DBL_MAX);
+ print_cmp_test(-1, "%500.10g", DBL_MAX);
+ print_cmp_test(-1, "%-500.10g", DBL_MAX);
+ print_cmp_test(-1, "%500.10G", DBL_MAX);
+ print_cmp_test(-1, "%-500.10G", DBL_MAX);
+}
+
+char some_characters[] =
+"abcdefghijklmnopqrstuvwxyz���"
+"ABCDEFGHIJKLMNOPQRSTUVXYZ���"
+"1234567890"
+"()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_"
+"\a\b\f\n\r\t\v";
+
+#include "string_test.h"
+
+static void
+string_test(void)
+{
+ expected_result = string_expected_result;
+ print_cmp_test(-1, "%s", "hej");
+ print_cmp_test(-1, "%-10.5s", "hopp");
+ print_cmp_test(-1, "%10.5s", "hopp");
+ print_cmp_test(-1, "%-500.500s", "hopp");
+ print_cmp_test(-1, "%500.500s", "hopp");
+ print_cmp_test(-1, "\t%10.4s", some_characters);
+ print_cmp_test(-1, "\t%500.500s", some_characters);
+}
+
+#include "character_test.h"
+
+static void
+character_test(void)
+{
+ char *cp;
+ expected_result = character_expected_result;
+ for (cp = some_characters; *cp; cp++) {
+ print_cmp_test(-1, "%c", *cp);
+ print_cmp_test(-1, "%-10.5c", *cp);
+ print_cmp_test(-1, "%10.5c", *cp);
+ print_cmp_test(-1, "%-500.500c", *cp);
+ print_cmp_test(-1, "%500.500c", *cp);
+ }
+}
+
+#include "snprintf_test.h"
+
+static void
+snprintf_test(void)
+{
+ expected_result = snprintf_expected_result;
+ print_cmp_test(6, "hej hopp");
+ print_cmp_test(7, "hej hopp");
+ print_cmp_test(8, "hej hopp");
+ print_cmp_test(9, "hej hopp");
+ print_cmp_test(10, "hej hopp");
+ print_cmp_test(6, "hej %d", 4711);
+ print_cmp_test(7, "hej %d", 4711);
+ print_cmp_test(8, "hej %d", 4711);
+ print_cmp_test(9, "hej %d", 4711);
+ print_cmp_test(10, "hej %d", 4711);
+ print_cmp_test(sizeof(some_characters)-2, "%s", some_characters);
+ print_cmp_test(sizeof(some_characters)-1, "%s", some_characters);
+ print_cmp_test(sizeof(some_characters), "%s", some_characters);
+ print_cmp_test(sizeof(some_characters)+1, "%s", some_characters);
+ print_cmp_test(sizeof(some_characters)+2, "%s", some_characters);
+ print_cmp_test(sizeof(some_characters)/2, "%s%s",
+ some_characters, some_characters);
+ print_cmp_test(sizeof(some_characters)*3, "%s%s",
+ some_characters, some_characters);
+}
+
+static void
+quote_test(void)
+{
+ expected_result = NULL;
+ print_cmp_test(-1, "\n");
+ print_cmp_test(-1, "\\n");
+ print_cmp_test(-1, "\r");
+ print_cmp_test(-1, "\\r");
+ print_cmp_test(-1, "\t");
+ print_cmp_test(-1, "\\t");
+ print_cmp_test(-1, "\v");
+ print_cmp_test(-1, "\\v");
+ print_cmp_test(-1, "\b");
+ print_cmp_test(-1, "\\b");
+ print_cmp_test(-1, "\f");
+ print_cmp_test(-1, "\\f");
+ print_cmp_test(-1, "\x80");
+ print_cmp_test(-1, "\\x80");
+ print_cmp_test(-1, "\x14");
+ print_cmp_test(-1, "\\x14");
+ print_cmp_test(-1, "\xff");
+ print_cmp_test(-1, "\\xff");
+ print_cmp_test(-1, "\043");
+ print_cmp_test(-1, "\\043");
+ print_cmp_test(-1, "\053");
+ print_cmp_test(-1, "\\053");
+ print_cmp_test(-1, "\0143");
+ print_cmp_test(-1, "\\0143");
+ print_cmp_test(-1, "\\lf");
+ print_cmp_test(-1, "\\msss");
+ print_cmp_test(-1, "\\ss");
+
+}
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * The dispatcher *
+\* */
+
+int
+main(int argc, char *argv[])
+{
+ if (argc < 2)
+ fail("To few arguments for test case");
+
+ {
+ char *testcase;
+ int save_xres = 0;
+ int i;
+
+ send_my_pid();
+
+ testcase = argv[1];
+#ifdef THREAD_SAFE
+ {
+ int res = ethr_init(NULL);
+ if (res != 0)
+ fail("Failed to initialize the ethread library");
+ }
+#endif
+
+ for (i = 2; i < argc; i++) {
+ if (strcmp(argv[i], "save_expected_result") == 0) {
+ save_xres = 1;
+ break;
+ }
+ }
+
+ if (save_xres) {
+ char filename[100];
+ sprintf(filename,
+ "%s%s_test.h",
+ testcase,
+ sizeof(void *) == 8 ? "_64" : "");
+ printf("Saving expected result to %s\n", filename);
+ outfile = fopen(filename, "w");
+ ASSERT(outfile);
+ fprintf(outfile,
+ "/*\n"
+ " * %%CopyrightBegin%%\n"
+ " * Copyright Ericsson AB 1996-2009. All Rights Reserved.\n"
+ " * \n"
+ " * The contents of this file are subject to the Erlang Public License,\n"
+ " * Version 1.1, (the \"License\"); you may not use this file except in\n"
+ " * compliance with the License. You should have received a copy of the\n"
+ " * Erlang Public License along with this software. If not, it can be\n"
+ " * retrieved online at http://www.erlang.org/.\n"
+ " * \n"
+ " * Software distributed under the License is distributed on an \"AS IS\"\n"
+ " * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See\n"
+ " * the License for the specific language governing rights and limitations\n"
+ " * under the License.\n"
+ " * %%CopyrightEnd%%\n"
+ " */\n"
+ "\n");
+ fprintf(outfile,
+ "/* \n"
+ " * This file has been automatically generated. Do NOT edit it; instead,\n"
+ " * run '%s %s save_expected_result'%s.\n"
+ " */\n"
+ "\n",
+ argv[0],
+ testcase,
+ sizeof(void *) == 8 ? " on a 64-bit machine" : "");
+ fprintf(outfile,
+ "char *%s%s_expected_result[] = {\n",
+ testcase,
+ sizeof(void *) == 8 ? "_64" : "");
+ }
+
+ if (strcmp("integer", testcase) == 0)
+ integer_test();
+ else if (strcmp("float", testcase) == 0)
+ float_test();
+ else if (strcmp("string", testcase) == 0)
+ string_test();
+ else if (strcmp("character", testcase) == 0)
+ character_test();
+ else if (strcmp("snprintf", testcase) == 0)
+ snprintf_test();
+ else if (strcmp("quote", testcase) == 0)
+ quote_test();
+ else if (!save_xres)
+ skip("Test case \"%s\" not implemented yet", testcase);
+
+ if (save_xres) {
+ fprintf(outfile, "\tNULL};\n");
+ fclose(outfile);
+ }
+
+ succeed(NULL);
+ }
+
+ return 0;
+}
+
+
+
diff --git a/erts/test/erl_print_SUITE_data/integer_64_test.h b/erts/test/erl_print_SUITE_data/integer_64_test.h
new file mode 100644
index 0000000000..0df09ded44
--- /dev/null
+++ b/erts/test/erl_print_SUITE_data/integer_64_test.h
@@ -0,0 +1,1106 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2005-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%
+ */
+
+/*
+ * This file has been automatically generated. Do NOT edit it; instead,
+ * run 'erl_print_tests.true integer save_expected_result' on a 64-bit machine.
+ */
+
+char *integer_64_expected_result[] = {
+ "103",
+ "-104",
+ "0",
+ "-1",
+ "1",
+ "1",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-4351",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-1412567295",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "2882400001",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "2882400001",
+ "103",
+ "-104",
+ "0",
+ "-1",
+ "1",
+ "1",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-4351",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-1412567295",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "2882400001",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "2882400001",
+ "103",
+ "65432",
+ "0",
+ "255",
+ "1",
+ "1",
+ "4711",
+ "60824",
+ "0",
+ "65535",
+ "1",
+ "61185",
+ "4711",
+ "4294962584",
+ "3221225470",
+ "4294967295",
+ "1",
+ "2882400001",
+ "4711",
+ "18446744073709546904",
+ "13835058055282163710",
+ "18446744073709551615",
+ "1",
+ "2882400001",
+ "4711",
+ "18446744073709546904",
+ "13835058055282163710",
+ "18446744073709551615",
+ "1",
+ "2882400001",
+ "147",
+ "177630",
+ "0",
+ "377",
+ "1",
+ "1",
+ "11147",
+ "166630",
+ "0",
+ "177777",
+ "1",
+ "167401",
+ "11147",
+ "37777766630",
+ "27777777776",
+ "37777777777",
+ "1",
+ "25363367401",
+ "11147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ "1",
+ "25363367401",
+ "11147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ "1",
+ "25363367401",
+ "67",
+ "ff98",
+ "0",
+ "ff",
+ "1",
+ "1",
+ "1267",
+ "ed98",
+ "0",
+ "ffff",
+ "1",
+ "ef01",
+ "1267",
+ "ffffed98",
+ "bffffffe",
+ "ffffffff",
+ "1",
+ "abcdef01",
+ "1267",
+ "ffffffffffffed98",
+ "bffffffffffffffe",
+ "ffffffffffffffff",
+ "1",
+ "abcdef01",
+ "1267",
+ "ffffffffffffed98",
+ "bffffffffffffffe",
+ "ffffffffffffffff",
+ "1",
+ "abcdef01",
+ "67",
+ "FF98",
+ "0",
+ "FF",
+ "1",
+ "1",
+ "1267",
+ "ED98",
+ "0",
+ "FFFF",
+ "1",
+ "EF01",
+ "1267",
+ "FFFFED98",
+ "BFFFFFFE",
+ "FFFFFFFF",
+ "1",
+ "ABCDEF01",
+ "1267",
+ "FFFFFFFFFFFFED98",
+ "BFFFFFFFFFFFFFFE",
+ "FFFFFFFFFFFFFFFF",
+ "1",
+ "ABCDEF01",
+ "1267",
+ "FFFFFFFFFFFFED98",
+ "BFFFFFFFFFFFFFFE",
+ "FFFFFFFFFFFFFFFF",
+ "1",
+ "ABCDEF01",
+ " 00103",
+ " -00104",
+ " 00000",
+ " -00001",
+ " 00001",
+ " 00001",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ " -04351",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "-1412567295",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "2882400001",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "2882400001",
+ " 00103",
+ " -00104",
+ " 00000",
+ " -00001",
+ " 00001",
+ " 00001",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ " -04351",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "-1412567295",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "2882400001",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "2882400001",
+ " 00103",
+ " 65432",
+ " 00000",
+ " 00255",
+ " 00001",
+ " 00001",
+ " 04711",
+ " 60824",
+ " 00000",
+ " 65535",
+ " 00001",
+ " 61185",
+ " 04711",
+ "4294962584",
+ "3221225470",
+ "4294967295",
+ " 00001",
+ "2882400001",
+ " 04711",
+ "18446744073709546904",
+ "13835058055282163710",
+ "18446744073709551615",
+ " 00001",
+ "2882400001",
+ " 04711",
+ "18446744073709546904",
+ "13835058055282163710",
+ "18446744073709551615",
+ " 00001",
+ "2882400001",
+ " 00147",
+ " 177630",
+ " 00000",
+ " 00377",
+ " 00001",
+ " 00001",
+ " 11147",
+ " 166630",
+ " 00000",
+ " 177777",
+ " 00001",
+ " 167401",
+ " 11147",
+ "37777766630",
+ "27777777776",
+ "37777777777",
+ " 00001",
+ "25363367401",
+ " 11147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ " 00001",
+ "25363367401",
+ " 11147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ " 00001",
+ "25363367401",
+ " 00067",
+ " 0ff98",
+ " 00000",
+ " 000ff",
+ " 00001",
+ " 00001",
+ " 01267",
+ " 0ed98",
+ " 00000",
+ " 0ffff",
+ " 00001",
+ " 0ef01",
+ " 01267",
+ " ffffed98",
+ " bffffffe",
+ " ffffffff",
+ " 00001",
+ " abcdef01",
+ " 01267",
+ "ffffffffffffed98",
+ "bffffffffffffffe",
+ "ffffffffffffffff",
+ " 00001",
+ " abcdef01",
+ " 01267",
+ "ffffffffffffed98",
+ "bffffffffffffffe",
+ "ffffffffffffffff",
+ " 00001",
+ " abcdef01",
+ " 00067",
+ " 0FF98",
+ " 00000",
+ " 000FF",
+ " 00001",
+ " 00001",
+ " 01267",
+ " 0ED98",
+ " 00000",
+ " 0FFFF",
+ " 00001",
+ " 0EF01",
+ " 01267",
+ " FFFFED98",
+ " BFFFFFFE",
+ " FFFFFFFF",
+ " 00001",
+ " ABCDEF01",
+ " 01267",
+ "FFFFFFFFFFFFED98",
+ "BFFFFFFFFFFFFFFE",
+ "FFFFFFFFFFFFFFFF",
+ " 00001",
+ " ABCDEF01",
+ " 01267",
+ "FFFFFFFFFFFFED98",
+ "BFFFFFFFFFFFFFFE",
+ "FFFFFFFFFFFFFFFF",
+ " 00001",
+ " ABCDEF01",
+ "+103 ",
+ "-104 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "+1 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-4351 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-1412567295 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "+2882400001 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "+2882400001 ",
+ "+103 ",
+ "-104 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "+1 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-4351 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-1412567295 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "+2882400001 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "+2882400001 ",
+ "103 ",
+ "65432 ",
+ "0 ",
+ "255 ",
+ "1 ",
+ "1 ",
+ "4711 ",
+ "60824 ",
+ "0 ",
+ "65535 ",
+ "1 ",
+ "61185 ",
+ "4711 ",
+ "4294962584 ",
+ "3221225470 ",
+ "4294967295 ",
+ "1 ",
+ "2882400001 ",
+ "4711 ",
+ "18446744073709546904 ",
+ "13835058055282163710 ",
+ "18446744073709551615 ",
+ "1 ",
+ "2882400001 ",
+ "4711 ",
+ "18446744073709546904 ",
+ "13835058055282163710 ",
+ "18446744073709551615 ",
+ "1 ",
+ "2882400001 ",
+ "147 ",
+ "177630 ",
+ "0 ",
+ "377 ",
+ "1 ",
+ "1 ",
+ "11147 ",
+ "166630 ",
+ "0 ",
+ "177777 ",
+ "1 ",
+ "167401 ",
+ "11147 ",
+ "37777766630 ",
+ "27777777776 ",
+ "37777777777 ",
+ "1 ",
+ "25363367401 ",
+ "11147 ",
+ "1777777777777777766630 ",
+ "1377777777777777777776 ",
+ "1777777777777777777777 ",
+ "1 ",
+ "25363367401 ",
+ "11147 ",
+ "1777777777777777766630 ",
+ "1377777777777777777776 ",
+ "1777777777777777777777 ",
+ "1 ",
+ "25363367401 ",
+ "67 ",
+ "ff98 ",
+ "0 ",
+ "ff ",
+ "1 ",
+ "1 ",
+ "1267 ",
+ "ed98 ",
+ "0 ",
+ "ffff ",
+ "1 ",
+ "ef01 ",
+ "1267 ",
+ "ffffed98 ",
+ "bffffffe ",
+ "ffffffff ",
+ "1 ",
+ "abcdef01 ",
+ "1267 ",
+ "ffffffffffffed98 ",
+ "bffffffffffffffe ",
+ "ffffffffffffffff ",
+ "1 ",
+ "abcdef01 ",
+ "1267 ",
+ "ffffffffffffed98 ",
+ "bffffffffffffffe ",
+ "ffffffffffffffff ",
+ "1 ",
+ "abcdef01 ",
+ "67 ",
+ "FF98 ",
+ "0 ",
+ "FF ",
+ "1 ",
+ "1 ",
+ "1267 ",
+ "ED98 ",
+ "0 ",
+ "FFFF ",
+ "1 ",
+ "EF01 ",
+ "1267 ",
+ "FFFFED98 ",
+ "BFFFFFFE ",
+ "FFFFFFFF ",
+ "1 ",
+ "ABCDEF01 ",
+ "1267 ",
+ "FFFFFFFFFFFFED98 ",
+ "BFFFFFFFFFFFFFFE ",
+ "FFFFFFFFFFFFFFFF ",
+ "1 ",
+ "ABCDEF01 ",
+ "1267 ",
+ "FFFFFFFFFFFFED98 ",
+ "BFFFFFFFFFFFFFFE ",
+ "FFFFFFFFFFFFFFFF ",
+ "1 ",
+ "ABCDEF01 ",
+ " 00000103",
+ " -00000104",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " 00000001",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -00004351",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -1412567295",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " 2882400001",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " 2882400001",
+ " 00000103",
+ " -00000104",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " 00000001",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -00004351",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -1412567295",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " 2882400001",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " 2882400001",
+ " 00000103",
+ " 00065432",
+ " 00000000",
+ " 00000255",
+ " 00000001",
+ " 00000001",
+ " 00004711",
+ " 00060824",
+ " 00000000",
+ " 00065535",
+ " 00000001",
+ " 00061185",
+ " 00004711",
+ " 4294962584",
+ " 3221225470",
+ " 4294967295",
+ " 00000001",
+ " 2882400001",
+ " 00004711",
+ " 18446744073709546904",
+ " 13835058055282163710",
+ " 18446744073709551615",
+ " 00000001",
+ " 2882400001",
+ " 00004711",
+ " 18446744073709546904",
+ " 13835058055282163710",
+ " 18446744073709551615",
+ " 00000001",
+ " 2882400001",
+ " 00000147",
+ " 00177630",
+ " 00000000",
+ " 00000377",
+ " 00000001",
+ " 00000001",
+ " 00011147",
+ " 00166630",
+ " 00000000",
+ " 00177777",
+ " 00000001",
+ " 00167401",
+ " 00011147",
+ " 37777766630",
+ " 27777777776",
+ " 37777777777",
+ " 00000001",
+ " 25363367401",
+ " 00011147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ " 00000001",
+ " 25363367401",
+ " 00011147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ " 00000001",
+ " 25363367401",
+ " 00000067",
+ " 0000ff98",
+ " 00000000",
+ " 000000ff",
+ " 00000001",
+ " 00000001",
+ " 00001267",
+ " 0000ed98",
+ " 00000000",
+ " 0000ffff",
+ " 00000001",
+ " 0000ef01",
+ " 00001267",
+ " ffffed98",
+ " bffffffe",
+ " ffffffff",
+ " 00000001",
+ " abcdef01",
+ " 00001267",
+ " ffffffffffffed98",
+ " bffffffffffffffe",
+ " ffffffffffffffff",
+ " 00000001",
+ " abcdef01",
+ " 00001267",
+ " ffffffffffffed98",
+ " bffffffffffffffe",
+ " ffffffffffffffff",
+ " 00000001",
+ " abcdef01",
+ " 00000067",
+ " 0000FF98",
+ " 00000000",
+ " 000000FF",
+ " 00000001",
+ " 00000001",
+ " 00001267",
+ " 0000ED98",
+ " 00000000",
+ " 0000FFFF",
+ " 00000001",
+ " 0000EF01",
+ " 00001267",
+ " FFFFED98",
+ " BFFFFFFE",
+ " FFFFFFFF",
+ " 00000001",
+ " ABCDEF01",
+ " 00001267",
+ " FFFFFFFFFFFFED98",
+ " BFFFFFFFFFFFFFFE",
+ " FFFFFFFFFFFFFFFF",
+ " 00000001",
+ " ABCDEF01",
+ " 00001267",
+ " FFFFFFFFFFFFED98",
+ " BFFFFFFFFFFFFFFE",
+ " FFFFFFFFFFFFFFFF",
+ " 00000001",
+ " ABCDEF01",
+ "00000103 ",
+ "-00000104 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "00000001 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-00004351 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-1412567295 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "2882400001 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "2882400001 ",
+ "00000103 ",
+ "-00000104 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "00000001 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-00004351 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-1412567295 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "2882400001 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "2882400001 ",
+ "00000103 ",
+ "00065432 ",
+ "00000000 ",
+ "00000255 ",
+ "00000001 ",
+ "00000001 ",
+ "00004711 ",
+ "00060824 ",
+ "00000000 ",
+ "00065535 ",
+ "00000001 ",
+ "00061185 ",
+ "00004711 ",
+ "4294962584 ",
+ "3221225470 ",
+ "4294967295 ",
+ "00000001 ",
+ "2882400001 ",
+ "00004711 ",
+ "18446744073709546904 ",
+ "13835058055282163710 ",
+ "18446744073709551615 ",
+ "00000001 ",
+ "2882400001 ",
+ "00004711 ",
+ "18446744073709546904 ",
+ "13835058055282163710 ",
+ "18446744073709551615 ",
+ "00000001 ",
+ "2882400001 ",
+ "00000147 ",
+ "00177630 ",
+ "00000000 ",
+ "00000377 ",
+ "00000001 ",
+ "00000001 ",
+ "00011147 ",
+ "00166630 ",
+ "00000000 ",
+ "00177777 ",
+ "00000001 ",
+ "00167401 ",
+ "00011147 ",
+ "37777766630 ",
+ "27777777776 ",
+ "37777777777 ",
+ "00000001 ",
+ "25363367401 ",
+ "00011147 ",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ "00000001 ",
+ "25363367401 ",
+ "00011147 ",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ "00000001 ",
+ "25363367401 ",
+ "00000067 ",
+ "0000ff98 ",
+ "00000000 ",
+ "000000ff ",
+ "00000001 ",
+ "00000001 ",
+ "00001267 ",
+ "0000ed98 ",
+ "00000000 ",
+ "0000ffff ",
+ "00000001 ",
+ "0000ef01 ",
+ "00001267 ",
+ "ffffed98 ",
+ "bffffffe ",
+ "ffffffff ",
+ "00000001 ",
+ "abcdef01 ",
+ "00001267 ",
+ "ffffffffffffed98 ",
+ "bffffffffffffffe ",
+ "ffffffffffffffff ",
+ "00000001 ",
+ "abcdef01 ",
+ "00001267 ",
+ "ffffffffffffed98 ",
+ "bffffffffffffffe ",
+ "ffffffffffffffff ",
+ "00000001 ",
+ "abcdef01 ",
+ "00000067 ",
+ "0000FF98 ",
+ "00000000 ",
+ "000000FF ",
+ "00000001 ",
+ "00000001 ",
+ "00001267 ",
+ "0000ED98 ",
+ "00000000 ",
+ "0000FFFF ",
+ "00000001 ",
+ "0000EF01 ",
+ "00001267 ",
+ "FFFFED98 ",
+ "BFFFFFFE ",
+ "FFFFFFFF ",
+ "00000001 ",
+ "ABCDEF01 ",
+ "00001267 ",
+ "FFFFFFFFFFFFED98 ",
+ "BFFFFFFFFFFFFFFE ",
+ "FFFFFFFFFFFFFFFF ",
+ "00000001 ",
+ "ABCDEF01 ",
+ "00001267 ",
+ "FFFFFFFFFFFFED98 ",
+ "BFFFFFFFFFFFFFFE ",
+ "FFFFFFFFFFFFFFFF ",
+ "00000001 ",
+ "ABCDEF01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004351 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001412567295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004351 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001412567295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065432 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000255 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060824 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065535 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061185 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004294962584 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003221225470 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004294967295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744073709546904 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013835058055282163710 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744073709551615 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744073709546904 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013835058055282163710 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744073709551615 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000177630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000166630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000177777 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000167401 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037777766630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027777777776 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037777777777 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025363367401 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001777777777777777766630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001377777777777777777776 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001777777777777777777777 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025363367401 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001777777777777777766630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001377777777777777777776 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001777777777777777777777 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025363367401 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff98 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed98 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ef01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffed98 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bffffffe ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000abcdef01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffed98 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bffffffffffffffe ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000abcdef01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffed98 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bffffffffffffffe ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000abcdef01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF98 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ED98 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EF01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFED98 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BFFFFFFE ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ABCDEF01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFED98 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BFFFFFFFFFFFFFFE ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ABCDEF01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFED98 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BFFFFFFFFFFFFFFE ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ABCDEF01 ",
+ NULL};
diff --git a/erts/test/erl_print_SUITE_data/integer_test.h b/erts/test/erl_print_SUITE_data/integer_test.h
new file mode 100644
index 0000000000..94c8d59897
--- /dev/null
+++ b/erts/test/erl_print_SUITE_data/integer_test.h
@@ -0,0 +1,1106 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2005-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%
+ */
+
+/*
+ * This file has been automatically generated. Do NOT edit it; instead,
+ * run 'erl_print_tests.true integer save_expected_result'
+ */
+
+char *integer_expected_result[] = {
+ "103",
+ "-104",
+ "0",
+ "-1",
+ "1",
+ "1",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-4351",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-1412567295",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-1412567295",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-1412567295",
+ "103",
+ "-104",
+ "0",
+ "-1",
+ "1",
+ "1",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-4351",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-1412567295",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-1412567295",
+ "4711",
+ "-4712",
+ "0",
+ "-1",
+ "1",
+ "-1412567295",
+ "103",
+ "65432",
+ "0",
+ "255",
+ "1",
+ "1",
+ "4711",
+ "60824",
+ "0",
+ "65535",
+ "1",
+ "61185",
+ "4711",
+ "4294962584",
+ "3221225470",
+ "4294967295",
+ "1",
+ "2882400001",
+ "4711",
+ "4294962584",
+ "3221225470",
+ "4294967295",
+ "1",
+ "2882400001",
+ "4711",
+ "18446744073709546904",
+ "13835058055282163710",
+ "18446744073709551615",
+ "1",
+ "18446744072296984321",
+ "147",
+ "177630",
+ "0",
+ "377",
+ "1",
+ "1",
+ "11147",
+ "166630",
+ "0",
+ "177777",
+ "1",
+ "167401",
+ "11147",
+ "37777766630",
+ "27777777776",
+ "37777777777",
+ "1",
+ "25363367401",
+ "11147",
+ "37777766630",
+ "27777777776",
+ "37777777777",
+ "1",
+ "25363367401",
+ "11147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ "1",
+ "1777777777765363367401",
+ "67",
+ "ff98",
+ "0",
+ "ff",
+ "1",
+ "1",
+ "1267",
+ "ed98",
+ "0",
+ "ffff",
+ "1",
+ "ef01",
+ "1267",
+ "ffffed98",
+ "bffffffe",
+ "ffffffff",
+ "1",
+ "abcdef01",
+ "1267",
+ "ffffed98",
+ "bffffffe",
+ "ffffffff",
+ "1",
+ "abcdef01",
+ "1267",
+ "ffffffffffffed98",
+ "bffffffffffffffe",
+ "ffffffffffffffff",
+ "1",
+ "ffffffffabcdef01",
+ "67",
+ "FF98",
+ "0",
+ "FF",
+ "1",
+ "1",
+ "1267",
+ "ED98",
+ "0",
+ "FFFF",
+ "1",
+ "EF01",
+ "1267",
+ "FFFFED98",
+ "BFFFFFFE",
+ "FFFFFFFF",
+ "1",
+ "ABCDEF01",
+ "1267",
+ "FFFFED98",
+ "BFFFFFFE",
+ "FFFFFFFF",
+ "1",
+ "ABCDEF01",
+ "1267",
+ "FFFFFFFFFFFFED98",
+ "BFFFFFFFFFFFFFFE",
+ "FFFFFFFFFFFFFFFF",
+ "1",
+ "FFFFFFFFABCDEF01",
+ " 00103",
+ " -00104",
+ " 00000",
+ " -00001",
+ " 00001",
+ " 00001",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ " -04351",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "-1412567295",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "-1412567295",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "-1412567295",
+ " 00103",
+ " -00104",
+ " 00000",
+ " -00001",
+ " 00001",
+ " 00001",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ " -04351",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "-1412567295",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "-1412567295",
+ " 04711",
+ " -04712",
+ " 00000",
+ " -00001",
+ " 00001",
+ "-1412567295",
+ " 00103",
+ " 65432",
+ " 00000",
+ " 00255",
+ " 00001",
+ " 00001",
+ " 04711",
+ " 60824",
+ " 00000",
+ " 65535",
+ " 00001",
+ " 61185",
+ " 04711",
+ "4294962584",
+ "3221225470",
+ "4294967295",
+ " 00001",
+ "2882400001",
+ " 04711",
+ "4294962584",
+ "3221225470",
+ "4294967295",
+ " 00001",
+ "2882400001",
+ " 04711",
+ "18446744073709546904",
+ "13835058055282163710",
+ "18446744073709551615",
+ " 00001",
+ "18446744072296984321",
+ " 00147",
+ " 177630",
+ " 00000",
+ " 00377",
+ " 00001",
+ " 00001",
+ " 11147",
+ " 166630",
+ " 00000",
+ " 177777",
+ " 00001",
+ " 167401",
+ " 11147",
+ "37777766630",
+ "27777777776",
+ "37777777777",
+ " 00001",
+ "25363367401",
+ " 11147",
+ "37777766630",
+ "27777777776",
+ "37777777777",
+ " 00001",
+ "25363367401",
+ " 11147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ " 00001",
+ "1777777777765363367401",
+ " 00067",
+ " 0ff98",
+ " 00000",
+ " 000ff",
+ " 00001",
+ " 00001",
+ " 01267",
+ " 0ed98",
+ " 00000",
+ " 0ffff",
+ " 00001",
+ " 0ef01",
+ " 01267",
+ " ffffed98",
+ " bffffffe",
+ " ffffffff",
+ " 00001",
+ " abcdef01",
+ " 01267",
+ " ffffed98",
+ " bffffffe",
+ " ffffffff",
+ " 00001",
+ " abcdef01",
+ " 01267",
+ "ffffffffffffed98",
+ "bffffffffffffffe",
+ "ffffffffffffffff",
+ " 00001",
+ "ffffffffabcdef01",
+ " 00067",
+ " 0FF98",
+ " 00000",
+ " 000FF",
+ " 00001",
+ " 00001",
+ " 01267",
+ " 0ED98",
+ " 00000",
+ " 0FFFF",
+ " 00001",
+ " 0EF01",
+ " 01267",
+ " FFFFED98",
+ " BFFFFFFE",
+ " FFFFFFFF",
+ " 00001",
+ " ABCDEF01",
+ " 01267",
+ " FFFFED98",
+ " BFFFFFFE",
+ " FFFFFFFF",
+ " 00001",
+ " ABCDEF01",
+ " 01267",
+ "FFFFFFFFFFFFED98",
+ "BFFFFFFFFFFFFFFE",
+ "FFFFFFFFFFFFFFFF",
+ " 00001",
+ "FFFFFFFFABCDEF01",
+ "+103 ",
+ "-104 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "+1 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-4351 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-1412567295 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-1412567295 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-1412567295 ",
+ "+103 ",
+ "-104 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "+1 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-4351 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-1412567295 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-1412567295 ",
+ "+4711 ",
+ "-4712 ",
+ "+0 ",
+ "-1 ",
+ "+1 ",
+ "-1412567295 ",
+ "103 ",
+ "65432 ",
+ "0 ",
+ "255 ",
+ "1 ",
+ "1 ",
+ "4711 ",
+ "60824 ",
+ "0 ",
+ "65535 ",
+ "1 ",
+ "61185 ",
+ "4711 ",
+ "4294962584 ",
+ "3221225470 ",
+ "4294967295 ",
+ "1 ",
+ "2882400001 ",
+ "4711 ",
+ "4294962584 ",
+ "3221225470 ",
+ "4294967295 ",
+ "1 ",
+ "2882400001 ",
+ "4711 ",
+ "18446744073709546904 ",
+ "13835058055282163710 ",
+ "18446744073709551615 ",
+ "1 ",
+ "18446744072296984321 ",
+ "147 ",
+ "177630 ",
+ "0 ",
+ "377 ",
+ "1 ",
+ "1 ",
+ "11147 ",
+ "166630 ",
+ "0 ",
+ "177777 ",
+ "1 ",
+ "167401 ",
+ "11147 ",
+ "37777766630 ",
+ "27777777776 ",
+ "37777777777 ",
+ "1 ",
+ "25363367401 ",
+ "11147 ",
+ "37777766630 ",
+ "27777777776 ",
+ "37777777777 ",
+ "1 ",
+ "25363367401 ",
+ "11147 ",
+ "1777777777777777766630 ",
+ "1377777777777777777776 ",
+ "1777777777777777777777 ",
+ "1 ",
+ "1777777777765363367401 ",
+ "67 ",
+ "ff98 ",
+ "0 ",
+ "ff ",
+ "1 ",
+ "1 ",
+ "1267 ",
+ "ed98 ",
+ "0 ",
+ "ffff ",
+ "1 ",
+ "ef01 ",
+ "1267 ",
+ "ffffed98 ",
+ "bffffffe ",
+ "ffffffff ",
+ "1 ",
+ "abcdef01 ",
+ "1267 ",
+ "ffffed98 ",
+ "bffffffe ",
+ "ffffffff ",
+ "1 ",
+ "abcdef01 ",
+ "1267 ",
+ "ffffffffffffed98 ",
+ "bffffffffffffffe ",
+ "ffffffffffffffff ",
+ "1 ",
+ "ffffffffabcdef01 ",
+ "67 ",
+ "FF98 ",
+ "0 ",
+ "FF ",
+ "1 ",
+ "1 ",
+ "1267 ",
+ "ED98 ",
+ "0 ",
+ "FFFF ",
+ "1 ",
+ "EF01 ",
+ "1267 ",
+ "FFFFED98 ",
+ "BFFFFFFE ",
+ "FFFFFFFF ",
+ "1 ",
+ "ABCDEF01 ",
+ "1267 ",
+ "FFFFED98 ",
+ "BFFFFFFE ",
+ "FFFFFFFF ",
+ "1 ",
+ "ABCDEF01 ",
+ "1267 ",
+ "FFFFFFFFFFFFED98 ",
+ "BFFFFFFFFFFFFFFE ",
+ "FFFFFFFFFFFFFFFF ",
+ "1 ",
+ "FFFFFFFFABCDEF01 ",
+ " 00000103",
+ " -00000104",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " 00000001",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -00004351",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -1412567295",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -1412567295",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -1412567295",
+ " 00000103",
+ " -00000104",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " 00000001",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -00004351",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -1412567295",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -1412567295",
+ " 00004711",
+ " -00004712",
+ " 00000000",
+ " -00000001",
+ " 00000001",
+ " -1412567295",
+ " 00000103",
+ " 00065432",
+ " 00000000",
+ " 00000255",
+ " 00000001",
+ " 00000001",
+ " 00004711",
+ " 00060824",
+ " 00000000",
+ " 00065535",
+ " 00000001",
+ " 00061185",
+ " 00004711",
+ " 4294962584",
+ " 3221225470",
+ " 4294967295",
+ " 00000001",
+ " 2882400001",
+ " 00004711",
+ " 4294962584",
+ " 3221225470",
+ " 4294967295",
+ " 00000001",
+ " 2882400001",
+ " 00004711",
+ " 18446744073709546904",
+ " 13835058055282163710",
+ " 18446744073709551615",
+ " 00000001",
+ " 18446744072296984321",
+ " 00000147",
+ " 00177630",
+ " 00000000",
+ " 00000377",
+ " 00000001",
+ " 00000001",
+ " 00011147",
+ " 00166630",
+ " 00000000",
+ " 00177777",
+ " 00000001",
+ " 00167401",
+ " 00011147",
+ " 37777766630",
+ " 27777777776",
+ " 37777777777",
+ " 00000001",
+ " 25363367401",
+ " 00011147",
+ " 37777766630",
+ " 27777777776",
+ " 37777777777",
+ " 00000001",
+ " 25363367401",
+ " 00011147",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ " 00000001",
+ "1777777777765363367401",
+ " 00000067",
+ " 0000ff98",
+ " 00000000",
+ " 000000ff",
+ " 00000001",
+ " 00000001",
+ " 00001267",
+ " 0000ed98",
+ " 00000000",
+ " 0000ffff",
+ " 00000001",
+ " 0000ef01",
+ " 00001267",
+ " ffffed98",
+ " bffffffe",
+ " ffffffff",
+ " 00000001",
+ " abcdef01",
+ " 00001267",
+ " ffffed98",
+ " bffffffe",
+ " ffffffff",
+ " 00000001",
+ " abcdef01",
+ " 00001267",
+ " ffffffffffffed98",
+ " bffffffffffffffe",
+ " ffffffffffffffff",
+ " 00000001",
+ " ffffffffabcdef01",
+ " 00000067",
+ " 0000FF98",
+ " 00000000",
+ " 000000FF",
+ " 00000001",
+ " 00000001",
+ " 00001267",
+ " 0000ED98",
+ " 00000000",
+ " 0000FFFF",
+ " 00000001",
+ " 0000EF01",
+ " 00001267",
+ " FFFFED98",
+ " BFFFFFFE",
+ " FFFFFFFF",
+ " 00000001",
+ " ABCDEF01",
+ " 00001267",
+ " FFFFED98",
+ " BFFFFFFE",
+ " FFFFFFFF",
+ " 00000001",
+ " ABCDEF01",
+ " 00001267",
+ " FFFFFFFFFFFFED98",
+ " BFFFFFFFFFFFFFFE",
+ " FFFFFFFFFFFFFFFF",
+ " 00000001",
+ " FFFFFFFFABCDEF01",
+ "00000103 ",
+ "-00000104 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "00000001 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-00004351 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-1412567295 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-1412567295 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-1412567295 ",
+ "00000103 ",
+ "-00000104 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "00000001 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-00004351 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-1412567295 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-1412567295 ",
+ "00004711 ",
+ "-00004712 ",
+ "00000000 ",
+ "-00000001 ",
+ "00000001 ",
+ "-1412567295 ",
+ "00000103 ",
+ "00065432 ",
+ "00000000 ",
+ "00000255 ",
+ "00000001 ",
+ "00000001 ",
+ "00004711 ",
+ "00060824 ",
+ "00000000 ",
+ "00065535 ",
+ "00000001 ",
+ "00061185 ",
+ "00004711 ",
+ "4294962584 ",
+ "3221225470 ",
+ "4294967295 ",
+ "00000001 ",
+ "2882400001 ",
+ "00004711 ",
+ "4294962584 ",
+ "3221225470 ",
+ "4294967295 ",
+ "00000001 ",
+ "2882400001 ",
+ "00004711 ",
+ "18446744073709546904 ",
+ "13835058055282163710 ",
+ "18446744073709551615 ",
+ "00000001 ",
+ "18446744072296984321 ",
+ "00000147 ",
+ "00177630 ",
+ "00000000 ",
+ "00000377 ",
+ "00000001 ",
+ "00000001 ",
+ "00011147 ",
+ "00166630 ",
+ "00000000 ",
+ "00177777 ",
+ "00000001 ",
+ "00167401 ",
+ "00011147 ",
+ "37777766630 ",
+ "27777777776 ",
+ "37777777777 ",
+ "00000001 ",
+ "25363367401 ",
+ "00011147 ",
+ "37777766630 ",
+ "27777777776 ",
+ "37777777777 ",
+ "00000001 ",
+ "25363367401 ",
+ "00011147 ",
+ "1777777777777777766630",
+ "1377777777777777777776",
+ "1777777777777777777777",
+ "00000001 ",
+ "1777777777765363367401",
+ "00000067 ",
+ "0000ff98 ",
+ "00000000 ",
+ "000000ff ",
+ "00000001 ",
+ "00000001 ",
+ "00001267 ",
+ "0000ed98 ",
+ "00000000 ",
+ "0000ffff ",
+ "00000001 ",
+ "0000ef01 ",
+ "00001267 ",
+ "ffffed98 ",
+ "bffffffe ",
+ "ffffffff ",
+ "00000001 ",
+ "abcdef01 ",
+ "00001267 ",
+ "ffffed98 ",
+ "bffffffe ",
+ "ffffffff ",
+ "00000001 ",
+ "abcdef01 ",
+ "00001267 ",
+ "ffffffffffffed98 ",
+ "bffffffffffffffe ",
+ "ffffffffffffffff ",
+ "00000001 ",
+ "ffffffffabcdef01 ",
+ "00000067 ",
+ "0000FF98 ",
+ "00000000 ",
+ "000000FF ",
+ "00000001 ",
+ "00000001 ",
+ "00001267 ",
+ "0000ED98 ",
+ "00000000 ",
+ "0000FFFF ",
+ "00000001 ",
+ "0000EF01 ",
+ "00001267 ",
+ "FFFFED98 ",
+ "BFFFFFFE ",
+ "FFFFFFFF ",
+ "00000001 ",
+ "ABCDEF01 ",
+ "00001267 ",
+ "FFFFED98 ",
+ "BFFFFFFE ",
+ "FFFFFFFF ",
+ "00000001 ",
+ "ABCDEF01 ",
+ "00001267 ",
+ "FFFFFFFFFFFFED98 ",
+ "BFFFFFFFFFFFFFFE ",
+ "FFFFFFFFFFFFFFFF ",
+ "00000001 ",
+ "FFFFFFFFABCDEF01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004351 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001412567295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001412567295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001412567295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004351 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001412567295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001412567295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004712 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "-0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001412567295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065432 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000255 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060824 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065535 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061185 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004294962584 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003221225470 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004294967295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004294962584 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003221225470 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004294967295 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002882400001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004711 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744073709546904 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013835058055282163710 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744073709551615 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018446744072296984321 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000177630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000377 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000166630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000177777 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000167401 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037777766630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027777777776 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037777777777 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025363367401 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037777766630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000027777777776 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000037777777777 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000025363367401 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011147 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001777777777777777766630 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001377777777777777777776 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001777777777777777777777 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001777777777765363367401 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff98 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ed98 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ef01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffed98 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bffffffe ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000abcdef01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffed98 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bffffffe ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000abcdef01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffed98 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bffffffffffffffe ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffabcdef01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000067 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF98 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ED98 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EF01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFED98 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BFFFFFFE ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ABCDEF01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFED98 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BFFFFFFE ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ABCDEF01 ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001267 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFED98 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000BFFFFFFFFFFFFFFE ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF ",
+ "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 ",
+ "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000FFFFFFFFABCDEF01 ",
+ NULL};
diff --git a/erts/test/erl_print_SUITE_data/snprintf_test.h b/erts/test/erl_print_SUITE_data/snprintf_test.h
new file mode 100644
index 0000000000..0849b60562
--- /dev/null
+++ b/erts/test/erl_print_SUITE_data/snprintf_test.h
@@ -0,0 +1,43 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2005-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%
+ */
+
+/*
+ * This file has been automatically generated. Do NOT edit it; instead,
+ * run 'erl_print_tests.false snprintf save_expected_result'
+ */
+
+char *snprintf_expected_result[] = {
+ "hej h",
+ "hej ho",
+ "hej hop",
+ "hej hopp",
+ "hej hopp",
+ "hej 4",
+ "hej 47",
+ "hej 471",
+ "hej 4711",
+ "hej 4711",
+ "abcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ���1234567890()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_\a\b\f\n\r",
+ "abcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ���1234567890()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_\a\b\f\n\r\t",
+ "abcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ���1234567890()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_\a\b\f\n\r\t\v",
+ "abcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ���1234567890()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_\a\b\f\n\r\t\v",
+ "abcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ���1234567890()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_\a\b\f\n\r\t\v",
+ "abcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ�",
+ "abcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ���1234567890()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_\a\b\f\n\r\t\vabcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ���1234567890()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_\a\b\f\n\r\t\v",
+ NULL};
diff --git a/erts/test/erl_print_SUITE_data/string_test.h b/erts/test/erl_print_SUITE_data/string_test.h
new file mode 100644
index 0000000000..32249ab6e9
--- /dev/null
+++ b/erts/test/erl_print_SUITE_data/string_test.h
@@ -0,0 +1,33 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2005-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%
+ */
+
+/*
+ * This file has been automatically generated. Do NOT edit it; instead,
+ * run 'erl_print_tests.false string save_expected_result'
+ */
+
+char *string_expected_result[] = {
+ "hej",
+ "hopp ",
+ " hopp",
+ "hopp ",
+ " hopp",
+ "\t abcd",
+ "\t abcdefghijklmnopqrstuvwxyz���ABCDEFGHIJKLMNOPQRSTUVXYZ���1234567890()[]{}+-;,:.@�$!\"#�%&/\\=?'`�^~��|<>�*_\a\b\f\n\r\t\v",
+ NULL};
diff --git a/erts/test/erlc_SUITE.erl b/erts/test/erlc_SUITE.erl
new file mode 100644
index 0000000000..ce64ef1a75
--- /dev/null
+++ b/erts/test/erlc_SUITE.erl
@@ -0,0 +1,286 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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(erlc_SUITE).
+
+%% Tests the erlc command by compiling various types of files.
+
+-export([all/1, compile_erl/1, compile_yecc/1, compile_script/1,
+ compile_mib/1, good_citizen/1, deep_cwd/1]).
+
+-include("test_server.hrl").
+
+all(suite) ->
+ [compile_erl, compile_yecc, compile_script, compile_mib,
+ good_citizen, deep_cwd].
+
+%% Copy from erlc_SUITE_data/include/erl_test.hrl.
+
+-record(person, {name, shoe_size}).
+
+%% Tests that compiling Erlang source code works.
+
+compile_erl(Config) when is_list(Config) ->
+ ?line {SrcDir, OutDir, Cmd} = get_cmd(Config),
+ ?line FileName = filename:join(SrcDir, "erl_test_ok.erl"),
+
+ %% By default, warnings are now turned on.
+ ?line run(Config, Cmd, FileName, "",
+ ["Warning: function foo/0 is unused\$",
+ "_OK_"]),
+
+ %% Test that the compiled file is where it should be,
+ %% and that it is runnable.
+
+ ?line {module, erl_test_ok} = code:load_abs(filename:join(OutDir,
+ "erl_test_ok")),
+ ?line 42 = erl_test_ok:shoe_size(#person{shoe_size=42}),
+ ?line code:purge(erl_test_ok),
+
+ %% Try disabling warnings.
+
+ ?line run(Config, Cmd, FileName, "-W0", ["_OK_"]),
+
+ %% Check a bad file.
+
+ ?line BadFile = filename:join(SrcDir, "erl_test_bad.erl"),
+ ?line run(Config, Cmd, BadFile, "", ["function non_existing/1 undefined\$",
+ "_ERROR_"]),
+
+ ok.
+
+%% Test that compiling yecc source code works.
+
+compile_yecc(Config) when is_list(Config) ->
+ ?line {SrcDir, _, OutDir} = get_dirs(Config),
+ ?line Cmd = erlc() ++ " -o" ++ OutDir ++ " ",
+ ?line FileName = filename:join(SrcDir, "yecc_test_ok.yrl"),
+ ?line run(Config, Cmd, FileName, "-W0", ["_OK_"]),
+ ?line true = exists(filename:join(OutDir, "yecc_test_ok.erl")),
+
+ ?line BadFile = filename:join(SrcDir, "yecc_test_bad.yrl"),
+ ?line run(Config, Cmd, BadFile, "-W0",
+ ["rootsymbol form is not a nonterminal\$",
+ "undefined nonterminal: form\$",
+ "Nonterminals is missing\$",
+ "_ERROR_"]),
+ ?line exists(filename:join(OutDir, "yecc_test_ok.erl")),
+
+ ok.
+
+%% Test that compiling start scripts works.
+
+compile_script(Config) when is_list(Config) ->
+ ?line {SrcDir, OutDir, Cmd} = get_cmd(Config),
+ ?line FileName = filename:join(SrcDir, "start_ok.script"),
+ ?line run(Config, Cmd, FileName, "", ["_OK_"]),
+ ?line true = exists(filename:join(OutDir, "start_ok.boot")),
+
+ ?line BadFile = filename:join(SrcDir, "start_bad.script"),
+ ?line run(Config, Cmd, BadFile, "", ["syntax error before:", "_ERROR_"]),
+ ok.
+
+%% Test that compiling SNMP mibs works.
+
+compile_mib(Config) when is_list(Config) ->
+ ?line {SrcDir, OutDir, Cmd} = get_cmd(Config),
+ ?line FileName = filename:join(SrcDir, "GOOD-MIB.mib"),
+ ?line run(Config, Cmd, FileName, "", ["_OK_"]),
+ ?line Output = filename:join(OutDir, "GOOD-MIB.bin"),
+ ?line true = exists(Output),
+
+ %% Try -W option.
+
+ ?line ok = file:delete(Output),
+ ?line run(Config, Cmd, FileName, "-W",
+ ["_OK_"]),
+ ?line true = exists(Output),
+
+ %% Try -W option and more verbose.
+
+ ?line ok = file:delete(Output),
+ ?line case test_server:os_type() of
+ {unix,_} ->
+ ?line run(Config, Cmd, FileName, "-W +'{verbosity,info}'",
+ ["GOOD-MIB.mib: Info. No accessfunction for 'sysDescr'",
+ "_OK_"]),
+ ?line true = exists(Output),
+ ?line ok = file:delete(Output);
+ _ -> ok %Don't bother -- too much work.
+ end,
+
+ %% Try a bad file.
+
+ ?line BadFile = filename:join(SrcDir, "BAD-MIB.mib"),
+ ?line run(Config, Cmd, BadFile, "",
+ ["Error: syntax error before: mibs\$", "compilation_failed_ERROR_"]),
+
+ %% Make sure that no -I option works.
+
+ ?line NewCmd = erlc() ++ " -o" ++ OutDir ++ " ",
+ ?line run(Config, NewCmd, FileName, "", ["_OK_"]),
+ ?line true = exists(Output),
+
+ ok.
+
+%% Checks that 'erlc' doesn't eat any input (important when called from a
+%% shell script with redirected input).
+good_citizen(Config) when is_list(Config) ->
+ case os:type() of
+ {unix, _} ->
+ ?line PrivDir = ?config(priv_dir, Config),
+ ?line Answer = filename:join(PrivDir, "answer"),
+ ?line Script = filename:join(PrivDir, "test_script"),
+ ?line Test = filename:join(PrivDir, "test.erl"),
+ ?line S = ["#! /bin/sh\n", "erlc ", Test, "\n",
+ "read reply\n", "echo $reply\n"],
+ ?line ok = file:write_file(Script, S),
+ ?line ok = file:write_file(Test, "-module(test).\n"),
+ ?line Cmd = "echo y | sh " ++ Script ++ " > " ++ Answer,
+ ?line os:cmd(Cmd),
+ ?line {ok, Answer0} = file:read_file(Answer),
+ ?line [$y|_] = binary_to_list(Answer0),
+ ok;
+ _ ->
+ {skip, "Unix specific"}
+ end.
+
+%% Make sure that compiling an Erlang module deep down in
+%% in a directory with more than 255 characters works.
+deep_cwd(Config) when is_list(Config) ->
+ case os:type() of
+ {unix, _} ->
+ PrivDir = ?config(priv_dir, Config),
+ deep_cwd_1(PrivDir);
+ _ ->
+ {skip, "Only a problem on Unix"}
+ end.
+
+deep_cwd_1(PrivDir) ->
+ ?line DeepDir0 = filename:join(PrivDir, lists:duplicate(128, $a)),
+ ?line DeepDir = filename:join(DeepDir0, lists:duplicate(128, $b)),
+ ?line ok = file:make_dir(DeepDir0),
+ ?line ok = file:make_dir(DeepDir),
+ ?line ok = file:set_cwd(DeepDir),
+ ?line ok = file:write_file("test.erl", "-module(test).\n\n"),
+ ?line io:format("~s\n", [os:cmd("erlc test.erl")]),
+ ?line true = filelib:is_file("test.beam"),
+ ok.
+
+erlc() ->
+ case os:find_executable("erlc") of
+ false ->
+ test_server:fail("Can't find erlc");
+ Erlc ->
+ Erlc
+ end.
+
+%% Runs a command.
+
+run(Config, Cmd0, Name, Options, Expect) ->
+ Cmd = Cmd0 ++ " " ++ Options ++ " " ++ Name,
+ io:format("~s", [Cmd]),
+ Result = run_command(Config, Cmd),
+ Messages = split(Result, [], []),
+ io:format("Result: ~p", [Messages]),
+ io:format("Expected: ~p", [Expect]),
+ match_messages(Messages, Expect).
+
+split([$\n|Rest], Current, Lines) ->
+ split(Rest, [], [lists:reverse(Current)|Lines]);
+split([$\r|Rest], Current, Lines) ->
+ split(Rest, Current, Lines);
+split([Char|Rest], Current, Lines) ->
+ split(Rest, [Char|Current], Lines);
+split([], [], Lines) ->
+ lists:reverse(Lines);
+split([], Current, Lines) ->
+ split([], [], [lists:reverse(Current)|Lines]).
+
+match_messages([Msg|Rest1], [Regexp|Rest2]) ->
+ case re:run(Msg, Regexp, [{capture,none}]) of
+ match ->
+ ok;
+ nomatch ->
+ io:format("Not matching: ~s\n", [Msg]),
+ io:format("Regexp : ~s\n", [Regexp]),
+ test_server:fail(message_mismatch)
+ end,
+ match_messages(Rest1, Rest2);
+match_messages([], [Expect|Rest]) ->
+ test_server:fail({too_few_messages, [Expect|Rest]});
+match_messages([Msg|Rest], []) ->
+ test_server:fail({too_many_messages, [Msg|Rest]});
+match_messages([], []) ->
+ ok.
+
+get_cmd(Cfg) ->
+ ?line {SrcDir, IncDir, OutDir} = get_dirs(Cfg),
+ ?line Cmd = erlc() ++ " -I" ++ IncDir ++ " -o" ++ OutDir ++ " ",
+ {SrcDir, OutDir, Cmd}.
+
+get_dirs(Cfg) ->
+ ?line DataDir = ?config(data_dir, Cfg),
+ ?line PrivDir = ?config(priv_dir, Cfg),
+ ?line SrcDir = filename:join(DataDir, "src"),
+ ?line IncDir = filename:join(DataDir, "include"),
+ {SrcDir, IncDir, PrivDir}.
+
+exists(Name) ->
+ filelib:is_file(Name).
+
+%% Runs the command using os:cmd/1.
+%%
+%% Returns the output from the command (as a list of characters with
+%% embedded newlines). The very last line will indicate the
+%% exit status of the command, where _OK_ means zero, and _ERROR_
+%% a non-zero exit status.
+
+run_command(Config, Cmd) ->
+ TmpDir = filename:join(?config(priv_dir, Config), "tmp"),
+ file:make_dir(TmpDir),
+ {RunFile, Run, Script} = run_command(TmpDir, os:type(), Cmd),
+ ok = file:write_file(filename:join(TmpDir, RunFile), Script),
+ os:cmd(Run).
+
+run_command(Dir, {win32, _}, Cmd) ->
+ BatchFile = filename:join(Dir, "run.bat"),
+ Run = re:replace(filename:rootname(BatchFile), "/", "\\",
+ [global,{return,list}]),
+ {BatchFile,
+ Run,
+ ["@echo off\r\n",
+ "set ERLC_EMULATOR=", atom_to_list(lib:progname()), "\r\n",
+ Cmd, "\r\n",
+ "if errorlevel 1 echo _ERROR_\r\n",
+ "if not errorlevel 1 echo _OK_\r\n"]};
+run_command(Dir, {unix, _}, Cmd) ->
+ Name = filename:join(Dir, "run"),
+ {Name,
+ "/bin/sh " ++ Name,
+ ["#!/bin/sh\n",
+ "ERLC_EMULATOR='", atom_to_list(lib:progname()), "'\n",
+ "export ERLC_EMULATOR\n",
+ Cmd, "\n",
+ "case $? in\n",
+ " 0) echo '_OK_';;\n",
+ " *) echo '_ERROR_';;\n",
+ "esac\n"]};
+run_command(_Dir, Other, _Cmd) ->
+ M = io_lib:format("Don't know how to test exit code for ~p", [Other]),
+ test_server:fail(lists:flatten(M)).
diff --git a/erts/test/erlc_SUITE_data/include/erl_test.hrl b/erts/test/erlc_SUITE_data/include/erl_test.hrl
new file mode 100644
index 0000000000..fd89cb2f60
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/include/erl_test.hrl
@@ -0,0 +1,19 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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%
+%%
+-record(person, {name, shoe_size}).
diff --git a/erts/test/erlc_SUITE_data/src/BAD-MIB.mib b/erts/test/erlc_SUITE_data/src/BAD-MIB.mib
new file mode 100644
index 0000000000..93bde356f4
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/BAD-MIB.mib
@@ -0,0 +1 @@
+All mibs are bad!
diff --git a/erts/test/erlc_SUITE_data/src/GOOD-MIB.mib b/erts/test/erlc_SUITE_data/src/GOOD-MIB.mib
new file mode 100644
index 0000000000..af350ba891
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/GOOD-MIB.mib
@@ -0,0 +1,39 @@
+ GOOD-MIB DEFINITIONS ::= BEGIN
+
+ IMPORTS
+ mgmt
+ FROM RFC1155-SMI
+ OBJECT-TYPE
+ FROM RFC-1212;
+
+
+ -- textual conventions
+
+ DisplayString ::=
+ OCTET STRING
+
+ -- This data type is used to model textual information taken
+ -- from the NVT ASCII character set. By convention, objects
+ -- with this syntax are declared as having
+ -- the System group
+
+ -- Implementation of the System group is mandatory for all
+ -- systems. If an agent is not configured to have a value
+ -- for any of these variables, a string of length 0 is
+ -- returned.
+
+ sysDescr OBJECT-TYPE
+ SYNTAX DisplayString (SIZE (0..255))
+ ACCESS read-only
+ STATUS mandatory
+
+ DESCRIPTION
+ "A textual description of the entity. This value
+ should include the full name and version
+ identification of the system's hardware type,
+ software operating-system, and networking
+ software. It is mandatory that this only contain
+ printable ASCII characters."
+ ::= { mgmt 1 }
+
+ END
diff --git a/erts/test/erlc_SUITE_data/src/erl_test_bad.erl b/erts/test/erlc_SUITE_data/src/erl_test_bad.erl
new file mode 100644
index 0000000000..fb62f835ca
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/erl_test_bad.erl
@@ -0,0 +1,22 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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(erl_test_bad).
+
+-export([non_existing/1]).
diff --git a/erts/test/erlc_SUITE_data/src/erl_test_ok.erl b/erts/test/erlc_SUITE_data/src/erl_test_ok.erl
new file mode 100644
index 0000000000..50fa063a94
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/erl_test_ok.erl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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(erl_test_ok).
+-export([shoe_size/1]).
+
+-include("erl_test.hrl").
+
+shoe_size(#person{shoe_size=Size}) ->
+ Size.
+
+foo() ->
+ ok.
diff --git a/erts/test/erlc_SUITE_data/src/start_bad.script b/erts/test/erlc_SUITE_data/src/start_bad.script
new file mode 100644
index 0000000000..0cb903fabd
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/start_bad.script
@@ -0,0 +1 @@
+script,{"OTP APN 181 01","NT"}
diff --git a/erts/test/erlc_SUITE_data/src/start_ok.script b/erts/test/erlc_SUITE_data/src/start_ok.script
new file mode 100644
index 0000000000..4cd89f0439
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/start_ok.script
@@ -0,0 +1,207 @@
+{script,{"OTP APN 181 01","NT"},
+ [{preLoaded,[init,erl_prim_loader]},
+ {progress,preloaded},
+ {path,["$ROOT/lib/kernel/ebin",
+ "$ROOT/lib/stdlib/ebin"]},
+ {primLoad,[error_handler,
+ ets,
+ lib,
+ lists,
+ heart,
+ application_controller,
+ application_master,
+ application,
+ auth,
+ c,
+ calendar,
+ code,
+ erlang,
+ erl_distribution,
+ erl_parse,
+ erl_scan,
+ io_lib,
+ io_lib_format,
+ io_lib_fread,
+ io_lib_pretty,
+ error_logger,
+ file,
+ filename,
+ os,
+ gen,
+ gen_event,
+ gen_server,
+ global,
+ kernel,
+ net_kernel,
+ proc_lib,
+ rpc,
+ supervisor,
+ sys]},
+ {kernel_load_completed},
+ {progress,kernel_load_completed},
+ {primLoad,[group,
+ user,
+ user_drv,
+ kernel_config,
+ net,
+ erl_boot_server,
+ net_adm]},
+ {primLoad,[math,
+ random,
+ ordsets,
+ shell_default,
+ timer,
+ gen_fsm,
+ pg,
+ unix,
+ dict,
+ pool,
+ string,
+ digraph,
+ io,
+ epp,
+ queue,
+ erl_eval,
+ erl_id_trans,
+ shell,
+ erl_internal,
+ erl_lint,
+ edlin,
+ erl_pp,
+ error_logger_file_h,
+ error_logger_tty_h,
+ log_mf_h,
+ dets,
+ disk_log,
+ regexp,
+ slave,
+ supervisor_bridge]},
+ {progress,modules_loaded},
+ {kernelProcess,heart,{heart,start,[]}},
+ {kernelProcess,error_logger,{error_logger,start_link,[]}},
+ {kernelProcess,application_controller,
+ {application_controller,
+ start,
+ [{application,
+ kernel,
+ [{description,"ERTS CXC 138 10"},
+ {vsn,"NT"},
+ {modules,
+ [{application,1},
+ {erlang,1},
+ {group,1},
+ {rpc,1},
+ {application_controller,1},
+ {error_handler,1},
+ {heart,1},
+ {application_master,1},
+ {error_logger,1},
+ {init,1},
+ {user,1},
+ {auth,1},
+ {kernel,1},
+ {user_drv,1},
+ {code,1},
+ {kernel_config,1},
+ {net,1},
+ {erl_boot_server,1},
+ {erl_prim_loader,1},
+ {file,1},
+ {net_adm,1},
+ {erl_distribution,1},
+ {global,1},
+ {net_kernel,1}]},
+ {registered,
+ [init,
+ erl_prim_loader,
+ heart,
+ error_logger,
+ application_controller,
+ kernel_sup,
+ kernel_config,
+ net_sup,
+ net_kernel,
+ auth,
+ code_server,
+ file_server,
+ boot_server,
+ global_name_server,
+ rex,
+ user]},
+ {applications,[]},
+ {env,
+ [{error_logger,tty},
+ {os, nt}]},
+ {maxT,infinity},
+ {maxP,infinity},
+ {mod,{kernel,[]}}]}]}},
+ {progress,init_kernel_started},
+ {apply,{application,load,
+ [{application,
+ stdlib,
+ [{description,"ERTS CXC 138 10"},
+ {vsn,"NT"},
+ {modules,
+ [{c,1},
+ {gen,1},
+ {io_lib_format,1},
+ {math,1},
+ {random,1},
+ {sys,1},
+ {calendar,1},
+ {gen_event,1},
+ {io_lib_fread,1},
+ {ordsets,1},
+ {shell_default,1},
+ {timer,1},
+ {gen_fsm,1},
+ {io_lib_pretty,1},
+ {pg,1},
+ {slave,1},
+ {unix,1},
+ {dict,1},
+ {gen_server,1},
+ {lib,1},
+ {pool,1},
+ {string,1},
+ {digraph,1},
+ {io,1},
+ {lists,1},
+ {proc_lib,1},
+ {supervisor,1},
+ {epp,1},
+ {io_lib,1},
+ {log_mf_h,1},
+ {queue,1},
+ {erl_eval,1},
+ {erl_id_trans,1},
+ {shell,1},
+ {erl_internal,1},
+ {erl_lint,1},
+ {error_logger_file_h,1},
+ {erl_parse,1},
+ {error_logger_tty_h,1},
+ {edlin,1},
+ {erl_pp,1},
+ {ets,1},
+ {dets,1},
+ {disk_log,1},
+ {regexp,1},
+ {erl_scan,1},
+ {supervisor_bridge,1}]},
+ {registered,
+ [timer_server,
+ rsh_starter,
+ take_over_monitor,
+ pool_master,
+ dets,
+ disk_log]},
+ {applications,[kernel]},
+ {env,[]},
+ {maxT,infinity},
+ {maxP,infinity}]}]}},
+ {progress,applications_loaded},
+ {apply,{application,start,[kernel,permanent]}},
+ {apply,{application,start,[stdlib,permanent]}},
+ {apply,{c,erlangrc,[]}},
+ {progress,started}]}.
diff --git a/erts/test/erlc_SUITE_data/src/yecc_test_bad.yrl b/erts/test/erlc_SUITE_data/src/yecc_test_bad.yrl
new file mode 100644
index 0000000000..409718e24c
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/yecc_test_bad.yrl
@@ -0,0 +1,32 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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%
+%%
+
+foo
+
+Nonterminals
+form.
+
+Terminals
+atom dot.
+
+Rootsymbol form.
+
+form -> atom dot : '$1'.
+
+Erlang code.
diff --git a/erts/test/erlc_SUITE_data/src/yecc_test_ok.yrl b/erts/test/erlc_SUITE_data/src/yecc_test_ok.yrl
new file mode 100644
index 0000000000..a96085ac2d
--- /dev/null
+++ b/erts/test/erlc_SUITE_data/src/yecc_test_ok.yrl
@@ -0,0 +1,29 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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%
+%%
+Nonterminals
+form.
+
+Terminals
+atom dot.
+
+Rootsymbol form.
+
+form -> atom dot : '$1'.
+
+Erlang code.
diff --git a/erts/test/erlexec_SUITE.erl b/erts/test/erlexec_SUITE.erl
new file mode 100644
index 0000000000..fcf1e67e9e
--- /dev/null
+++ b/erts/test/erlexec_SUITE.erl
@@ -0,0 +1,437 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2007-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%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : erlexec_SUITE.erl
+%%% Author : Rickard Green <[email protected]>
+%%% Description : Test erlexec's command line parsing
+%%%
+%%% Created : 22 May 2007 by Rickard Green <[email protected]>
+%%%-------------------------------------------------------------------
+-module(erlexec_SUITE).
+
+
+%-define(line_trace, 1).
+
+-define(DEFAULT_TIMEOUT, ?t:minutes(1)).
+
+-export([all/1, init_per_testcase/2, fin_per_testcase/2]).
+
+-export([args_file/1, evil_args_file/1, env/1, args_file_env/1, otp_7461/1, otp_7461_remote/1, otp_8209/1]).
+
+-include("test_server.hrl").
+
+
+init_per_testcase(Case, Config) ->
+ Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
+ SavedEnv = save_env(),
+ [{testcase, Case}, {watchdog, Dog}, {erl_flags_env, SavedEnv} |Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ SavedEnv = ?config(erl_flags_env, Config),
+ restore_env(SavedEnv),
+ cleanup_nodes(),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(doc) -> [];
+all(suite) ->
+ [args_file, evil_args_file, env, args_file_env, otp_7461, otp_8209].
+
+
+otp_8209(doc) ->
+ ["Test that plain first argument does not "
+ "destroy -home switch [OTP-8209]"];
+otp_8209(suite) ->
+ [];
+otp_8209(Config) when is_list(Config) ->
+ ?line {ok,[[PName]]} = init:get_argument(progname),
+ ?line SNameS = "erlexec_test_01",
+ ?line SName = list_to_atom(SNameS++"@"++
+ hd(tl(string:tokens(atom_to_list(node()),"@")))),
+ ?line Cmd = PName ++ " dummy_param -sname "++SNameS++" -setcookie "++
+ atom_to_list(erlang:get_cookie()),
+ ?line open_port({spawn,Cmd},[]),
+ ?line pong = loop_ping(SName,40),
+ ?line {ok,[[_]]} = rpc:call(SName,init,get_argument,[home]),
+ ?line ["dummy_param"] = rpc:call(SName,init,get_plain_arguments,[]),
+ ?line ok = cleanup_nodes(),
+ ok.
+
+cleanup_nodes() ->
+ cleanup_node("erlexec_test_01",20).
+cleanup_node(SNameS,0) ->
+ {error, {would_not_die,list_to_atom(SNameS)}};
+cleanup_node(SNameS,N) ->
+ SName = list_to_atom(SNameS++"@"++
+ hd(tl(string:tokens(atom_to_list(node()),"@")))),
+ case rpc:call(SName,init,stop,[]) of
+ {badrpc,_} ->
+ ok;
+ ok ->
+ receive after 500 -> ok end,
+ cleanup_node(SNameS,N-1)
+ end.
+
+loop_ping(_,0) ->
+ pang;
+loop_ping(Node,N) ->
+ case net_adm:ping(Node) of
+ pang ->
+ receive
+ after 500 ->
+ ok
+ end,
+ loop_ping(Node, N-1);
+ pong ->
+ pong
+ end.
+
+args_file(doc) -> [];
+args_file(suite) -> [];
+args_file(Config) when is_list(Config) ->
+ ?line AFN1 = privfile("1", Config),
+ ?line AFN2 = privfile("2", Config),
+ ?line AFN3 = privfile("3", Config),
+ ?line AFN4 = privfile("4", Config),
+ ?line AFN5 = privfile("5", Config),
+ ?line AFN6 = privfile("6", Config),
+ ?line write_file(AFN1,
+ "-MiscArg2~n"
+ "# a comment +\\#1000~n"
+ "+\\#200 # another comment~n"
+ "~n"
+ "# another config file to read~n"
+ " -args_file ~s#acomment~n"
+ "~n"
+ "-MiscArg7~n"
+ "#~n"
+ "+\\#700~n"
+ "-extra +XtraArg6~n",
+ [AFN2]),
+ ?line write_file(AFN2,
+ "-MiscArg3~n"
+ "+\\#300~n"
+ "-args_file ~s~n"
+ "-MiscArg5~n"
+ "+\\#500#anothercomment -MiscArg10~n"
+ "-args_file ~s~n"
+ "-args_file ~s~n"
+ "-args_file ~s~n"
+ "-extra +XtraArg5~n",
+ [AFN3, AFN4, AFN5, AFN6]),
+ ?line write_file(AFN3,
+ "# comment again~n"
+ " -MiscArg4 +\\#400 -extra +XtraArg1"),
+ ?line write_file(AFN4,
+ " -MiscArg6 +\\#600 -extra +XtraArg2~n"
+ "+XtraArg3~n"
+ "+XtraArg4~n"
+ "# comment again~n"),
+ ?line write_file(AFN5, ""),
+ ?line write_file(AFN6, "-extra # +XtraArg10~n"),
+ ?line CmdLine = "+#100 -MiscArg1 "
+ ++ "-args_file " ++ AFN1
+ ++ " +#800 -MiscArg8 -extra +XtraArg7 +XtraArg8",
+ ?line {Emu, Misc, Extra} = emu_args(CmdLine),
+ ?line verify_args(["-#100", "-#200", "-#300", "-#400",
+ "-#500", "-#600", "-#700", "-#800"], Emu),
+ ?line verify_args(["-MiscArg1", "-MiscArg2", "-MiscArg3", "-MiscArg4",
+ "-MiscArg5", "-MiscArg6", "-MiscArg7", "-MiscArg8"],
+ Misc),
+ ?line verify_args(["+XtraArg1", "+XtraArg2", "+XtraArg3", "+XtraArg4",
+ "+XtraArg5", "+XtraArg6", "+XtraArg7", "+XtraArg8"],
+ Extra),
+ ?line verify_not_args(["-MiscArg10", "-#1000", "+XtraArg10",
+ "-MiscArg1", "-MiscArg2", "-MiscArg3", "-MiscArg4",
+ "-MiscArg5", "-MiscArg6", "-MiscArg7", "-MiscArg8",
+ "+XtraArg1", "+XtraArg2", "+XtraArg3", "+XtraArg4",
+ "+XtraArg5", "+XtraArg6", "+XtraArg7", "+XtraArg8"],
+ Emu),
+ ?line verify_not_args(["-MiscArg10", "-#1000", "+XtraArg10",
+ "-#100", "-#200", "-#300", "-#400",
+ "-#500", "-#600", "-#700", "-#800",
+ "+XtraArg1", "+XtraArg2", "+XtraArg3", "+XtraArg4",
+ "+XtraArg5", "+XtraArg6", "+XtraArg7", "+XtraArg8"],
+ Misc),
+ ?line verify_not_args(["-MiscArg10", "-#1000", "+XtraArg10",
+ "-#100", "-#200", "-#300", "-#400",
+ "-#500", "-#600", "-#700", "-#800",
+ "-MiscArg1", "-MiscArg2", "-MiscArg3", "-MiscArg4",
+ "-MiscArg5", "-MiscArg6", "-MiscArg7", "-MiscArg8"],
+ Extra),
+ ?line ok.
+
+evil_args_file(doc) -> [];
+evil_args_file(suite) -> [];
+evil_args_file(Config) when is_list(Config) ->
+ ?line Lim = 300,
+ ?line FNums = lists:seq(1, Lim),
+ lists:foreach(fun (End) when End == Lim ->
+ ?line AFN = privfile(integer_to_list(End), Config),
+ ?line write_file(AFN,
+ "-MiscArg~p ",
+ [End]);
+ (I) ->
+ ?line AFNX = privfile(integer_to_list(I), Config),
+ ?line AFNY = privfile(integer_to_list(I+1), Config),
+ {Frmt, Args} =
+ case I rem 2 of
+ 0 ->
+ {"-MiscArg~p -args_file ~s -MiscArg~p",
+ [I, AFNY, I]};
+ _ ->
+ {"-MiscArg~p -args_file ~s",
+ [I, AFNY]}
+ end,
+ ?line write_file(AFNX, Frmt, Args)
+ end,
+ FNums),
+ ?line {_Emu, Misc, _Extra} = emu_args("-args_file "
+ ++ privfile("1", Config)),
+ ?line ANums = FNums
+ ++ lists:reverse(lists:filter(fun (I) when I == Lim -> false;
+ (I) when I rem 2 == 0 -> true;
+ (_) -> false
+ end, FNums)),
+ ?line verify_args(lists:map(fun (I) -> "-MiscArg"++integer_to_list(I) end,
+ ANums),
+ Misc),
+ ?line ok.
+
+
+
+env(doc) -> [];
+env(suite) -> [];
+env(Config) when is_list(Config) ->
+ ?line os:putenv("ERL_AFLAGS", "-MiscArg1 +#100 -extra +XtraArg1 +XtraArg2"),
+ ?line CmdLine = "+#200 -MiscArg2 -extra +XtraArg3 +XtraArg4",
+ ?line os:putenv("ERL_FLAGS", "-MiscArg3 +#300 -extra +XtraArg5"),
+ ?line os:putenv("ERL_ZFLAGS", "-MiscArg4 +#400 -extra +XtraArg6"),
+ ?line {Emu, Misc, Extra} = emu_args(CmdLine),
+ ?line verify_args(["-#100", "-#200", "-#300", "-#400"], Emu),
+ ?line verify_args(["-MiscArg1", "-MiscArg2", "-MiscArg3", "-MiscArg4"],
+ Misc),
+ ?line verify_args(["+XtraArg1", "+XtraArg2", "+XtraArg3", "+XtraArg4",
+ "+XtraArg5", "+XtraArg6"],
+ Extra),
+ ?line ok.
+
+args_file_env(doc) -> [];
+args_file_env(suite) -> [];
+args_file_env(Config) when is_list(Config) ->
+ ?line AFN1 = privfile("1", Config),
+ ?line AFN2 = privfile("2", Config),
+ ?line write_file(AFN1, "-MiscArg2 +\\#200 -extra +XtraArg1"),
+ ?line write_file(AFN2, "-MiscArg3 +\\#400 -extra +XtraArg3"),
+ ?line os:putenv("ERL_AFLAGS",
+ "-MiscArg1 +#100 -args_file "++AFN1++ " -extra +XtraArg2"),
+ ?line CmdLine = "+#300 -args_file "++AFN2++" -MiscArg4 -extra +XtraArg4",
+ ?line os:putenv("ERL_FLAGS", "-MiscArg5 +#500 -extra +XtraArg5"),
+ ?line os:putenv("ERL_ZFLAGS", "-MiscArg6 +#600 -extra +XtraArg6"),
+ ?line {Emu, Misc, Extra} = emu_args(CmdLine),
+ ?line verify_args(["-#100", "-#200", "-#300", "-#400",
+ "-#500", "-#600"], Emu),
+ ?line verify_args(["-MiscArg1", "-MiscArg2", "-MiscArg3", "-MiscArg4",
+ "-MiscArg5", "-MiscArg6"],
+ Misc),
+ ?line verify_args(["+XtraArg1", "+XtraArg2", "+XtraArg3", "+XtraArg4",
+ "+XtraArg5", "+XtraArg6"],
+ Extra),
+ ?line ok.
+
+%% Make sure "erl -detached" survives when parent process group gets killed
+otp_7461(doc) -> [];
+otp_7461(suite) -> [];
+otp_7461(Config) when is_list(Config) ->
+ case os:type() of
+ {unix,_} ->
+ {NetStarted, _} = net_kernel:start([test_server, shortnames]),
+ try
+ net_kernel:monitor_nodes(true),
+ register(otp_7461, self()),
+
+ otp_7461_do(Config)
+ after
+ catch unregister(otp_7461),
+ catch net_kernel:monitor_nodes(false),
+ case NetStarted of
+ ok -> net_kernel:stop();
+ _ -> ok
+ end
+ end;
+ _ ->
+ {skip,"Only on Unix."}
+ end.
+
+otp_7461_do(Config) ->
+ io:format("alive=~p node=~p\n",[is_alive(), node()]),
+ TestProg = filename:join([?config(data_dir, Config), "erlexec_tests"]),
+ {ok, [[ErlProg]]} = init:get_argument(progname),
+ ?line Cmd = TestProg ++ " " ++ ErlProg ++
+ " -detached -sname " ++ get_nodename(otp_7461) ++
+ " -setcookie " ++ atom_to_list(erlang:get_cookie()) ++
+ " -pa " ++ filename:dirname(code:which(?MODULE)) ++
+ " -s erlexec_SUITE otp_7461_remote init " ++ atom_to_list(node()),
+
+ %% otp_7461 --------> erlexec_tests.c --------> cerl -detached
+ %% open_port fork+exec
+
+ io:format("spawn port prog ~p\n",[Cmd]),
+ ?line Port = open_port({spawn, Cmd}, [eof]),
+
+ io:format("Wait for node to connect...\n",[]),
+ ?line {nodeup, Slave} = receive Msg -> Msg
+ after 20*1000 -> timeout end,
+ io:format("Node alive: ~p\n", [Slave]),
+
+ ?line pong = net_adm:ping(Slave),
+ io:format("Ping ok towards ~p\n", [Slave]),
+
+ ?line Port ! { self(), {command, "K"}}, % Kill child process group
+ ?line {Port, {data, "K"}} = receive Msg2 -> Msg2 end,
+ ?line port_close(Port),
+
+ %% Now the actual test. Detached node should still be alive.
+ ?line pong = net_adm:ping(Slave),
+ io:format("Ping still ok towards ~p\n", [Slave]),
+
+ %% Halt node
+ ?line rpc:cast(Slave, ?MODULE, otp_7461_remote, [[halt, self()]]),
+
+ ?line {nodedown, Slave} = receive Msg3 -> Msg3
+ after 20*1000 -> timeout end,
+ io:format("Node dead: ~p\n", [Slave]),
+ ok.
+
+
+%% Executed on slave node
+otp_7461_remote([init, Master]) ->
+ io:format("otp_7461_remote(init,~p) at ~p\n",[Master, node()]),
+ net_kernel:connect_node(Master);
+otp_7461_remote([halt, Pid]) ->
+ io:format("halt order from ~p to node ~p\n",[Pid,node()]),
+ halt().
+
+
+
+%%
+%% Utils
+%%
+
+save_env() ->
+ {erl_flags,
+ os:getenv("ERL_AFLAGS"),
+ os:getenv("ERL_FLAGS"),
+ os:getenv("ERL_"++erlang:system_info(otp_release)++"_FLAGS"),
+ os:getenv("ERL_ZFLAGS")}.
+
+restore_env(EVar, false) when is_list(EVar) ->
+ restore_env(EVar, "");
+restore_env(EVar, "") when is_list(EVar) ->
+ case os:getenv(EVar) of
+ false -> ok;
+ "" -> ok;
+ " " -> ok;
+ _ -> os:putenv(EVar, " ")
+ end;
+restore_env(EVar, Value) when is_list(EVar), is_list(Value) ->
+ case os:getenv(EVar) of
+ Value -> ok;
+ _ -> os:putenv(EVar, Value)
+ end.
+
+restore_env({erl_flags, AFlgs, Flgs, RFlgs, ZFlgs}) ->
+ restore_env("ERL_AFLAGS", AFlgs),
+ restore_env("ERL_FLAGS", Flgs),
+ restore_env("ERL_"++erlang:system_info(otp_release)++"_FLAGS", RFlgs),
+ restore_env("ERL_ZFLAGS", ZFlgs),
+ ok.
+
+privfile(Name, Config) ->
+ filename:join([?config(priv_dir, Config),
+ atom_to_list(?config(testcase, Config)) ++ "." ++ Name]).
+
+write_file(FileName, Frmt) ->
+ write_file(FileName, Frmt, []).
+
+write_file(FileName, Frmt, Args) ->
+ {ok, File} = file:open(FileName, [write]),
+ io:format(File, Frmt, Args),
+ ok = file:close(File).
+
+verify_args([], _Ys) ->
+ ok;
+verify_args(Xs, []) ->
+ exit({args_not_found_in_order, Xs});
+verify_args([X|Xs], [X|Ys]) ->
+ verify_args(Xs, Ys);
+verify_args(Xs, [_Y|Ys]) ->
+ verify_args(Xs, Ys).
+
+verify_not_args(Xs, Ys) ->
+ lists:foreach(fun (X) ->
+ case lists:member(X, Ys) of
+ true -> exit({arg_present, X});
+ false -> ok
+ end
+ end,
+ Xs).
+
+emu_args(CmdLineArgs) ->
+ io:format("CmdLineArgs = ~s~n", [CmdLineArgs]),
+ {ok,[[Erl]]} = init:get_argument(progname),
+ EmuCL = os:cmd(Erl ++ " -emu_args_exit " ++ CmdLineArgs),
+ io:format("EmuCL = ~s", [EmuCL]),
+ split_emu_clt(string:tokens(EmuCL, [$ ,$\t,$\n,$\r])).
+
+split_emu_clt(EmuCLT) ->
+ split_emu_clt(EmuCLT, [], [], [], emu).
+
+split_emu_clt([], _Emu, _Misc, _Extra, emu) ->
+ exit(bad_cmd_line);
+split_emu_clt([], Emu, Misc, Extra, _Type) ->
+ {lists:reverse(Emu), lists:reverse(Misc), lists:reverse(Extra)};
+
+split_emu_clt(["--"|As], Emu, Misc, Extra, emu) ->
+ split_emu_clt(As, Emu, Misc, Extra, misc);
+split_emu_clt([A|As], Emu, Misc, Extra, emu = Type) ->
+ split_emu_clt(As, [A|Emu], Misc, Extra, Type);
+
+split_emu_clt(["-extra"|As], Emu, Misc, Extra, misc) ->
+ split_emu_clt(As, Emu, Misc, Extra, extra);
+split_emu_clt([A|As], Emu, Misc, Extra, misc = Type) ->
+ split_emu_clt(As, Emu, [A|Misc], Extra, Type);
+
+split_emu_clt([A|As], Emu, Misc, Extra, extra = Type) ->
+ split_emu_clt(As, Emu, Misc, [A|Extra], Type).
+
+
+get_nodename(T) ->
+ {A, B, C} = now(),
+ atom_to_list(T)
+ ++ "-"
+ ++ atom_to_list(?MODULE)
+ ++ "-"
+ ++ integer_to_list(A)
+ ++ "-"
+ ++ integer_to_list(B)
+ ++ "-"
+ ++ integer_to_list(C).
diff --git a/erts/test/erlexec_SUITE_data/Makefile.src b/erts/test/erlexec_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..b751547b8f
--- /dev/null
+++ b/erts/test/erlexec_SUITE_data/Makefile.src
@@ -0,0 +1,37 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2008-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%
+#
+
+CC = @CC@
+CFLAGS = @ERTS_CFLAGS@
+LIBS = @ERTS_LIBS@
+
+ERLX_T_CFLAGS = -Wall $(ERLX_DEFS) $(CFLAGS) @DEFS@
+
+GCC = .@DS@gccifier -CC"$(CC)"
+
+PROGS = erlexec_tests@exe@
+
+all: $(PROGS)
+
+gccifier@exe@: ..@DS@utils@[email protected]
+ $(CC) $(CFLAGS) -o gccifier@exe@ ..@DS@utils@[email protected] $(LIBS)
+
+erlexec_tests@exe@: gccifier@exe@ erlexec_tests.c
+ $(GCC) $(ERLX_T_CFLAGS) -o erlexec_tests@exe@ erlexec_tests.c
+
diff --git a/erts/test/erlexec_SUITE_data/erlexec_tests.c b/erts/test/erlexec_SUITE_data/erlexec_tests.c
new file mode 100644
index 0000000000..a49a0b21a8
--- /dev/null
+++ b/erts/test/erlexec_SUITE_data/erlexec_tests.c
@@ -0,0 +1,110 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2008-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%
+ */
+/* Used by test case otp_7461 to spawn a child process with a given
+ * command line. Child process group is killed by order received on stdin.
+ *
+ * Author: Sverker Eriksson
+ */
+
+#if defined (__WIN32__) || defined(VXWORKS) || defined(_OSE_)
+int main() {return 0;}
+
+#else /* UNIX only */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define TRY(cmd) if ((cmd) < 0) bail_out(#cmd " failed")
+
+static void bail_out(const char* msg)
+{
+ perror(msg);
+ exit(-1);
+}
+
+static void alarm_handler(int signo)
+{
+ fprintf(stderr, __FILE__" self terminating after timeout\n");
+ exit(1);
+}
+
+int main(int argc, char* argv[])
+{
+ pid_t child;
+ int ret;
+ char cmd;
+ int child_exit;
+
+ if (argc < 2) {
+ fprintf(stderr, "Must specify command to run in background\n");
+ exit(-1);
+ }
+ TRY(child=fork());
+
+ if (child == 0) { /* child */
+ pid_t gchild;
+ TRY(setpgid(getpid(), getpid())); /* create process group */
+
+ TRY(gchild=fork());
+ if (gchild == 0) { /* grandchild */
+ TRY(execvp(argv[1],&argv[1]));
+ }
+ exit(0);
+ }
+ /* parent */
+
+ signal(SIGALRM, alarm_handler);
+ alarm(10*60); /* suicide in case nothing happens */
+
+ TRY(wait(&child_exit));
+ if (!WIFEXITED(child_exit) || WEXITSTATUS(child_exit)!=0) {
+ fprintf(stderr, "child did not exit normally (status=%d)\n", child_exit);
+ exit(-1);
+ }
+
+ for (;;)
+ {
+ TRY(ret=read(STDIN_FILENO, &cmd, 1));
+ if (ret == 0) break; /* eof -> exit */
+ switch (cmd)
+ {
+ case 'K':
+ ret = kill(-child, SIGINT); /* child process _group_ */
+ if (ret < 0 && errno != ESRCH) {
+ bail_out("kill failed");
+ }
+ write(STDOUT_FILENO, &cmd, 1); /* echo ack */
+ break;
+ case '\n':
+ break;/* ignore (for interactive testing) */
+ default:
+ fprintf(stderr, "Unknown command '%c'\n", cmd);
+ exit(-1);
+ }
+ }
+
+ return 0;
+}
+
+#endif /* UNIX */
diff --git a/erts/test/ethread_SUITE.erl b/erts/test/ethread_SUITE.erl
new file mode 100644
index 0000000000..a8f4f5e90c
--- /dev/null
+++ b/erts/test/ethread_SUITE.erl
@@ -0,0 +1,365 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2004-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%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : ethread_SUITE.erl
+%%% Author : Rickard Green <[email protected]>
+%%% Description :
+%%%
+%%% Created : 17 Jun 2004 by Rickard Green <[email protected]>
+%%%-------------------------------------------------------------------
+-module(ethread_SUITE).
+-author('[email protected]').
+
+%-define(line_trace, 1).
+
+-define(DEFAULT_TIMEOUT, ?t:minutes(10)).
+
+-export([all/1, init_per_testcase/2, fin_per_testcase/2]).
+
+-export([create_join_thread/1,
+ equal_tids/1,
+ mutex/1,
+ try_lock_mutex/1,
+ recursive_mutex/1,
+ time_now/1,
+ cond_wait/1,
+ cond_timedwait/1,
+ broadcast/1,
+ detached_thread/1,
+ max_threads/1,
+ forksafety/1,
+ vfork/1,
+ tsd/1,
+ spinlock/1,
+ rwspinlock/1,
+ rwmutex/1,
+ atomic/1,
+ gate/1]).
+
+-include("test_server.hrl").
+
+tests() ->
+ [create_join_thread,
+ equal_tids,
+ mutex,
+ try_lock_mutex,
+ recursive_mutex,
+ time_now,
+ cond_wait,
+ cond_timedwait,
+ broadcast,
+ detached_thread,
+ max_threads,
+ forksafety,
+ vfork,
+ tsd,
+ spinlock,
+ rwspinlock,
+ rwmutex,
+ atomic,
+ gate].
+
+all(doc) -> [];
+all(suite) -> tests().
+
+
+%%
+%%
+%% The test-cases
+%%
+%%
+
+create_join_thread(doc) ->
+ ["Tests ethr_thr_create and ethr_thr_join."];
+create_join_thread(suite) ->
+ [];
+create_join_thread(Config) ->
+ run_case(Config, "create_join_thread", "").
+
+equal_tids(doc) ->
+ ["Tests ethr_equal_tids."];
+equal_tids(suite) ->
+ [];
+equal_tids(Config) ->
+ run_case(Config, "equal_tids", "").
+
+mutex(doc) ->
+ ["Tests mutexes."];
+mutex(suite) ->
+ [];
+mutex(Config) ->
+ run_case(Config, "mutex", "").
+
+try_lock_mutex(doc) ->
+ ["Tests try lock on mutex."];
+try_lock_mutex(suite) ->
+ [];
+try_lock_mutex(Config) ->
+ run_case(Config, "try_lock_mutex", "").
+
+recursive_mutex(doc) ->
+ ["Tests recursive mutexes."];
+recursive_mutex(suite) ->
+ [];
+recursive_mutex(Config) ->
+ run_case(Config, "recursive_mutex", "").
+
+time_now(doc) ->
+ ["Tests ethr_time_now by comparing time values with Erlang."];
+time_now(suite) ->
+ [];
+time_now(Config) ->
+ run_case(Config, "time_now", "", fun (P) ->
+ spawn_link(fun () ->
+ watchdog(P)
+ end)
+ end).
+
+wd_dispatch(P) ->
+ receive
+ bye ->
+ ?line true = port_command(P, "-1 "),
+ ?line bye;
+ L when is_list(L) ->
+ ?line true = port_command(P, L),
+ ?line wd_dispatch(P)
+ end.
+
+watchdog(Port) ->
+ ?line process_flag(priority, max),
+ ?line receive after 500 -> ok end,
+
+ ?line random:seed(),
+ ?line true = port_command(Port, "0 "),
+ ?line lists:foreach(fun (T) ->
+ erlang:send_after(T,
+ self(),
+ integer_to_list(T)
+ ++ " ")
+ end,
+ lists:usort(lists:map(fun (_) ->
+ random:uniform(4500)+500
+ end,
+ lists:duplicate(50,0)))),
+ ?line erlang:send_after(5100, self(), bye),
+
+ wd_dispatch(Port).
+
+cond_wait(doc) ->
+ ["Tests ethr_cond_wait with ethr_cond_signal and ethr_cond_broadcast."];
+cond_wait(suite) ->
+ [];
+cond_wait(Config) ->
+ run_case(Config, "cond_wait", "").
+
+cond_timedwait(doc) ->
+ ["Tests ethr_cond_timedwait with ethr_cond_signal and ethr_cond_broadcast."];
+cond_timedwait(suite) ->
+ [];
+cond_timedwait(Config) ->
+ run_case(Config, "cond_timedwait", "").
+
+broadcast(doc) ->
+ ["Tests that a ethr_cond_broadcast really wakes up all waiting threads"];
+broadcast(suite) ->
+ [];
+broadcast(Config) ->
+ run_case(Config, "broadcast", "").
+
+detached_thread(doc) ->
+ ["Tests detached threads."];
+detached_thread(suite) ->
+ [];
+detached_thread(Config) ->
+ run_case(Config, "detached_thread", "").
+
+max_threads(doc) ->
+ ["Tests maximum number of threads."];
+max_threads(suite) ->
+ [];
+max_threads(Config) ->
+ run_case(Config, "max_threads", "").
+
+forksafety(doc) ->
+ ["Tests forksafety."];
+forksafety(suite) ->
+ [];
+forksafety(Config) ->
+ run_case(Config, "forksafety", "").
+
+vfork(doc) ->
+ ["Tests vfork with threads."];
+vfork(suite) ->
+ case ?t:os_type() of
+ {unix, osf1} ->
+ {skip, "vfork() known to hang multi-threaded applications on osf1"};
+ _ ->
+ []
+ end;
+vfork(Config) ->
+ run_case(Config, "vfork", "").
+
+tsd(doc) ->
+ ["Tests thread specific data."];
+tsd(suite) ->
+ [];
+tsd(Config) ->
+ run_case(Config, "tsd", "").
+
+spinlock(doc) ->
+ ["Tests spinlocks."];
+spinlock(suite) ->
+ [];
+spinlock(Config) ->
+ run_case(Config, "spinlock", "").
+
+rwspinlock(doc) ->
+ ["Tests rwspinlocks."];
+rwspinlock(suite) ->
+ [];
+rwspinlock(Config) ->
+ run_case(Config, "rwspinlock", "").
+
+rwmutex(doc) ->
+ ["Tests rwmutexes."];
+rwmutex(suite) ->
+ [];
+rwmutex(Config) ->
+ run_case(Config, "rwmutex", "").
+
+atomic(doc) ->
+ ["Tests atomics."];
+atomic(suite) ->
+ [];
+atomic(Config) ->
+ run_case(Config, "atomic", "").
+
+gate(doc) ->
+ ["Tests gates."];
+gate(suite) ->
+ [];
+gate(Config) ->
+ run_case(Config, "gate", "").
+
+%%
+%%
+%% Auxiliary functions
+%%
+%%
+
+init_per_testcase(_Case, Config) ->
+ Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
+ [{watchdog, Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+-define(TESTPROG, "ethread_tests").
+-define(FAILED_MARKER, $E,$T,$H,$R,$-,$T,$E,$S,$T,$-,$F,$A,$I,$L,$U,$R,$E).
+-define(SKIPPED_MARKER, $E,$T,$H,$R,$-,$T,$E,$S,$T,$-,$S,$K,$I,$P).
+-define(SUCCESS_MARKER, $E,$T,$H,$R,$-,$T,$E,$S,$T,$-,$S,$U,$C,$C,$E,$S,$S).
+-define(PID_MARKER, $E,$T,$H,$R,$-,$T,$E,$S,$T,$-,$P,$I,$D).
+
+port_prog_killer(EProc, OSProc) when is_pid(EProc), is_list(OSProc) ->
+ ?line process_flag(trap_exit, true),
+ ?line Ref = erlang:monitor(process, EProc),
+ ?line receive
+ {'DOWN', Ref, _, _, Reason} when is_tuple(Reason),
+ element(1, Reason)
+ == timetrap_timeout ->
+ ?line Cmd = "kill -9 " ++ OSProc,
+ ?line ?t:format("Test case timed out. "
+ "Trying to kill port program.~n"
+ " Executing: ~p~n", [Cmd]),
+ ?line case os:cmd(Cmd) of
+ [] ->
+ ok;
+ OsCmdRes ->
+ ?line ?t:format(" ~s", [OsCmdRes])
+ end;
+ {'DOWN', Ref, _, _, _} ->
+ %% OSProc is assumed to have terminated by itself
+ ?line ok
+ end.
+
+get_line(_Port, eol, Data) ->
+ ?line Data;
+get_line(Port, noeol, Data) ->
+ ?line receive
+ {Port, {data, {Flag, NextData}}} ->
+ ?line get_line(Port, Flag, Data ++ NextData);
+ {Port, eof} ->
+ ?line ?t:fail(port_prog_unexpectedly_closed)
+ end.
+
+read_case_data(Port, TestCase) ->
+ ?line receive
+ {Port, {data, {eol, [?SUCCESS_MARKER]}}} ->
+ ?line ok;
+ {Port, {data, {Flag, [?SUCCESS_MARKER | CommentStart]}}} ->
+ ?line {comment, get_line(Port, Flag, CommentStart)};
+ {Port, {data, {Flag, [?SKIPPED_MARKER | CommentStart]}}} ->
+ ?line {skipped, get_line(Port, Flag, CommentStart)};
+ {Port, {data, {Flag, [?FAILED_MARKER | ReasonStart]}}} ->
+ ?line ?t:fail(get_line(Port, Flag, ReasonStart));
+ {Port, {data, {eol, [?PID_MARKER | PidStr]}}} ->
+ ?line ?t:format("Port program pid: ~s~n", [PidStr]),
+ ?line CaseProc = self(),
+ ?line list_to_integer(PidStr), % Sanity check
+ spawn_opt(fun () ->
+ port_prog_killer(CaseProc, PidStr)
+ end,
+ [{priority, max}, link]),
+ read_case_data(Port, TestCase);
+ {Port, {data, {Flag, LineStart}}} ->
+ ?line ?t:format("~s~n", [get_line(Port, Flag, LineStart)]),
+ read_case_data(Port, TestCase);
+ {Port, eof} ->
+ ?line ?t:fail(port_prog_unexpectedly_closed)
+ end.
+
+run_case(Config, Test, TestArgs) ->
+ run_case(Config, Test, TestArgs, fun (_Port) -> ok end).
+
+run_case(Config, Test, TestArgs, Fun) ->
+ TestProg = filename:join([?config(data_dir, Config), ?TESTPROG]),
+ Cmd = TestProg ++ " " ++ Test ++ " " ++ TestArgs,
+ case catch open_port({spawn, Cmd}, [stream,
+ use_stdio,
+ stderr_to_stdout,
+ eof,
+ {line, 1024}]) of
+ Port when is_port(Port) ->
+ ?line Fun(Port),
+ ?line CaseResult = read_case_data(Port, Test),
+ ?line receive
+ {Port, eof} ->
+ ?line ok
+ end,
+ ?line CaseResult;
+ Error ->
+ ?line ?t:fail({open_port_failed, Error})
+ end.
+
+
+
+
diff --git a/erts/test/ethread_SUITE_data/Makefile.src b/erts/test/ethread_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..132b23344c
--- /dev/null
+++ b/erts/test/ethread_SUITE_data/Makefile.src
@@ -0,0 +1,41 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2004-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%
+#
+
+include @erts_lib_include_internal_generated@@[email protected]
+include @erts_lib_include_internal_generated@@DS@erts_internal.mk
+
+CC = @CC@
+CFLAGS = @ERTS_CFLAGS@
+LIBS = @ERTS_LIBS@
+
+ETHR_T_CFLAGS = -Wall $(ETHR_DEFS) $(CFLAGS) @DEFS@ -I@erts_lib_include_internal@ -I@erts_lib_include_internal_generated@
+ETHR_T_LIBS = $(LIBS) -L@erts_lib_internal_path@ $(ETHR_LIBS) $(ERTS_INTERNAL_X_LIBS)
+
+GCC = .@DS@gccifier -CC"$(CC)"
+
+PROGS = ethread_tests@exe@
+
+all: $(PROGS)
+
+gccifier@exe@: ..@DS@utils@[email protected]
+ $(CC) $(CFLAGS) -o gccifier@exe@ ..@DS@utils@[email protected] $(LIBS)
+
+ethread_tests@exe@: gccifier@exe@ ethread_tests.c
+ $(GCC) $(ETHR_T_CFLAGS) -o ethread_tests@exe@ ethread_tests.c -lerts_internal_r $(ETHR_T_LIBS)
+
diff --git a/erts/test/ethread_SUITE_data/ethread_tests.c b/erts/test/ethread_SUITE_data/ethread_tests.c
new file mode 100644
index 0000000000..f779f13c51
--- /dev/null
+++ b/erts/test/ethread_SUITE_data/ethread_tests.c
@@ -0,0 +1,2403 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-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%
+ */
+
+/*
+ * Description: Test suite for the ethread thread library.
+ * Author: Rickard Green
+ */
+
+#define ETHR_NO_SUPP_THR_LIB_NOT_FATAL
+#include "ethread.h"
+#include "erl_misc_utils.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#ifndef __WIN32__
+#include <unistd.h>
+#endif
+#include <limits.h>
+
+/*
+ * Auxiliary functions
+ */
+
+#define PRINT_VA_LIST(FRMT) \
+do { \
+ if (FRMT && FRMT != '\0') { \
+ va_list args; \
+ va_start(args, FRMT); \
+ vfprintf(stderr, FRMT, args); \
+ va_end(args); \
+ } \
+} while (0)
+
+#define ASSERT(B) \
+do { \
+ if (!(B)) \
+ fail("%s:%d: Assertion \"%s\" failed!",__FILE__,__LINE__,#B); \
+} while (0)
+
+
+#define ASSERT_PRINT(B, PRNT) \
+do { \
+ if (!(B)) { \
+ print PRNT; \
+ fail("%s:%d: Assertion \"%s\" failed!",__FILE__,__LINE__,#B); \
+ } \
+} while (0)
+
+#define ASSERT_EQ(VAR, VAL, FSTR) \
+do { \
+ if ((VAR) != (VAL)) { \
+ print("%s=" FSTR "\n", #VAR, (VAR)); \
+ fail("%s:%d: Assertion \"%s == " FSTR "\" failed!", \
+ __FILE__, __LINE__, #VAR, (VAL)); \
+ } \
+} while (0)
+
+#ifdef __WIN32_
+#define EOL "\r\n"
+#else
+#define EOL "\n"
+#endif
+
+static void
+print_eol(void)
+{
+ fprintf(stderr, EOL);
+}
+
+static void print_line(char *frmt,...)
+{
+ PRINT_VA_LIST(frmt);
+ print_eol();
+}
+
+static void print(char *frmt,...)
+{
+ PRINT_VA_LIST(frmt);
+}
+
+static void fail(char *frmt,...)
+{
+ char *abrt_env;
+ print_eol();
+ fprintf(stderr, "ETHR-TEST-FAILURE");
+ PRINT_VA_LIST(frmt);
+ print_eol();
+ abrt_env = getenv("ERL_ABORT_ON_FAILURE");
+ if (abrt_env && strcmp("true", abrt_env) == 0)
+ abort();
+ else
+ exit(1);
+}
+
+static void skip(char *frmt,...)
+{
+ print_eol();
+ fprintf(stderr, "ETHR-TEST-SKIP");
+ PRINT_VA_LIST(frmt);
+ print_eol();
+ exit(0);
+}
+
+static void succeed(char *frmt,...)
+{
+ print_eol();
+ fprintf(stderr, "ETHR-TEST-SUCCESS");
+ PRINT_VA_LIST(frmt);
+ print_eol();
+ exit(0);
+}
+
+static void
+do_sleep(unsigned secs)
+{
+ while (erts_milli_sleep(secs*1000) != 0);
+}
+
+#define WAIT_UNTIL_INTERVAL 10
+
+#define WAIT_UNTIL_LIM(TEST, LIM) \
+do { \
+ int ms__ = (LIM)*1000; \
+ while (!(TEST)) { \
+ while (erts_milli_sleep(WAIT_UNTIL_INTERVAL) != 0); \
+ ms__ -= WAIT_UNTIL_INTERVAL; \
+ if (ms__ <= 0) \
+ break; \
+ } \
+} while (0)
+
+static void
+send_my_pid(void)
+{
+#ifndef __WIN32__
+ int pid = (int) getpid();
+ fprintf(stderr, EOL "ETHR-TEST-PID%d" EOL, pid);
+#endif
+}
+
+/*
+ * The test-cases
+ */
+
+#ifndef ETHR_NO_THREAD_LIB
+
+/*
+ * The create join thread test case.
+ *
+ * Tests ethr_thr_create and ethr_thr_join.
+ */
+
+#define CJTT_NO_THREADS 64
+ethr_tid cjtt_tids[CJTT_NO_THREADS + 1];
+int cjtt_ix[CJTT_NO_THREADS + 1];
+int cjtt_res[CJTT_NO_THREADS + 1];
+void *cjtt_thread(void *vpix)
+{
+ int ix = *((int *) vpix);
+ cjtt_res[ix] = ix;
+ return (void *) &cjtt_res[ix];
+}
+
+static void
+create_join_thread_test(void)
+{
+ int i, res;
+
+ for (i = 1; i <= CJTT_NO_THREADS; i++) {
+ cjtt_ix[i] = i;
+ cjtt_res[i] = 0;
+ }
+
+ for (i = 1; i <= CJTT_NO_THREADS; i++) {
+ res = ethr_thr_create(&cjtt_tids[i],
+ cjtt_thread,
+ (void *) &cjtt_ix[i],
+ NULL);
+ ASSERT(res == 0);
+ }
+
+ for (i = 1; i <= CJTT_NO_THREADS; i++) {
+ int *tres;
+ res = ethr_thr_join(cjtt_tids[i], (void **) &tres);
+ ASSERT(res == 0);
+ ASSERT(tres == &cjtt_res[i]);
+ ASSERT(cjtt_res[i] == i);
+ }
+
+}
+
+
+/*
+ * The eq tid test case.
+ *
+ * Tests ethr_equal_tids.
+ */
+
+#define ETT_THREADS 100000
+
+static ethr_tid ett_tids[3];
+static ethr_mutex ett_mutex = ETHR_MUTEX_INITER;
+static ethr_cond ett_cond = ETHR_COND_INITER;
+static int ett_terminate;
+
+static void *
+ett_thread(void *my_tid)
+{
+
+ ASSERT(!ethr_equal_tids(ethr_self(), ett_tids[0]));
+ ASSERT(ethr_equal_tids(ethr_self(), *((ethr_tid *) my_tid)));
+
+ return NULL;
+}
+
+static void *
+ett_thread2(void *unused)
+{
+ int res;
+ res = ethr_mutex_lock(&ett_mutex);
+ ASSERT(res == 0);
+ while (!ett_terminate) {
+ res = ethr_cond_wait(&ett_cond, &ett_mutex);
+ ASSERT(res == 0);
+ }
+ res = ethr_mutex_unlock(&ett_mutex);
+ ASSERT(res == 0);
+ return NULL;
+}
+
+static void
+equal_tids_test(void)
+{
+ int res, i;
+
+ ett_tids[0] = ethr_self();
+
+ res = ethr_thr_create(&ett_tids[1], ett_thread, (void *) &ett_tids[1], NULL);
+ ASSERT(res == 0);
+
+ ASSERT(ethr_equal_tids(ethr_self(), ett_tids[0]));
+ ASSERT(!ethr_equal_tids(ethr_self(), ett_tids[1]));
+
+ res = ethr_thr_join(ett_tids[1], NULL);
+
+ res = ethr_thr_create(&ett_tids[2], ett_thread, (void *) &ett_tids[2], NULL);
+ ASSERT(res == 0);
+
+ ASSERT(ethr_equal_tids(ethr_self(), ett_tids[0]));
+ ASSERT(!ethr_equal_tids(ethr_self(), ett_tids[1]));
+ ASSERT(!ethr_equal_tids(ethr_self(), ett_tids[2]));
+
+#if 0
+ /* This fails on some linux platforms. Until we decides if a tid
+ * is allowed to be reused right away or not, we disable the test.
+ */
+
+ ASSERT(!ethr_equal_tids(ett_tids[1], ett_tids[2]));
+#endif
+
+ res = ethr_thr_join(ett_tids[2], NULL);
+ ASSERT(res == 0);
+
+ /* Second part of test */
+
+ ett_terminate = 0;
+
+ res = ethr_thr_create(&ett_tids[1], ett_thread2, NULL, NULL);
+ ASSERT(res == 0);
+
+ ASSERT(!ethr_equal_tids(ett_tids[0], ett_tids[1]));
+
+ for (i = 0; i < ETT_THREADS; i++) {
+ res = ethr_thr_create(&ett_tids[2], ett_thread, (void*)&ett_tids[2], NULL);
+ ASSERT(res == 0);
+
+ ASSERT(!ethr_equal_tids(ett_tids[0], ett_tids[2]));
+ ASSERT(!ethr_equal_tids(ett_tids[1], ett_tids[2]));
+
+ res = ethr_thr_join(ett_tids[2], NULL);
+ ASSERT(res == 0);
+ }
+
+ res = ethr_mutex_lock(&ett_mutex);
+ ASSERT(res == 0);
+ ett_terminate = 1;
+ res = ethr_cond_signal(&ett_cond);
+ ASSERT(res == 0);
+ res = ethr_mutex_unlock(&ett_mutex);
+ ASSERT(res == 0);
+ res = ethr_thr_join(ett_tids[1], NULL);
+ ASSERT(res == 0);
+
+ res = ethr_cond_destroy(&ett_cond);
+ ASSERT(res == 0);
+ res = ethr_mutex_destroy(&ett_mutex);
+ ASSERT(res == 0);
+
+}
+
+/*
+ * The mutex test case.
+ *
+ * Tests mutexes.
+ */
+
+static ethr_mutex mt_mutex = ETHR_MUTEX_INITER;
+static int mt_data;
+
+void *
+mt_thread(void *unused)
+{
+ int res;
+
+ print_line("Aux thread tries to lock mutex");
+ res = ethr_mutex_lock(&mt_mutex);
+ ASSERT(res == 0);
+ print_line("Aux thread locked mutex");
+
+ ASSERT(mt_data == 0);
+
+ mt_data = 1;
+ print_line("Aux thread wrote");
+
+ print_line("Aux thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Aux thread woke up");
+
+ ASSERT(mt_data == 1);
+
+ res = ethr_mutex_unlock(&mt_mutex);
+ ASSERT(res == 0);
+ print_line("Aux thread unlocked mutex");
+
+ return NULL;
+}
+
+
+static void
+mutex_test(void)
+{
+ int do_restart = 1;
+ int res;
+ ethr_tid tid;
+
+ print_line("Running test with statically initialized mutex");
+
+ restart:
+ mt_data = 0;
+
+ print_line("Main thread tries to lock mutex");
+ res = ethr_mutex_lock(&mt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread locked mutex");
+
+ ASSERT(mt_data == 0);
+
+ print_line("Main thread about to create aux thread");
+ res = ethr_thr_create(&tid, mt_thread, NULL, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread created aux thread");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(mt_data == 0);
+
+ res = ethr_mutex_unlock(&mt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread unlocked mutex");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ print_line("Main thread tries to lock mutex");
+ res = ethr_mutex_lock(&mt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread locked mutex");
+
+ ASSERT(mt_data == 1);
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(mt_data == 1);
+
+ res = ethr_mutex_unlock(&mt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread unlocked mutex");
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread joined aux thread");
+
+ res = ethr_mutex_destroy(&mt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread destroyed mutex");
+
+ if (do_restart) {
+ do_restart = 0;
+
+ print_line("Running test with dynamically initialized mutex");
+
+ print_line("Trying to initialize mutex");
+ res = ethr_mutex_init(&mt_mutex);
+ ASSERT(res == 0);
+ print_line("Initialized mutex");
+
+ goto restart;
+
+ }
+
+}
+
+/*
+ * The try lock mutex test case.
+ *
+ * Tests try lock mutex operation.
+ */
+
+static ethr_mutex tlmt_mtx1 = ETHR_MUTEX_INITER;
+static ethr_mutex tlmt_mtx2 = ETHR_MUTEX_INITER;
+static ethr_cond tlmt_cnd2 = ETHR_COND_INITER;
+
+static int tlmt_mtx1_locked;
+static int tlmt_mtx1_do_unlock;
+
+static void *
+tlmt_thread(void *unused)
+{
+ int res;
+
+ res = ethr_mutex_lock(&tlmt_mtx1);
+ ASSERT(res == 0);
+ res = ethr_mutex_lock(&tlmt_mtx2);
+ ASSERT(res == 0);
+
+ tlmt_mtx1_locked = 1;
+ res = ethr_cond_signal(&tlmt_cnd2);
+ ASSERT(res == 0);
+
+ while (!tlmt_mtx1_do_unlock) {
+ res = ethr_cond_wait(&tlmt_cnd2, &tlmt_mtx2);
+ ASSERT(res == 0 || res == EINTR);
+ }
+
+ res = ethr_mutex_unlock(&tlmt_mtx2);
+ ASSERT(res == 0);
+ res = ethr_mutex_unlock(&tlmt_mtx1);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_lock(&tlmt_mtx2);
+ ASSERT(res == 0);
+ tlmt_mtx1_locked = 0;
+ res = ethr_cond_signal(&tlmt_cnd2);
+ ASSERT(res == 0);
+ res = ethr_mutex_unlock(&tlmt_mtx2);
+ ASSERT(res == 0);
+
+ return NULL;
+}
+
+static void
+try_lock_mutex_test(void)
+{
+ int i, res;
+ ethr_tid tid;
+
+ tlmt_mtx1_locked = 0;
+ tlmt_mtx1_do_unlock = 0;
+
+ res = ethr_thr_create(&tid, tlmt_thread, NULL, NULL);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_lock(&tlmt_mtx2);
+ ASSERT(res == 0);
+
+ while (!tlmt_mtx1_locked) {
+ res = ethr_cond_wait(&tlmt_cnd2, &tlmt_mtx2);
+ ASSERT(res == 0 || res == EINTR);
+ }
+
+ res = ethr_mutex_unlock(&tlmt_mtx2);
+ ASSERT(res == 0);
+
+ for (i = 0; i < 10; i++) {
+ res = ethr_mutex_trylock(&tlmt_mtx1);
+ ASSERT(res == EBUSY);
+ }
+
+ res = ethr_mutex_lock(&tlmt_mtx2);
+ ASSERT(res == 0);
+
+ tlmt_mtx1_do_unlock = 1;
+ res = ethr_cond_signal(&tlmt_cnd2);
+ ASSERT(res == 0);
+
+ while (tlmt_mtx1_locked) {
+ res = ethr_cond_wait(&tlmt_cnd2, &tlmt_mtx2);
+ ASSERT(res == 0 || res == EINTR);
+ }
+
+ res = ethr_mutex_unlock(&tlmt_mtx2);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_trylock(&tlmt_mtx1);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_unlock(&tlmt_mtx1);
+ ASSERT(res == 0);
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_destroy(&tlmt_mtx1);
+ ASSERT(res == 0);
+ res = ethr_mutex_destroy(&tlmt_mtx2);
+ ASSERT(res == 0);
+ res = ethr_cond_destroy(&tlmt_cnd2);
+ ASSERT(res == 0);
+}
+
+/*
+ * The recursive mutex test case.
+ *
+ * Tests recursive mutexes.
+ */
+
+#ifdef ETHR_HAVE_ETHR_REC_MUTEX_INIT
+
+static ethr_mutex rmt_mutex
+#ifdef ETHR_REC_MUTEX_INITER
+ = ETHR_REC_MUTEX_INITER
+#endif
+ ;
+static int rmt_data;
+
+void *
+rmt_thread(void *unused)
+{
+ int res;
+
+ print_line("Aux thread tries to lock mutex");
+ res = ethr_mutex_lock(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Aux thread locked mutex");
+
+ ASSERT(rmt_data == 0);
+
+ rmt_data = 1;
+ print_line("Aux thread wrote");
+
+ print_line("Aux thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Aux thread woke up");
+
+ ASSERT(rmt_data == 1);
+
+ res = ethr_mutex_unlock(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Aux thread unlocked mutex");
+
+ return NULL;
+}
+
+#endif
+
+static void
+recursive_mutex_test(void)
+{
+#ifdef ETHR_HAVE_ETHR_REC_MUTEX_INIT
+ int do_restart = 1;
+ int res;
+ ethr_tid tid;
+
+#ifdef ETHR_REC_MUTEX_INITER
+ print_line("Running test with statically initialized mutex");
+#else
+ goto dynamic_init;
+#endif
+
+ restart:
+ rmt_data = 0;
+
+ print_line("Main thread tries to lock mutex");
+ res = ethr_mutex_lock(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread locked mutex");
+
+ print_line("Main thread tries to lock mutex again");
+ res = ethr_mutex_lock(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread locked mutex again");
+
+ ASSERT(rmt_data == 0);
+
+ print_line("Main thread about to create aux thread");
+ res = ethr_thr_create(&tid, rmt_thread, NULL, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread created aux thread");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(rmt_data == 0);
+
+ res = ethr_mutex_unlock(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread unlocked mutex");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(rmt_data == 0);
+
+ res = ethr_mutex_unlock(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread unlocked mutex again");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ print_line("Main thread tries to lock mutex");
+ res = ethr_mutex_lock(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread locked mutex");
+
+ ASSERT(rmt_data == 1);
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(rmt_data == 1);
+
+ res = ethr_mutex_unlock(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread unlocked mutex");
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread joined aux thread");
+
+ res = ethr_mutex_destroy(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Main thread destroyed mutex");
+
+ if (do_restart) {
+#ifndef ETHR_REC_MUTEX_INITER
+ dynamic_init:
+#endif
+ do_restart = 0;
+
+ print_line("Running test with dynamically initialized mutex");
+
+ print_line("Trying to initialize mutex");
+ res = ethr_rec_mutex_init(&rmt_mutex);
+ ASSERT(res == 0);
+ print_line("Initialized mutex");
+
+ goto restart;
+ }
+
+#ifndef ETHR_REC_MUTEX_INITER
+ succeed("Static initializer for recursive mutexes not supported");
+#endif
+
+#else /* #ifdef ETHR_HAVE_ETHR_REC_MUTEX_INIT */
+ skip("Recursive mutexes not supported");
+#endif /* #ifdef ETHR_HAVE_ETHR_REC_MUTEX_INIT */
+}
+
+/*
+ * The time now test.
+ *
+ * Tests ethr_time_now by comparing time values with Erlang.
+ */
+#define TNT_MAX_TIME_DIFF 200000
+#define TNT_MAX_TIME_VALUES 52
+
+static void
+time_now_test(void)
+{
+ int scanf_res, time_now_res, i, no_values, max_abs_diff;
+ static ethr_timeval tv[TNT_MAX_TIME_VALUES];
+ static int ms[TNT_MAX_TIME_VALUES];
+
+ i = 0;
+ do {
+ ASSERT(i < TNT_MAX_TIME_VALUES);
+ scanf_res = scanf("%d", &ms[i]);
+ time_now_res = ethr_time_now(&tv[i]);
+ ASSERT(scanf_res == 1);
+ ASSERT(time_now_res == 0);
+#if 0
+ print_line("Got %d; %ld:%ld", ms[i], tv[i].tv_sec, tv[i].tv_nsec);
+#endif
+ i++;
+ } while (ms[i-1] >= 0);
+
+ no_values = i-1;
+
+ ASSERT(ms[0] == 0);
+
+ print_line("TNT_MAX_TIME_DIFF = %d (us)", TNT_MAX_TIME_DIFF);
+
+ max_abs_diff = 0;
+
+ for (i = 1; i < no_values; i++) {
+ long diff;
+ long tn_us;
+ long e_us;
+
+ tn_us = (tv[i].tv_sec - tv[0].tv_sec) * 1000000;
+ tn_us += (tv[i].tv_nsec - tv[0].tv_nsec)/1000;
+
+ e_us = ms[i]*1000;
+
+ diff = e_us - tn_us;
+
+ print_line("Erlang time = %ld us; ethr_time_now = %ld us; diff %ld us",
+ e_us, tn_us, diff);
+
+ if (max_abs_diff < abs((int) diff)) {
+ max_abs_diff = abs((int) diff);
+ }
+
+ ASSERT(e_us - TNT_MAX_TIME_DIFF <= tn_us);
+ ASSERT(tn_us <= e_us + TNT_MAX_TIME_DIFF);
+ }
+
+ print_line("Max absolute diff = %d us", max_abs_diff);
+ succeed("Max absolute diff = %d us", max_abs_diff);
+}
+
+/*
+ * The cond wait test case.
+ *
+ * Tests ethr_cond_wait with ethr_cond_signal and ethr_cond_broadcast.
+ */
+
+
+static ethr_mutex cwt_mutex = ETHR_MUTEX_INITER;
+static ethr_cond cwt_cond = ETHR_COND_INITER;
+static int cwt_counter;
+
+void *
+cwt_thread(void *is_timedwait_test_ptr)
+{
+ int use_timedwait = *((int *) is_timedwait_test_ptr);
+ int res;
+
+ res = ethr_mutex_lock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ if (use_timedwait) {
+ ethr_timeval tv;
+ res = ethr_time_now(&tv);
+ ASSERT(res == 0);
+ tv.tv_sec += 3600; /* Make sure we won't time out */
+
+ do {
+ res = ethr_cond_timedwait(&cwt_cond, &cwt_mutex, &tv);
+ } while (res == EINTR);
+ ASSERT(res == 0);
+ }
+ else {
+ do {
+ res = ethr_cond_wait(&cwt_cond, &cwt_mutex);
+ } while (res == EINTR);
+ ASSERT(res == 0);
+ }
+
+ cwt_counter++;
+
+ res = ethr_mutex_unlock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ return NULL;
+}
+
+static void
+cond_wait_test(int is_timedwait_test)
+{
+ int do_restart = !is_timedwait_test;
+ ethr_tid tid1, tid2;
+ int res;
+
+ if (!is_timedwait_test)
+ print_line("Running test with statically initialized mutex and cond");
+
+ restart:
+ /* Wake with signal */
+
+ cwt_counter = 0;
+
+ res = ethr_thr_create(&tid1, cwt_thread, (void *) &is_timedwait_test, NULL);
+ ASSERT(res == 0);
+ res = ethr_thr_create(&tid2, cwt_thread, (void *) &is_timedwait_test, NULL);
+ ASSERT(res == 0);
+
+ do_sleep(1); /* Make sure threads waits on cond var */
+
+ res = ethr_mutex_lock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_cond_signal(&cwt_cond); /* Wake one thread */
+ ASSERT(res == 0);
+
+ do_sleep(1); /* Make sure awakened thread waits on mutex */
+
+ ASSERT(cwt_counter == 0);
+
+ res = ethr_mutex_unlock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ do_sleep(1); /* Let awakened thread proceed */
+
+ res = ethr_mutex_lock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ ASSERT(cwt_counter == 1);
+
+ res = ethr_cond_signal(&cwt_cond); /* Wake the other thread */
+ ASSERT(res == 0);
+
+ do_sleep(1); /* Make sure awakened thread waits on mutex */
+
+ ASSERT(cwt_counter == 1);
+
+ res = ethr_mutex_unlock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ do_sleep(1); /* Let awakened thread proceed */
+
+ res = ethr_mutex_lock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ ASSERT(cwt_counter == 2);
+
+ res = ethr_mutex_unlock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_thr_join(tid1, NULL);
+ ASSERT(res == 0);
+
+ res = ethr_thr_join(tid2, NULL);
+ ASSERT(res == 0);
+
+
+ /* Wake with broadcast */
+
+ cwt_counter = 0;
+
+ res = ethr_thr_create(&tid1, cwt_thread, (void *) &is_timedwait_test, NULL);
+ ASSERT(res == 0);
+ res = ethr_thr_create(&tid2, cwt_thread, (void *) &is_timedwait_test, NULL);
+ ASSERT(res == 0);
+
+ do_sleep(1); /* Make sure threads waits on cond var */
+
+ res = ethr_mutex_lock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_cond_broadcast(&cwt_cond); /* Wake the threads */
+ ASSERT(res == 0);
+
+ do_sleep(1); /* Make sure awakened threads wait on mutex */
+
+ ASSERT(cwt_counter == 0);
+
+ res = ethr_mutex_unlock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ do_sleep(1); /* Let awakened threads proceed */
+
+ res = ethr_mutex_lock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ ASSERT(cwt_counter == 2);
+
+ res = ethr_mutex_unlock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_thr_join(tid1, NULL);
+ ASSERT(res == 0);
+
+ res = ethr_thr_join(tid2, NULL);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_destroy(&cwt_mutex);
+ ASSERT(res == 0);
+ res = ethr_cond_destroy(&cwt_cond);
+ ASSERT(res == 0);
+
+ if (do_restart) {
+ do_restart = 0;
+ res = ethr_mutex_init(&cwt_mutex);
+ ASSERT(res == 0);
+ res = ethr_cond_init(&cwt_cond);
+ ASSERT(res == 0);
+ print_line("Running test with dynamically initialized mutex and cond");
+ goto restart;
+ }
+}
+
+/*
+ * The cond timedwait test case.
+ *
+ * Tests ethr_cond_timedwait with ethr_cond_signal and ethr_cond_broadcast.
+ */
+
+#define CTWT_MAX_TIME_DIFF 100000
+
+static long
+ctwt_check_timeout(long to)
+{
+ int res;
+ ethr_timeval tva, tvb;
+ long diff, abs_diff;
+
+ res = ethr_time_now(&tva);
+ ASSERT(res == 0);
+
+ tva.tv_sec += to / 1000;
+ tva.tv_nsec += (to % 1000) * 1000000;
+ if (tva.tv_nsec >= 1000000000) {
+ tva.tv_sec++;
+ tva.tv_nsec -= 1000000000;
+ ASSERT(tva.tv_nsec < 1000000000);
+ }
+
+ do {
+ res = ethr_cond_timedwait(&cwt_cond, &cwt_mutex, &tva);
+ } while (res == EINTR);
+ ASSERT(res == ETIMEDOUT);
+
+ res = ethr_time_now(&tvb);
+ ASSERT(res == 0);
+
+ diff = (tvb.tv_sec - tva.tv_sec) * 1000000;
+ diff += (tvb.tv_nsec - tva.tv_nsec)/1000;
+
+ print("Timeout=%ld; ", to);
+ print("tva.tv_sec=%ld tva.tv_nsec=%ld; ", tva.tv_sec, tva.tv_nsec);
+ print("tvb.tv_sec=%ld tvb.tv_nsec=%ld; ", tvb.tv_sec, tvb.tv_nsec);
+ print_line("diff (tvb - tva) = %ld us", diff);
+
+ abs_diff = (long) abs((int) diff);
+
+ ASSERT(CTWT_MAX_TIME_DIFF >= abs_diff);
+ return abs_diff;
+}
+
+static void
+cond_timedwait_test(void)
+{
+ int do_restart = 1;
+ long abs_diff, max_abs_diff = 0;
+ int res;
+
+#define CTWT_UPD_MAX_DIFF if (abs_diff > max_abs_diff) max_abs_diff = abs_diff;
+
+ print_line("Running test with statically initialized mutex and cond");
+
+ print_line("CTWT_MAX_TIME_DIFF=%d", CTWT_MAX_TIME_DIFF);
+
+ restart:
+
+ res = ethr_mutex_lock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ abs_diff = ctwt_check_timeout(300);
+ CTWT_UPD_MAX_DIFF;
+ abs_diff = ctwt_check_timeout(700);
+ CTWT_UPD_MAX_DIFF;
+ abs_diff = ctwt_check_timeout(1000);
+ CTWT_UPD_MAX_DIFF;
+ abs_diff = ctwt_check_timeout(2300);
+ CTWT_UPD_MAX_DIFF;
+ abs_diff = ctwt_check_timeout(5100);
+ CTWT_UPD_MAX_DIFF;
+
+ res = ethr_mutex_unlock(&cwt_mutex);
+ ASSERT(res == 0);
+
+ cond_wait_test(1);
+
+ if (do_restart) {
+ do_restart = 0;
+ res = ethr_mutex_init(&cwt_mutex);
+ ASSERT(res == 0);
+ res = ethr_cond_init(&cwt_cond);
+ ASSERT(res == 0);
+ print_line("Running test with dynamically initialized mutex and cond");
+ goto restart;
+ }
+
+ print_line("Max absolute diff = %d us", max_abs_diff);
+ succeed("Max absolute diff = %d us", max_abs_diff);
+
+#undef CTWT_UPD_MAX_DIFF
+}
+
+/*
+ * The broadcast test case.
+ *
+ * Tests that a ethr_cond_broadcast really wakes up all waiting threads.
+ */
+
+#define BCT_THREADS 64
+#define BCT_NO_OF_WAITS 100
+
+static int bct_woken = 0;
+static int bct_waiting = 0;
+static int bct_done = 0;
+static ethr_mutex bct_mutex = ETHR_MUTEX_INITER;
+static ethr_cond bct_cond = ETHR_COND_INITER;
+static ethr_cond bct_cntrl_cond = ETHR_COND_INITER;
+
+
+static void *
+bct_thread(void *unused)
+{
+ int res;
+
+ res = ethr_mutex_lock(&bct_mutex);
+ ASSERT(res == 0);
+
+ while (!bct_done) {
+
+ bct_waiting++;
+ if (bct_waiting == BCT_THREADS) {
+ res = ethr_cond_signal(&bct_cntrl_cond);
+ ASSERT(res == 0);
+ }
+ do {
+ res = ethr_cond_wait(&bct_cond, &bct_mutex);
+ } while (res == EINTR);
+ ASSERT(res == 0);
+ bct_woken++;
+ if (bct_woken == BCT_THREADS) {
+ res = ethr_cond_signal(&bct_cntrl_cond);
+ ASSERT(res == 0);
+ }
+
+ }
+
+ res = ethr_mutex_unlock(&bct_mutex);
+ ASSERT(res == 0);
+
+ return NULL;
+}
+
+static void
+broadcast_test(void)
+{
+ int res, i;
+ ethr_tid tid[BCT_THREADS];
+
+ for (i = 0; i < BCT_THREADS; i++) {
+ res = ethr_thr_create(&tid[i], bct_thread, NULL, NULL);
+ ASSERT(res == 0);
+
+ }
+
+ res = ethr_mutex_lock(&bct_mutex);
+ ASSERT(res == 0);
+
+ for (i = 0; i < BCT_NO_OF_WAITS; i++) {
+
+ while (bct_waiting != BCT_THREADS) {
+ res = ethr_cond_wait(&bct_cntrl_cond, &bct_mutex);
+ ASSERT(res == 0 || res == EINTR);
+ }
+
+ bct_waiting = 0;
+ bct_woken = 0;
+
+ /* Wake all threads */
+ res = ethr_cond_broadcast(&bct_cond);
+ ASSERT(res == 0);
+
+ while (bct_woken != BCT_THREADS) {
+ res = ethr_cond_wait(&bct_cntrl_cond, &bct_mutex);
+ ASSERT(res == 0 || res == EINTR);
+ }
+
+ }
+
+ bct_done = 1;
+
+ /* Wake all threads */
+ res = ethr_cond_broadcast(&bct_cond);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_unlock(&bct_mutex);
+ ASSERT(res == 0);
+
+ for (i = 0; i < BCT_THREADS - 1; i++) {
+ res = ethr_thr_join(tid[i], NULL);
+ ASSERT(res == 0);
+ }
+
+ res = ethr_mutex_destroy(&bct_mutex);
+ ASSERT(res == 0);
+ res = ethr_cond_destroy(&bct_cntrl_cond);
+ ASSERT(res == 0);
+ res = ethr_cond_destroy(&bct_cond);
+ ASSERT(res == 0);
+
+}
+
+/*
+ * The detached thread test case.
+ *
+ * Tests detached threads.
+ */
+
+#define DT_THREADS (50*1024)
+#define DT_BATCH_SIZE 64
+
+static ethr_mutex dt_mutex = ETHR_MUTEX_INITER;
+static ethr_cond dt_cond = ETHR_COND_INITER;
+static int dt_count;
+static int dt_limit;
+
+static void *
+dt_thread(void *unused)
+{
+ int res;
+
+ res = ethr_mutex_lock(&dt_mutex);
+ ASSERT(res == 0);
+
+ dt_count++;
+
+ if (dt_count >= dt_limit)
+ ethr_cond_signal(&dt_cond);
+
+ res = ethr_mutex_unlock(&dt_mutex);
+ ASSERT(res == 0);
+
+ return NULL;
+}
+
+static void
+detached_thread_test(void)
+{
+ ethr_thr_opts thr_opts = ETHR_THR_OPTS_DEFAULT_INITER;
+ ethr_tid tid[DT_BATCH_SIZE];
+ int i, j, res;
+
+ thr_opts.detached = 1;
+ dt_count = 0;
+ dt_limit = 0;
+
+ for (i = 0; i < DT_THREADS/DT_BATCH_SIZE; i++) {
+
+ dt_limit += DT_BATCH_SIZE;
+
+ for (j = 0; j < DT_BATCH_SIZE; j++) {
+ res = ethr_thr_create(&tid[j], dt_thread, NULL, &thr_opts);
+ ASSERT(res == 0);
+ }
+
+ res = ethr_mutex_lock(&dt_mutex);
+ ASSERT(res == 0);
+ while (dt_count < dt_limit) {
+ res = ethr_cond_wait(&dt_cond, &dt_mutex);
+ ASSERT(res == 0 || res == EINTR);
+ }
+ res = ethr_mutex_unlock(&dt_mutex);
+ ASSERT(res == 0);
+
+ print_line("dt_count = %d", dt_count);
+ }
+ do_sleep(1);
+}
+
+
+
+/*
+ * The max threads test case.
+ *
+ * Tests
+ */
+#define MTT_TIMES 10
+
+static int mtt_terminate;
+static ethr_mutex mtt_mutex = ETHR_MUTEX_INITER;
+static ethr_cond mtt_cond = ETHR_COND_INITER;
+static char mtt_string[22*MTT_TIMES]; /* 22 is enough for ", %d" */
+
+
+void *mtt_thread(void *unused)
+{
+ int res;
+
+ res = ethr_mutex_lock(&mtt_mutex);
+ ASSERT(res == 0);
+
+ while (!mtt_terminate) {
+ res = ethr_cond_wait(&mtt_cond, &mtt_mutex);
+ ASSERT(res == 0 || res == EINTR);
+ }
+
+ res = ethr_mutex_unlock(&mtt_mutex);
+ ASSERT(res == 0);
+
+ return NULL;
+}
+
+
+static int
+mtt_create_join_threads(void)
+{
+ int no_tids = 100, ix = 0, res = 0, no_threads;
+ ethr_tid *tids;
+
+ mtt_terminate = 0;
+
+ tids = (ethr_tid *) malloc(sizeof(ethr_tid)*no_tids);
+ ASSERT(tids);
+
+ print_line("Beginning to create threads");
+
+ while (1) {
+ if (ix >= no_tids) {
+ no_tids += 100;
+ tids = (ethr_tid *) realloc((void *)tids, sizeof(ethr_tid)*no_tids);
+ ASSERT(tids);
+ }
+ res = ethr_thr_create(&tids[ix], mtt_thread, NULL, NULL);
+ if (res != 0)
+ break;
+ ix++;
+ } while (res == 0);
+
+ no_threads = ix;
+
+ print_line("%d = ethr_thr_create()", res);
+ print_line("Number of created threads: %d", no_threads);
+
+ res = ethr_mutex_lock(&mtt_mutex);
+ ASSERT(res == 0);
+
+ mtt_terminate = 1;
+
+ res = ethr_cond_broadcast(&mtt_cond);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_unlock(&mtt_mutex);
+ ASSERT(res == 0);
+
+ while (ix) {
+ res = ethr_thr_join(tids[--ix], NULL);
+ ASSERT(res == 0);
+ }
+
+ print_line("All created threads terminated");
+
+ free((void *) tids);
+
+ return no_threads;
+
+}
+
+static void
+max_threads_test(void)
+{
+ int no_threads[MTT_TIMES], i, up, down, eq;
+ char *str;
+
+ for (i = 0; i < MTT_TIMES; i++) {
+ no_threads[i] = mtt_create_join_threads();
+ }
+
+ str = &mtt_string[0];
+ eq = up = down = 0;
+ for (i = 0; i < MTT_TIMES; i++) {
+ if (i == 0) {
+ str += sprintf(str, "%d", no_threads[i]);
+ continue;
+ }
+
+ str += sprintf(str, ", %d", no_threads[i]);
+
+ if (no_threads[i] < no_threads[i-1])
+ down++;
+ else if (no_threads[i] > no_threads[i-1])
+ up++;
+ else
+ eq++;
+ }
+
+ print_line("Max created threads: %s", mtt_string);
+
+ /* We fail if the no of threads we are able to create constantly decrease */
+ ASSERT(!down || up || eq);
+
+ succeed("Max created threads: %s", mtt_string);
+
+}
+
+
+/*
+ * The forksafety test case.
+ *
+ * Tests forksafety.
+ */
+#ifdef __WIN32__
+#define NO_FORK_PRESENT
+#endif
+
+#ifndef NO_FORK_PRESENT
+
+static ethr_mutex ft_test_inner_mutex = ETHR_MUTEX_INITER;
+static ethr_mutex ft_test_outer_mutex = ETHR_MUTEX_INITER;
+static ethr_mutex ft_go_mutex = ETHR_MUTEX_INITER;
+static ethr_cond ft_go_cond = ETHR_COND_INITER;
+static int ft_go;
+static int ft_have_forked;
+
+static void *
+ft_thread(void *unused)
+{
+ int res;
+
+ res = ethr_mutex_lock(&ft_test_outer_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_lock(&ft_go_mutex);
+ ASSERT(res == 0);
+
+ ft_go = 1;
+ res = ethr_cond_signal(&ft_go_cond);
+ ASSERT(res == 0);
+ res = ethr_mutex_unlock(&ft_go_mutex);
+ ASSERT(res == 0);
+
+ do_sleep(1);
+ ASSERT(!ft_have_forked);
+
+ res = ethr_mutex_lock(&ft_test_inner_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_unlock(&ft_test_inner_mutex);
+ ASSERT(res == 0);
+
+ do_sleep(1);
+ ASSERT(!ft_have_forked);
+
+ res = ethr_mutex_unlock(&ft_test_outer_mutex);
+ ASSERT(res == 0);
+
+ do_sleep(1);
+ ASSERT(ft_have_forked);
+
+
+ return NULL;
+}
+
+#endif /* #ifndef NO_FORK_PRESENT */
+
+static void
+forksafety_test(void)
+{
+#ifdef NO_FORK_PRESENT
+ skip("No fork() present; nothing to test");
+#elif defined(DEBUG)
+ skip("Doesn't work in debug build");
+#else
+ char snd_msg[] = "ok, bye!";
+ char rec_msg[sizeof(snd_msg)*2];
+ ethr_tid tid;
+ int res;
+ int fds[2];
+
+
+ res = ethr_mutex_set_forksafe(&ft_test_inner_mutex);
+ if (res == ENOTSUP) {
+ skip("Forksafety not supported on this platform!");
+ }
+ ASSERT(res == 0);
+ res = ethr_mutex_set_forksafe(&ft_test_outer_mutex);
+ ASSERT(res == 0);
+
+
+ res = pipe(fds);
+ ASSERT(res == 0);
+
+ ft_go = 0;
+ ft_have_forked = 0;
+
+ res = ethr_mutex_lock(&ft_go_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_thr_create(&tid, ft_thread, NULL, NULL);
+ ASSERT(res == 0);
+
+ do {
+ res = ethr_cond_wait(&ft_go_cond, &ft_go_mutex);
+ } while (res == EINTR || !ft_go);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_unlock(&ft_go_mutex);
+ ASSERT(res == 0);
+
+ res = fork();
+ ft_have_forked = 1;
+ if (res == 0) {
+ close(fds[0]);
+ res = ethr_mutex_lock(&ft_test_outer_mutex);
+ if (res != 0)
+ _exit(1);
+ res = ethr_mutex_lock(&ft_test_inner_mutex);
+ if (res != 0)
+ _exit(1);
+ res = ethr_mutex_unlock(&ft_test_inner_mutex);
+ if (res != 0)
+ _exit(1);
+ res = ethr_mutex_unlock(&ft_test_outer_mutex);
+ if (res != 0)
+ _exit(1);
+
+ res = ethr_mutex_destroy(&ft_test_inner_mutex);
+ if (res != 0)
+ _exit(1);
+ res = ethr_mutex_destroy(&ft_test_outer_mutex);
+ if (res != 0)
+ _exit(1);
+
+ res = (int) write(fds[1], (void *) snd_msg, sizeof(snd_msg));
+ if (res != sizeof(snd_msg))
+ _exit(1);
+ close(fds[1]);
+ _exit(0);
+ }
+ ASSERT(res > 0);
+ close(fds[1]);
+
+ res = (int) read(fds[0], (void *) rec_msg, sizeof(rec_msg));
+ ASSERT(res == (int) sizeof(snd_msg));
+ ASSERT(strcmp(snd_msg, rec_msg) == 0);
+
+ close(fds[0]);
+#endif
+}
+
+
+/*
+ * The vfork test case.
+ *
+ * Tests vfork with threads.
+ */
+
+#ifdef __WIN32__
+#define NO_VFORK_PRESENT
+#endif
+
+#ifndef NO_VFORK_PRESENT
+
+#undef vfork
+
+static ethr_mutex vt_mutex = ETHR_MUTEX_INITER;
+
+static void *
+vt_thread(void *vprog)
+{
+ char *prog = (char *) vprog;
+ int res;
+ char snd_msg[] = "ok, bye!";
+ char rec_msg[sizeof(snd_msg)*2];
+ int fds[2];
+ char closefd[20];
+ char writefd[20];
+
+ res = pipe(fds);
+ ASSERT(res == 0);
+
+ res = sprintf(closefd, "%d", fds[0]);
+ ASSERT(res <= 20);
+ res = sprintf(writefd, "%d", fds[1]);
+ ASSERT(res <= 20);
+
+ print("parent: About to vfork and execute ");
+ print("execlp(\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", NULL)",
+ prog, prog, "vfork", "exec", snd_msg, closefd, writefd);
+ print_line(" in child");
+ res = vfork();
+ if (res == 0) {
+ execlp(prog, prog, "vfork", "exec", snd_msg, closefd, writefd, NULL);
+ _exit(1);
+ }
+ ASSERT(res > 0);
+
+ print_line("parent: I'm back");
+
+ close(fds[1]);
+
+ res = (int) read(fds[0], (void *) rec_msg, sizeof(rec_msg));
+ print_line("parent: %d = read()", res);
+ print_line("parent: rec_msg=\"%s\"", rec_msg);
+ ASSERT(res == (int) sizeof(snd_msg));
+ ASSERT(strcmp(snd_msg, rec_msg) == 0);
+
+ close(fds[0]);
+
+ return NULL;
+}
+
+#endif /* #ifndef NO_VFORK_PRESENT */
+
+static void
+vfork_test(int argc, char *argv[])
+{
+#ifdef NO_VFORK_PRESENT
+ skip("No vfork() present; nothing to test");
+#else
+ int res;
+ ethr_tid tid;
+
+ if (argc == 6 && strcmp("exec", argv[2]) == 0) {
+ /* We are child after vfork() and execlp() ... */
+
+ char *snd_msg;
+ int closefd;
+ int writefd;
+
+ snd_msg = argv[3];
+ closefd = atoi(argv[4]);
+ writefd = atoi(argv[5]);
+
+ print_line("child: snd_msg=\"%s\"; closefd=%d writefd=%d",
+ snd_msg, closefd, writefd);
+
+ close(closefd);
+
+ res = (int) write(writefd, (void *) snd_msg, strlen(snd_msg)+1);
+ print_line("child: %d = write()", res);
+ if (res != strlen(snd_msg)+1)
+ exit(1);
+ close(writefd);
+ print_line("child: bye");
+ exit(0);
+ }
+ ASSERT(argc == 2);
+
+ res = ethr_mutex_set_forksafe(&vt_mutex);
+ ASSERT(res == 0 || res == ENOTSUP);
+ res = ethr_mutex_lock(&vt_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_thr_create(&tid, vt_thread, (void *) argv[0], NULL);
+ ASSERT(res == 0);
+
+ do_sleep(1);
+
+ res = ethr_mutex_unlock(&vt_mutex);
+ ASSERT(res == 0);
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+
+ res = ethr_mutex_destroy(&vt_mutex);
+ ASSERT(res == 0);
+#endif
+}
+
+
+/*
+ * The tsd test case.
+ *
+ * Tests thread specific data.
+ */
+
+#define TT_THREADS 10
+static ethr_tsd_key tt_key;
+
+static void *
+tt_thread(void *arg)
+{
+ int res = ethr_tsd_set(tt_key, arg);
+ ASSERT(res == 0);
+ return ethr_tsd_get(tt_key);
+}
+
+static void
+tsd_test(void)
+{
+ void *tres;
+ int i, res;
+ ethr_tid tid[TT_THREADS];
+ int values[TT_THREADS];
+
+ res = ethr_tsd_key_create(&tt_key);
+ ASSERT(res == 0);
+
+ for (i = 1; i < TT_THREADS; i++) {
+ res = ethr_thr_create(&tid[i], tt_thread, (void *) &values[i], NULL);
+ ASSERT(res == 0);
+ }
+
+ tres = tt_thread((void *) &values[0]);
+ ASSERT(tres == (void *) &values[0]);
+
+ for (i = 1; i < TT_THREADS; i++) {
+ res = ethr_thr_join(tid[i], &tres);
+ ASSERT(res == 0);
+ ASSERT(tres == (void *) &values[i]);
+ }
+
+ res = ethr_tsd_key_delete(tt_key);
+ ASSERT(res == 0);
+}
+
+
+/*
+ * The spinlock test case.
+ *
+ * Tests spinlocks.
+ */
+
+static ethr_spinlock_t st_spinlock;
+static int st_data;
+
+void *
+st_thread(void *unused)
+{
+ int res;
+
+ print_line("Aux thread tries to lock spinlock");
+ res = ethr_spin_lock(&st_spinlock);
+ ASSERT(res == 0);
+ print_line("Aux thread locked spinlock");
+
+ ASSERT(st_data == 0);
+
+ st_data = 1;
+ print_line("Aux thread wrote");
+
+ print_line("Aux thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Aux thread woke up");
+
+ ASSERT(st_data == 1);
+
+ res = ethr_spin_unlock(&st_spinlock);
+ ASSERT(res == 0);
+ print_line("Aux thread unlocked spinlock");
+
+ return NULL;
+}
+
+
+static void
+spinlock_test(void)
+{
+ int res;
+ ethr_tid tid;
+
+ print_line("Trying to initialize spinlock");
+ res = ethr_spinlock_init(&st_spinlock);
+ ASSERT(res == 0);
+ print_line("Initialized spinlock");
+
+ st_data = 0;
+
+ print_line("Main thread tries to lock spinlock");
+ res = ethr_spin_lock(&st_spinlock);
+ ASSERT(res == 0);
+ print_line("Main thread locked spinlock");
+
+ ASSERT(st_data == 0);
+
+ print_line("Main thread about to create aux thread");
+ res = ethr_thr_create(&tid, st_thread, NULL, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread created aux thread");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(st_data == 0);
+
+ res = ethr_spin_unlock(&st_spinlock);
+ ASSERT(res == 0);
+ print_line("Main thread unlocked spinlock");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ print_line("Main thread tries to lock spinlock");
+ res = ethr_spin_lock(&st_spinlock);
+ ASSERT(res == 0);
+ print_line("Main thread locked spinlock");
+
+ ASSERT(st_data == 1);
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(st_data == 1);
+
+ res = ethr_spin_unlock(&st_spinlock);
+ ASSERT(res == 0);
+ print_line("Main thread unlocked spinlock");
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread joined aux thread");
+
+ res = ethr_spinlock_destroy(&st_spinlock);
+ ASSERT(res == 0);
+ print_line("Main thread destroyed spinlock");
+
+}
+
+
+/*
+ * The rwspinlock test case.
+ *
+ * Tests rwspinlocks.
+ */
+
+static ethr_rwlock_t rwst_rwspinlock;
+static int rwst_data;
+
+void *
+rwst_thread(void *unused)
+{
+ int data;
+ int res;
+
+ print_line("Aux thread tries to read lock rwspinlock");
+ res = ethr_read_lock(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Aux thread read locked rwspinlock");
+
+ ASSERT(rwst_data == 4711);
+
+ print_line("Aux thread tries to read unlock rwspinlock");
+ res = ethr_read_unlock(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Aux thread read unlocked rwspinlock");
+
+ print_line("Aux thread tries to write lock rwspinlock");
+ res = ethr_write_lock(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Aux thread write locked rwspinlock");
+
+ data = ++rwst_data;
+ print_line("Aux thread wrote");
+
+ print_line("Aux thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Aux thread woke up");
+
+ ASSERT(rwst_data == data);
+ ++rwst_data;
+
+ print_line("Aux thread tries to write unlock rwspinlock");
+ res = ethr_write_unlock(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Aux thread write unlocked rwspinlock");
+
+ return NULL;
+}
+
+
+static void
+rwspinlock_test(void)
+{
+ int data;
+ int res;
+ ethr_tid tid;
+
+ print_line("Trying to initialize rwspinlock");
+ res = ethr_rwlock_init(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Initialized rwspinlock");
+
+ rwst_data = 4711;
+
+ print_line("Main thread tries to read lock rwspinlock");
+ res = ethr_read_lock(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Main thread read locked rwspinlock");
+
+ ASSERT(rwst_data == 4711);
+
+ print_line("Main thread about to create aux thread");
+ res = ethr_thr_create(&tid, rwst_thread, NULL, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread created aux thread");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(rwst_data == 4711);
+
+ print_line("Main thread tries to read unlock rwspinlock");
+ res = ethr_read_unlock(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Main thread read unlocked rwspinlock");
+
+ print_line("Main thread tries to write lock rwspinlock");
+ res = ethr_write_lock(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Main thread write locked rwspinlock");
+
+ data = ++rwst_data;
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(rwst_data == data);
+ ++rwst_data;
+
+ print_line("Main thread tries to write unlock rwspinlock");
+ res = ethr_write_unlock(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Main thread write unlocked rwspinlock");
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread joined aux thread");
+
+ res = ethr_rwlock_destroy(&rwst_rwspinlock);
+ ASSERT(res == 0);
+ print_line("Main thread destroyed rwspinlock");
+
+}
+
+
+/*
+ * The rwmutex test case.
+ *
+ * Tests rwmutexes.
+ */
+
+static ethr_rwmutex rwmt_rwmutex;
+static int rwmt_data;
+
+void *
+rwmt_thread(void *unused)
+{
+ int data;
+ int res;
+
+ print_line("Aux thread tries to read lock rwmutex");
+ res = ethr_rwmutex_rlock(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Aux thread read locked rwmutex");
+
+ ASSERT(rwmt_data == 4711);
+
+ print_line("Aux thread tries to read unlock rwmutex");
+ res = ethr_rwmutex_runlock(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Aux thread read unlocked rwmutex");
+
+ print_line("Aux thread tries to write lock rwmutex");
+ res = ethr_rwmutex_rwlock(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Aux thread write locked rwmutex");
+
+ data = ++rwmt_data;
+ print_line("Aux thread wrote");
+
+ print_line("Aux thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Aux thread woke up");
+
+ ASSERT(rwmt_data == data);
+ ++rwmt_data;
+
+ print_line("Aux thread tries to write unlock rwmutex");
+ res = ethr_rwmutex_rwunlock(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Aux thread write unlocked rwmutex");
+
+ return NULL;
+}
+
+
+static void
+rwmutex_test(void)
+{
+ int data;
+ int res;
+ ethr_tid tid;
+
+ print_line("Trying to initialize rwmutex");
+ res = ethr_rwmutex_init(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Initialized rwmutex");
+
+ rwmt_data = 4711;
+
+ print_line("Main thread tries to read lock rwmutex");
+ res = ethr_rwmutex_rlock(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Main thread read locked rwmutex");
+
+ ASSERT(rwmt_data == 4711);
+
+ print_line("Main thread about to create aux thread");
+ res = ethr_thr_create(&tid, rwmt_thread, NULL, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread created aux thread");
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(rwmt_data == 4711);
+
+ print_line("Main thread tries to read unlock rwmutex");
+ res = ethr_rwmutex_runlock(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Main thread read unlocked rwmutex");
+
+ print_line("Main thread tries to write lock rwmutex");
+ res = ethr_rwmutex_rwlock(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Main thread write locked rwmutex");
+
+ data = ++rwmt_data;
+
+ print_line("Main thread goes to sleep for 1 second");
+ do_sleep(1);
+ print_line("Main thread woke up");
+
+ ASSERT(rwmt_data == data);
+ ++rwmt_data;
+
+ print_line("Main thread tries to write unlock rwmutex");
+ res = ethr_rwmutex_rwunlock(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Main thread write unlocked rwmutex");
+
+ res = ethr_thr_join(tid, NULL);
+ ASSERT(res == 0);
+ print_line("Main thread joined aux thread");
+
+ res = ethr_rwmutex_destroy(&rwmt_rwmutex);
+ ASSERT(res == 0);
+ print_line("Main thread destroyed rwmutex");
+
+}
+
+/*
+ * The atomic test case.
+ *
+ * Tests atomics.
+ */
+
+#define AT_THREADS 4
+#define AT_ITER 10000
+
+long at_set_val, at_rm_val, at_max_val;
+
+static ethr_atomic_t at_ready;
+static ethr_atomic_t at_go;
+static ethr_atomic_t at_done;
+static ethr_atomic_t at_data;
+
+void *
+at_thread(void *unused)
+{
+ int res, i;
+ long val, go;
+
+
+ res = ethr_atomic_inctest(&at_ready, &val);
+ ASSERT(res == 0);
+ ASSERT(val > 0);
+ ASSERT(val <= AT_THREADS);
+
+ do {
+ res = ethr_atomic_read(&at_go, &go);
+ ASSERT(res == 0);
+ } while (!go);
+
+ for (i = 0; i < AT_ITER; i++) {
+ res = ethr_atomic_or_old(&at_data, at_set_val, &val);
+ ASSERT(res == 0);
+ ASSERT(val >= (i == 0 ? 0 : at_set_val) + (long) 4711);
+ ASSERT(val <= at_max_val);
+
+ res = ethr_atomic_and_old(&at_data, ~at_rm_val, &val);
+ ASSERT(res == 0);
+ ASSERT(val >= at_set_val + (long) 4711);
+ ASSERT(val <= at_max_val);
+
+ res = ethr_atomic_read(&at_data, &val);
+ ASSERT(res == 0);
+ ASSERT(val >= at_set_val + (long) 4711);
+ ASSERT(val <= at_max_val);
+
+ res = ethr_atomic_inctest(&at_data, &val);
+ ASSERT(res == 0);
+ ASSERT(val > at_set_val + (long) 4711);
+ ASSERT(val <= at_max_val);
+
+ res = ethr_atomic_dectest(&at_data, &val);
+ ASSERT(res == 0);
+ ASSERT(val >= at_set_val + (long) 4711);
+ ASSERT(val <= at_max_val);
+
+ res = ethr_atomic_inc(&at_data);
+ ASSERT(res == 0);
+
+ res = ethr_atomic_dec(&at_data);
+ ASSERT(res == 0);
+
+ res = ethr_atomic_addtest(&at_data, (long) 4711, &val);
+ ASSERT(res == 0);
+ ASSERT(val >= at_set_val + (long) 2*4711);
+ ASSERT(val <= at_max_val);
+
+ res = ethr_atomic_add(&at_data, (long) -4711);
+ ASSERT(res == 0);
+ ASSERT(val >= at_set_val + (long) 4711);
+ ASSERT(val <= at_max_val);
+ }
+
+ res = ethr_atomic_inc(&at_done);
+ ASSERT(res == 0);
+ return NULL;
+}
+
+
+static void
+atomic_test(void)
+{
+ long data_init, data_final, val;
+ int res, i;
+ ethr_tid tid[AT_THREADS];
+ ethr_thr_opts thr_opts = ETHR_THR_OPTS_DEFAULT_INITER;
+
+ if (sizeof(long) > 4) {
+ at_rm_val = ((long) 1) << 57;
+ at_set_val = ((long) 1) << 60;
+ }
+ else {
+ at_rm_val = ((long) 1) << 27;
+ at_set_val = ((long) 1) << 30;
+ }
+
+ at_max_val = at_set_val + at_rm_val + ((long) AT_THREADS + 1) * 4711;
+ data_init = at_rm_val + (long) 4711;
+ data_final = at_set_val + (long) 4711;
+
+ thr_opts.detached = 1;
+
+ print_line("Initializing");
+ res = ethr_atomic_init(&at_ready, 0);
+ ASSERT(res == 0);
+ res = ethr_atomic_init(&at_go, 0);
+ ASSERT(res == 0);
+ res = ethr_atomic_init(&at_done, data_init);
+ ASSERT(res == 0);
+ res = ethr_atomic_init(&at_data, data_init);
+ ASSERT(res == 0);
+
+ res = ethr_atomic_read(&at_data, &val);
+ ASSERT(res == 0);
+ ASSERT(val == data_init);
+ res = ethr_atomic_set(&at_done, 0);
+ ASSERT(res == 0);
+ res = ethr_atomic_read(&at_done, &val);
+ ASSERT(res == 0);
+ ASSERT(val == 0);
+
+ print_line("Creating threads");
+ for (i = 0; i < AT_THREADS; i++) {
+ res = ethr_thr_create(&tid[i], at_thread, NULL, &thr_opts);
+ ASSERT(res == 0);
+ }
+
+ print_line("Waiting for threads to ready up");
+ do {
+ res = ethr_atomic_read(&at_ready, &val);
+ ASSERT(res == 0);
+ ASSERT(val >= 0);
+ ASSERT(val <= AT_THREADS);
+ } while (val != AT_THREADS);
+
+ print_line("Letting threads loose");
+ res = ethr_atomic_xchg(&at_go, 17, &val);
+ ASSERT(res == 0);
+ ASSERT(val == 0);
+ res = ethr_atomic_read(&at_go, &val);
+ ASSERT(res == 0);
+ ASSERT(val == 17);
+
+
+ print_line("Waiting for threads to finish");
+ do {
+ res = ethr_atomic_read(&at_done, &val);
+ ASSERT(res == 0);
+ ASSERT(val >= 0);
+ ASSERT(val <= AT_THREADS);
+ } while (val != AT_THREADS);
+
+ print_line("Checking result");
+ res = ethr_atomic_read(&at_data, &val);
+ ASSERT(res == 0);
+ ASSERT(val == data_final);
+ print_line("Result ok");
+
+}
+
+
+/*
+ * The gate test case.
+ *
+ * Tests gates.
+ */
+
+#define GT_THREADS 10
+
+static ethr_atomic_t gt_wait1;
+static ethr_atomic_t gt_wait2;
+static ethr_atomic_t gt_done;
+
+static ethr_gate gt_gate1;
+static ethr_gate gt_gate2;
+
+void *
+gt_thread(void *thr_no)
+{
+ int no = (int)(long) thr_no;
+ int swait = no % 2 == 0;
+ int res;
+ long done;
+
+
+ do {
+
+ res = ethr_atomic_inc(&gt_wait1);
+ ASSERT(res == 0);
+
+ if (swait)
+ res = ethr_gate_swait(&gt_gate1, INT_MAX);
+ else
+ res = ethr_gate_wait(&gt_gate1);
+ ASSERT(res == 0);
+
+ res = ethr_atomic_dec(&gt_wait1);
+ ASSERT(res == 0);
+
+ res = ethr_atomic_inc(&gt_wait2);
+ ASSERT(res == 0);
+
+ if (swait)
+ res = ethr_gate_swait(&gt_gate2, INT_MAX);
+ else
+ res = ethr_gate_wait(&gt_gate2);
+ ASSERT(res == 0);
+
+ res = ethr_atomic_dec(&gt_wait2);
+ ASSERT(res == 0);
+
+ res = ethr_atomic_read(&gt_done, &done);
+ ASSERT(res == 0);
+ } while (!done);
+ return NULL;
+}
+
+
+static void
+gate_test(void)
+{
+ long val;
+ int res, i;
+ ethr_tid tid[GT_THREADS];
+
+ print_line("Initializing");
+ res = ethr_atomic_init(&gt_wait1, 0);
+ ASSERT_EQ(res, 0, "%d");
+ res = ethr_atomic_init(&gt_wait2, 0);
+ ASSERT_EQ(res, 0, "%d");
+ res = ethr_atomic_init(&gt_done, 0);
+ ASSERT_EQ(res, 0, "%d");
+ res = ethr_gate_init(&gt_gate1);
+ ASSERT_EQ(res, 0, "%d");
+ res = ethr_gate_init(&gt_gate2);
+ ASSERT_EQ(res, 0, "%d");
+
+ print_line("Creating threads");
+ for (i = 0; i < GT_THREADS; i++) {
+ res = ethr_thr_create(&tid[i], gt_thread, (void *) i, NULL);
+ ASSERT_EQ(res, 0, "%d");
+ }
+
+ print_line("Waiting for threads to ready up");
+ do {
+ res = ethr_atomic_read(&gt_wait1, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT(0 <= val && val <= GT_THREADS);
+ } while (val != GT_THREADS);
+
+ print_line("Testing");
+
+ res = ethr_gate_let_through(&gt_gate1, 8);
+ ASSERT_EQ(res, 0, "%d");
+
+ WAIT_UNTIL_LIM((res = ethr_atomic_read(&gt_wait2, &val),
+ (res != 0 || val == 8)),
+ 60);
+
+ res = ethr_atomic_read(&gt_wait1, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, GT_THREADS - 8, "%ld");
+
+ res = ethr_atomic_read(&gt_wait2, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, 8, "%ld");
+
+ res = ethr_gate_let_through(&gt_gate2, 4);
+ ASSERT_EQ(res, 0, "%d");
+
+ WAIT_UNTIL_LIM((res = ethr_atomic_read(&gt_wait2, &val),
+ (res != 0 || val == 4)),
+ 60);
+
+ res = ethr_atomic_read(&gt_wait1, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, GT_THREADS - 4, "%ld");
+
+ res = ethr_atomic_read(&gt_wait2, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, 4, "%ld");
+
+ res = ethr_gate_let_through(&gt_gate1, GT_THREADS);
+ ASSERT_EQ(res, 0, "%d");
+
+ WAIT_UNTIL_LIM((res = ethr_atomic_read(&gt_wait2, &val),
+ (res != 0 || val == GT_THREADS)),
+ 60);
+ res = ethr_atomic_read(&gt_wait1, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, 0, "%ld");
+
+ res = ethr_atomic_read(&gt_wait2, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, GT_THREADS, "%ld");
+
+ res = ethr_gate_let_through(&gt_gate2, GT_THREADS);
+ ASSERT_EQ(res, 0, "%d");
+
+ WAIT_UNTIL_LIM((res = ethr_atomic_read(&gt_wait2, &val),
+ (res != 0 || val == 4)),
+ 60);
+ res = ethr_atomic_read(&gt_wait1, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, GT_THREADS - 4, "%ld");
+
+ res = ethr_atomic_read(&gt_wait2, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, 4, "%ld");
+
+ res = ethr_atomic_set(&gt_done, 1);
+ ASSERT_EQ(res, 0, "%d");
+
+ res = ethr_gate_let_through(&gt_gate2, GT_THREADS);
+ ASSERT_EQ(res, 0, "%d");
+ res = ethr_gate_let_through(&gt_gate1, GT_THREADS - 4);
+ ASSERT_EQ(res, 0, "%d");
+
+ WAIT_UNTIL_LIM(((res = ethr_atomic_read(&gt_wait1, &val)) != 0
+ || (val == 0
+ && ((res = ethr_atomic_read(&gt_wait2, &val)) != 0
+ || val == 0))),
+ 60);
+
+ res = ethr_atomic_read(&gt_wait1, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, 0, "%ld");
+
+ res = ethr_atomic_read(&gt_wait2, &val);
+ ASSERT_EQ(res, 0, "%d");
+ ASSERT_EQ(val, 0, "%ld");
+
+ print_line("Joining threads");
+ for (i = 0; i < GT_THREADS; i++) {
+ res = ethr_thr_join(tid[i], NULL);
+ ASSERT_EQ(res, 0, "%d");
+ }
+
+ res = ethr_gate_destroy(&gt_gate1);
+ ASSERT_EQ(res, 0, "%d");
+ res = ethr_gate_destroy(&gt_gate2);
+ ASSERT_EQ(res, 0, "%d");
+
+}
+
+#endif /* #ifndef ETHR_NO_THREAD_LIB */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * The dispatcher *
+\* */
+
+int
+main(int argc, char *argv[])
+{
+ if (argc < 2)
+ fail("To few arguments for test case");
+
+#ifndef ETHR_NO_THREAD_LIB
+ {
+ char *testcase;
+ int res;
+
+ send_my_pid();
+
+ testcase = argv[1];
+ res = ethr_init(NULL);
+
+ if (res != 0)
+ fail("Failed to initialize the ethread library");
+
+ if (strcmp(testcase, "create_join_thread") == 0)
+ create_join_thread_test();
+ else if (strcmp(testcase, "equal_tids") == 0)
+ equal_tids_test();
+ else if (strcmp(testcase, "mutex") == 0)
+ mutex_test();
+ else if (strcmp(testcase, "try_lock_mutex") == 0)
+ try_lock_mutex_test();
+ else if (strcmp(testcase, "recursive_mutex") == 0)
+ recursive_mutex_test();
+ else if (strcmp(testcase, "time_now") == 0)
+ time_now_test();
+ else if (strcmp(testcase, "cond_wait") == 0)
+ cond_wait_test(0);
+ else if (strcmp(testcase, "cond_timedwait") == 0)
+ cond_timedwait_test();
+ else if (strcmp(testcase, "broadcast") == 0)
+ broadcast_test();
+ else if (strcmp(testcase, "detached_thread") == 0)
+ detached_thread_test();
+ else if (strcmp(testcase, "max_threads") == 0)
+ max_threads_test();
+ else if (strcmp(testcase, "forksafety") == 0)
+ forksafety_test();
+ else if (strcmp(testcase, "vfork") == 0)
+ vfork_test(argc, argv);
+ else if (strcmp(testcase, "tsd") == 0)
+ tsd_test();
+ else if (strcmp(testcase, "spinlock") == 0)
+ spinlock_test();
+ else if (strcmp(testcase, "rwspinlock") == 0)
+ rwspinlock_test();
+ else if (strcmp(testcase, "rwmutex") == 0)
+ rwmutex_test();
+ else if (strcmp(testcase, "atomic") == 0)
+ atomic_test();
+ else if (strcmp(testcase, "gate") == 0)
+ gate_test();
+ else
+ skip("Test case \"%s\" not implemented yet", testcase);
+
+ succeed(NULL);
+ }
+#else /* #ifndef ETHR_NO_THREAD_LIB */
+ skip("No ethread library to test");
+#endif /* #ifndef ETHR_NO_THREAD_LIB */
+
+ return 0;
+}
diff --git a/erts/test/ignore_cores.erl b/erts/test/ignore_cores.erl
new file mode 100644
index 0000000000..7ec2cac706
--- /dev/null
+++ b/erts/test/ignore_cores.erl
@@ -0,0 +1,158 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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%
+%%
+
+%%%-------------------------------------------------------------------
+%%% File : ignore_cores.erl
+%%% Author : Rickard Green <[email protected]>
+%%% Description :
+%%%
+%%% Created : 11 Feb 2008 by Rickard Green <[email protected]>
+%%%-------------------------------------------------------------------
+
+-module(ignore_cores).
+
+-include("test_server.hrl").
+
+-export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]).
+
+-record(ignore_cores, {org_cwd,
+ org_path,
+ org_pwd_env,
+ ign_dir = false,
+ cores_dir = false}).
+
+%%
+%% Takes a testcase config
+%%
+
+init(Config) ->
+ {ok, OrgCWD} = file:get_cwd(),
+ [{ignore_cores,
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = code:get_path(),
+ org_pwd_env = os:getenv("PWD")}}
+ | lists:keydelete(ignore_cores, 1, Config)].
+
+fini(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ ok = file:set_cwd(OrgCWD),
+ true = code:set_path(OrgPath),
+ case OrgPWD of
+ false -> ok;
+ _ -> true = os:putenv("PWD", OrgPWD)
+ end,
+ lists:keydelete(ignore_cores, 1, Config).
+
+setup(Suite, Testcase, Config) ->
+ setup(Suite, Testcase, Config, false).
+
+setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite),
+ is_atom(Testcase),
+ is_list(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD} = ?config(ignore_cores, Config),
+ Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath),
+ true = code:set_path(Path),
+ PrivDir = ?config(priv_dir, Config),
+ IgnDir = filename:join([PrivDir,
+ atom_to_list(Suite)
+ ++ "_"
+ ++ atom_to_list(Testcase)
+ ++ "_wd"]),
+ ok = file:make_dir(IgnDir),
+ case SetCwd of
+ false ->
+ ok;
+ _ ->
+ ok = file:set_cwd(IgnDir),
+ OrgPWD = case os:getenv("PWD") of
+ false -> false;
+ PWD ->
+ os:putenv("PWD", IgnDir),
+ PWD
+ end
+ end,
+ ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>),
+ %% cores are dumped in /cores on MacOS X
+ CoresDir = case {?t:os_type(), filelib:is_dir("/cores")} of
+ {{unix,darwin}, true} ->
+ filelib:fold_files("/cores",
+ "^core.*$",
+ false,
+ fun (C,Cs) -> [C|Cs] end,
+ []);
+ _ ->
+ false
+ end,
+ lists:keyreplace(ignore_cores,
+ 1,
+ Config,
+ {ignore_cores,
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD,
+ ign_dir = IgnDir,
+ cores_dir = CoresDir}}).
+
+restore(Config) ->
+ #ignore_cores{org_cwd = OrgCWD,
+ org_path = OrgPath,
+ org_pwd_env = OrgPWD,
+ ign_dir = IgnDir,
+ cores_dir = CoresDir} = ?config(ignore_cores, Config),
+ try
+ case CoresDir of
+ false ->
+ ok;
+ _ ->
+ %% Move cores dumped by these testcases in /cores
+ %% to cwd.
+ lists:foreach(fun (C) ->
+ case lists:member(C, CoresDir) of
+ true -> ok;
+ _ ->
+ Dst = filename:join(
+ [IgnDir,
+ filename:basename(C)]),
+ {ok, _} = file:copy(C, Dst),
+ file:delete(C)
+ end
+ end,
+ filelib:fold_files("/cores",
+ "^core.*$",
+ false,
+ fun (C,Cs) -> [C|Cs] end,
+ []))
+ end
+ after
+ catch file:set_cwd(OrgCWD),
+ catch code:set_path(OrgPath),
+ case OrgPWD of
+ false -> ok;
+ _ -> catch os:putenv("PWD", OrgPWD)
+ end
+ end.
+
+
+dir(Config) ->
+ #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config),
+ Dir.
diff --git a/erts/test/nt_SUITE.erl b/erts/test/nt_SUITE.erl
new file mode 100644
index 0000000000..7ff5c908e6
--- /dev/null
+++ b/erts/test/nt_SUITE.erl
@@ -0,0 +1,551 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-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%
+%%
+%%% Purpose: Test NT specific utilities
+-module(nt_SUITE).
+-include("test_server.hrl").
+-include_lib("kernel/include/file.hrl").
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,nt/1,handle_eventlog/2,
+ middleman/1,service_basic/1, service_env/1, user_env/1, synced/1,
+ service_prio/1,
+ logout/1, debug/1, restart/1, restart_always/1,stopaction/1,
+ shutdown_io/0,do_shutdown_io/0]).
+-define(TEST_TIMEOUT, ?t:seconds(180)).
+
+-define(TEST_SERVICES, [1,2,3,4,5,6,7,8,9,10,11]).
+
+all(suite) ->
+ case os:type() of
+ {win32,nt} ->
+ [nt, service_basic, service_env, user_env, synced, service_prio,
+ logout, debug,
+ restart, restart_always, stopaction];
+ _ -> [nt] %%% Just to give a little hint why they are skipped...
+ end.
+
+init_per_testcase(_Func, Config) ->
+ Dog = test_server:timetrap(?TEST_TIMEOUT),
+ [{watchdog, Dog} | Config].
+
+fin_per_testcase(_Func, Config) ->
+ lists:foreach(fun(X) ->
+ catch remove_service("test_service_" ++
+ integer_to_list(X)) end,
+ ?TEST_SERVICES),
+ Dog = ?config(watchdog, Config),
+ catch test_server:timetrap_cancel(Dog),
+ ok.
+
+erlsrv() ->
+ os:find_executable(erlsrv).
+
+
+recv_prog_output(Port) ->
+ receive
+ {Port, {data, {eol,Data}}} ->
+ %%io:format("Got data: ~s~n", [Data]),
+ [ Data | recv_prog_output(Port)];
+ _X ->
+ %%io:format("Got data: ~p~n", [_X]),
+ Port ! {self(), close},
+ receive
+ _ ->
+ []
+ end
+ end.
+
+
+%%% X == parameters to erlsrv
+%%% returns command output without stderr
+do_command(X) ->
+ %%io:format("Command: ~s~n", [erlsrv() ++ " " ++ X]),
+ Port = open_port({spawn, erlsrv() ++ " " ++ X}, [stream, {line, 100}, eof, in]),
+ Res = recv_prog_output(Port),
+ case Res of
+ [] ->
+ failed;
+ _Y ->
+ %%io:format("~p~n",[_Y]),
+ ok
+ end.
+
+
+create_service(Name) ->
+ ok = do_command("add " ++ Name).
+
+start_service(Name) ->
+ ok = do_command("start " ++ Name).
+
+stop_service(Name) ->
+ ok = do_command("stop " ++ Name).
+
+remove_service(Name) ->
+ ok = do_command("remove " ++ Name).
+do_wait_for_it(_,0) ->
+ false;
+do_wait_for_it(FullName,N) ->
+ case net_adm:ping(FullName) of
+ pong ->
+ true;
+ _ ->
+ receive
+ after 1000 ->
+ do_wait_for_it(FullName,N-1)
+ end
+ end.
+
+wait_for_node(Name) ->
+ FullName = make_full_name(Name),
+ do_wait_for_it(FullName,30).
+
+make_full_name(Name) ->
+ [_,Suffix] = string:tokens(atom_to_list(node()),"@"),
+ list_to_atom(Name ++ "@" ++ Suffix).
+
+
+%%% The following tests are only run on NT:
+
+service_basic(doc) ->
+ ["Check some basic (cosmetic) service parameters"];
+service_basic(suite) -> [];
+service_basic(Config) when is_list(Config) ->
+ ?line Name = "test_service_20",
+ ?line IntName = Name++"_internal",
+ ?line Service = [{servicename,Name},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie())]},
+ {internalservicename,IntName},
+ {comment,"Epic comment"}],
+ ?line ok = erlsrv:store_service(Service),
+ ?line start_service(Name),
+ ?line true = wait_for_node(Name),
+ ?line S2 = erlsrv:get_service(Name),
+ ?line {value,{comment,"Epic comment"}} = lists:keysearch(comment,1,S2),
+ ?line {value,{internalservicename,IntName}} =
+ lists:keysearch(internalservicename,1,S2),
+ ?line S3 = lists:keyreplace(comment,1,S2,{comment,"Basic comment"}),
+ ?line S4 = lists:keyreplace(internalservicename,1,S3,
+ {internalservicename,"WillNotHappen"}),
+ ?line ok = erlsrv:store_service(S4),
+ ?line S5 = erlsrv:get_service(Name),
+ ?line {value,{comment,"Basic comment"}} = lists:keysearch(comment,1,S5),
+ ?line {value,{internalservicename,IntName}} =
+ lists:keysearch(internalservicename,1,S5),
+ ?line NewName = "test_service_21",
+ ?line S6 = erlsrv:new_service(NewName,S5,[]), % should remove
+ % internalservicename
+ ?line ok = erlsrv:store_service(S6),
+ ?line S7 = erlsrv:get_service(NewName),
+ ?line {value,{comment,"Basic comment"}} = lists:keysearch(comment,1,S7),
+ ?line {value,{internalservicename,[$t,$e,$s,$t | _]}} =
+ lists:keysearch(internalservicename,1,S7),
+ ?line remove_service(Name),
+ ?line remove_service(NewName),
+ ok.
+
+service_env(doc) ->
+ ["Check that service name and executable is in the environment of the " ++
+ "erlang process created by erlsrv."];
+service_env(suite) -> [];
+service_env(Config) when is_list(Config) ->
+ ?line Name = "test_service_2",
+ ?line Service = [{servicename,Name},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie())]}],
+ ?line ok = erlsrv:store_service(Service),
+ ?line start_service(Name),
+ ?line true = wait_for_node(Name),
+ ?line Name = rpc:call(make_full_name(Name),os,getenv,
+ ["ERLSRV_SERVICE_NAME"]),
+ ?line "erlsrv.exe" = filename:basename(
+ hd(
+ string:tokens(
+ rpc:call(make_full_name(Name),
+ os,
+ getenv,
+ ["ERLSRV_EXECUTABLE"]),
+ "\""))),
+ ?line remove_service(Name),
+ ok.
+user_env(doc) ->
+ ["Check that the user defined environment is ADDED to the service's"++
+ " normal dito."];
+user_env(suite) -> [];
+user_env(Config) when is_list(Config) ->
+ ?line Name = "test_service_3",
+ ?line Service = [{servicename,Name},{env,[{"HUBBA","BUBBA"}]},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie())]}],
+ ?line ok = erlsrv:store_service(Service),
+ ?line start_service(Name),
+ ?line true = wait_for_node(Name),
+ ?line true = rpc:call(make_full_name(Name),os,getenv,
+ ["SystemDrive"]) =/= false,
+ ?line "BUBBA" = rpc:call(make_full_name(Name),os,getenv,["HUBBA"]),
+ ?line remove_service(Name),
+ ok.
+synced(doc) ->
+ ["Check that services are stopped and started syncronous and that"++
+ " failed stopactions kill the erlang machine anyway."];
+synced(suite) -> [];
+synced(Config) when is_list(Config) ->
+ ?line Name0 = "test_service_4",
+ ?line Service0 = [{servicename,Name0},
+ {machine, "N:\\nickeNyfikenPaSjukhus"}],
+ ?line ok = erlsrv:store_service(Service0),
+ ?line true = (catch start_service(Name0)) =/= ok,
+ ?line remove_service(Name0),
+ ?line Name = "test_service_5",
+ ?line Service = [{servicename,Name},
+ {stopaction,"erlang:info(garbage_collection)."},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie())]}],
+ ?line ok = erlsrv:store_service(Service),
+ ?line start_service(Name),
+ ?line true = wait_for_node(Name),
+ ?line T1 = calendar:datetime_to_gregorian_seconds(
+ calendar:universal_time()),
+ ?line stop_service(Name),
+ ?line Diff1 = calendar:datetime_to_gregorian_seconds(
+ calendar:universal_time()) - T1,
+ ?line true = Diff1 > 30,
+ ?line start_service(Name),
+ ?line true = wait_for_node(Name),
+ ?line T2 = calendar:datetime_to_gregorian_seconds(
+ calendar:universal_time()),
+ ?line remove_service(Name),
+ ?line Diff2 = calendar:datetime_to_gregorian_seconds(
+ calendar:universal_time()) - T2,
+ ?line true = Diff2 > 30,
+ ok.
+service_prio(doc) ->
+ ["Check that a service with higher prio create port programs with "
+ "higher prio."];
+service_prio(suite) -> [];
+service_prio(Config) when is_list(Config) ->
+ ?line Name = "test_service_6",
+ ?line Service = [{servicename,Name},{prio,"high"},
+ {env, [{"HEART_COMMAND","echo off"}]},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie()),
+ "-heart"]}],
+ ?line ok = erlsrv:store_service(Service),
+ ?line {ok, OldProcs} = get_current_procs(Config),
+ ?line start_service(Name),
+ ?line {ok, NewProcs} = get_current_procs(Config),
+ ?line remove_service(Name),
+ ?line Diff = arrived_procs(OldProcs,NewProcs),
+ %% Not really correct, could fail if another heart is
+ %% started at the same time...
+ ?line {value, {"heart.exe",_,"high"}} =
+ lists:keysearch("heart.exe",1,Diff),
+ ok.
+logout(doc) ->
+ ["Check that logout does not kill services"];
+logout(suite) -> [];
+logout(Config) when is_list(Config) ->
+ ?line {comment, "Have to be run manually by registering a service with " ++
+ "heart, logout and log in again and then examine that the heart " ++
+ "process id is not changed."}.
+debug(doc) ->
+ ["Check the debug options to erlsrv."];
+debug(suite) -> [];
+debug(Config) when is_list(Config) ->
+ ?line Name0 = "test_service_7",
+
+ %% We used to set the privdir as temporary directory, but for some
+ %% reason we don't seem to have write access to that directory,
+ %% so we'll use the directory specified in the next line.
+ ?line TempDir = "C:/TEMP",
+ ?line Service0 = [{servicename,Name0},
+ {workdir,filename:nativename(TempDir)},
+ {debugtype,"reuse"},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie())]}],
+ ?line ok = erlsrv:store_service(Service0),
+ ?line T1 = calendar:datetime_to_gregorian_seconds(
+ calendar:local_time()),
+ %% sleep a little
+ ?line receive after 2000 -> ok end,
+ ?line start_service(Name0),
+ ?line true = wait_for_node(Name0),
+ ?line LF = filename:join(TempDir, Name0++".debug"),
+ ?line {ok,Info0} = file:read_file_info(LF),
+ ?line T2 = calendar:datetime_to_gregorian_seconds(
+ Info0#file_info.mtime),
+ ?line true = T2 > T1,
+ ?line remove_service(Name0),
+ ?line file:delete(LF),
+ ?line Name1 = "test_service_8",
+ ?line Service1 = [{servicename,Name1},
+ {workdir, filename:nativename(TempDir)},
+ {debugtype,"new"},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie())]}],
+ ?line ok = erlsrv:store_service(Service1),
+ ?line T3 = calendar:datetime_to_gregorian_seconds(
+ calendar:local_time()),
+ %% sleep a little
+ ?line receive after 2000 -> ok end,
+ ?line NF = next_logfile(TempDir, Name1),
+ ?line start_service(Name1),
+ ?line true = wait_for_node(Name1),
+ ?line {ok,Info1} = file:read_file_info(NF),
+ ?line T4 = calendar:datetime_to_gregorian_seconds(
+ Info1#file_info.mtime),
+ ?line true = T4 > T3,
+ ?line remove_service(Name1),
+ ?line file:delete(NF),
+ ok.
+
+restart(doc) ->
+ ["Check the restart options to erlsrv"];
+restart(suite) -> [];
+restart(Config) when is_list(Config) ->
+ ?line Name = "test_service_9",
+ ?line Service = [{servicename,Name},
+ {workdir, filename:nativename(logdir(Config))},
+ {onfail,"restart"},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie())]}],
+ ?line ok = erlsrv:store_service(Service),
+ ?line start_service(Name),
+ ?line true = wait_for_node(Name),
+ ?line receive after 20000 -> ok end,
+ ?line rpc:call(make_full_name(Name),erlang,halt,[]),
+ ?line receive after 1000 -> ok end,
+ ?line true = wait_for_node(Name),
+ ?line rpc:call(make_full_name(Name),erlang,halt,[]),
+ ?line receive after 1000 -> ok end,
+ ?line false = wait_for_node(Name),
+ ?line remove_service(Name),
+ ok.
+
+restart_always(doc) ->
+ ["Check the restart options to erlsrv"];
+restart_always(suite) -> [];
+restart_always(Config) when is_list(Config) ->
+ ?line Name = "test_service_10",
+ ?line Service = [{servicename,Name},
+ {workdir, filename:nativename(logdir(Config))},
+ {onfail,"restart_always"},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie())]}],
+ ?line ok = erlsrv:store_service(Service),
+ ?line start_service(Name),
+ ?line true = wait_for_node(Name),
+ ?line rpc:call(make_full_name(Name),erlang,halt,[]),
+ ?line receive after 1000 -> ok end,
+ ?line true = wait_for_node(Name),
+ ?line rpc:call(make_full_name(Name),erlang,halt,[]),
+ ?line receive after 1000 -> ok end,
+ ?line true = wait_for_node(Name),
+ ?line remove_service(Name),
+ ok.
+stopaction(doc) ->
+ ["Check that stopaction does not hang output while shutting down"];
+stopaction(suite) -> [];
+stopaction(Config) when is_list(Config) ->
+ ?line Name = "test_service_11",
+ %% Icky, I prepend the first element in the codepath, cause
+ %% I "suppose" it's the one to where I am.
+ ?line Service = [{servicename,Name},
+ {stopaction,atom_to_list(?MODULE) ++ ":shutdown_io()."},
+ {args, ["-setcookie",
+ atom_to_list(erlang:get_cookie()),
+ "-pa", hd(code:get_path())]}],
+ ?line ok = erlsrv:store_service(Service),
+ ?line start_service(Name),
+ ?line true = wait_for_node(Name),
+ ?line T1 = calendar:datetime_to_gregorian_seconds(
+ calendar:universal_time()),
+ ?line stop_service(Name),
+ ?line Diff1 = calendar:datetime_to_gregorian_seconds(
+ calendar:universal_time()) - T1,
+ ?line true = Diff1 < 30,
+ ?line remove_service(Name),
+ ok.
+
+
+%%% This test is run on all platforms, but just gives a comment on
+%%% other platforms than NT.
+
+nt(doc) ->
+ ["Run NT specific tests."];
+nt(suite) ->
+ [];
+nt(Config) when is_list(Config) ->
+ case os:type() of
+ {win32,nt} ->
+ nt_run();
+ _ ->
+ {skipped, "This test case is intended for Win NT only."}
+ end.
+
+
+nt_run() ->
+ ?line start_all(),
+ ?line create_service("test_service_1"),
+ ?line R = start_look_for_single("System","ErlSrv","Informational",
+ ".*test_service_1.*started.*"),
+ ?line start_service("test_service_1"),
+ ?line Res = look_for_single(R),
+ ?line io:format("Result from eventlog: ~p~n",
+ [Res]),
+ ?line remove_service("test_service_1"),
+ ?line stop_all(),
+ ok.
+
+start_all() ->
+ Pid1 = spawn_link(?MODULE,middleman,[[]]),
+ register(?MODULE,Pid1),
+ _Pid2 = nteventlog:start("log_testing",
+ {?MODULE,handle_eventlog,[Pid1]}).
+
+stop_all() ->
+ ?MODULE ! stop,
+ nteventlog:stop().
+
+start_look_for_single(Cat,Fac,Sev,MessRE) ->
+ Ref = make_ref(),
+ ?MODULE ! {lookfor, {self(), Ref, {Cat,Fac,Sev,MessRE}}},
+ Ref.
+
+look_for_single(Ref) ->
+ receive
+ {Ref,Time,Mes} ->
+ {Time,Mes}
+ after 60000 ->
+ timeout
+ end.
+
+
+%%% Mes = {Time,Category,Facility,Severity,Message}
+handle_eventlog(Mes,Pid) ->
+ Pid ! Mes.
+
+%%% Waitfor = [{Pid, Ref, {Category,Facility,Severity,MessageRE}} ...]
+middleman(Waitfor) ->
+ receive
+ {Time,Category,Facility,Severity,Message} ->
+ io:format("Middleman got ~s...", [Message]),
+ case match_event({Time,Category,Facility,Severity,Message},
+ Waitfor) of
+ {ok, {Pid,Ref,Time,Mes}, Rest} ->
+ io:format("matched~n"),
+ Pid ! {Ref,Time,Mes},
+ middleman(Rest);
+ _ ->
+ io:format("no match~n"),
+ middleman(Waitfor)
+ end;
+ {lookfor, X} ->
+ io:format("Middleman told to look for ~p~n", [X]),
+ middleman([X|Waitfor]);
+ stop ->
+ stopped;
+ _ ->
+ middleman(Waitfor)
+ end.
+
+
+%%% Matches events, not tail recursive.
+match_event(_X, []) ->
+ nomatch;
+match_event({Time,Cat,Fac,Sev,Mes},[{Pid,Ref,{Cat,Fac,Sev,MesRE}} | Tail]) ->
+ case regexp:match(Mes,MesRE) of
+ {match,_,_} ->
+ %%io:format("Match!~n"),
+ {ok,{Pid,Ref,Time,Mes},Tail};
+ _Z ->
+ %%io:format("No match (~p)~n",[_Z]),
+ case match_event({Time,Cat,Fac,Sev,Mes},Tail) of
+ {ok,X,Rest} ->
+ {ok,X,[{Pid,Ref,{Cat,Fac,Sev,MesRE}} | Rest]};
+ X ->
+ X
+ end
+ end;
+match_event(X,[Y | T]) ->
+ %%io:format("X == ~p, Y == ~p~n",[X,Y]),
+ case match_event(X,T) of
+ {ok,Z,R} ->
+ {ok,Z,[Y|R]};
+ XX ->
+ XX
+ end.
+
+arrived_procs(_,[]) ->
+ [];
+arrived_procs(OldProcs,[{Executable, Pid, Priority} | TNewProcs]) ->
+ case lists:keysearch(Pid,2,OldProcs) of
+ {value, _} ->
+ arrived_procs(OldProcs, TNewProcs);
+ false ->
+ [{Executable, Pid, Priority} | arrived_procs(OldProcs, TNewProcs)]
+ end.
+
+
+get_current_procs(Config) ->
+ ?line P = open_port({spawn,nt_info(Config) ++ " -E"},
+ [{line,10000}]),
+ ?line L = receive
+ {P,{data,{eol,D}}} ->
+ D;
+ _ -> "error. "
+ end,
+ ?line P ! {self(), close},
+ ?line receive
+ {P, closed} -> ok
+ end,
+ ?line {done,{ok,Tok,_},_} = erl_scan:tokens([],L,0),
+ ?line erl_parse:parse_term(Tok).
+
+nt_info(Config) when is_list(Config) ->
+ ?line filename:join(?config(data_dir, Config), "nt_info").
+
+
+logdir(Config) ->
+ ?line ?config(priv_dir, Config).
+
+look_for_next(Template,L,N) ->
+ ?line FN = Template ++ integer_to_list(N),
+ ?line case lists:member(FN,L) of
+ true ->
+ ?line look_for_next(Template,L,N+1);
+ false ->
+ ?line FN
+ end.
+
+next_logfile(LD, Servicename) ->
+ ?line {ok, Files} = file:list_dir(LD),
+ ?line Ftmpl = Servicename ++ ".debug.",
+ ?line filename:join(LD,look_for_next(Ftmpl,Files,1)).
+
+%%% Functions run by the service
+
+do_shutdown_io() ->
+ receive
+ after 2000 ->
+ io:format("IO in shutting down...~n"),
+ erlang:halt()
+ end.
+
+shutdown_io() ->
+ spawn(?MODULE,do_shutdown_io,[]).
diff --git a/erts/test/nt_SUITE_data/Makefile.src b/erts/test/nt_SUITE_data/Makefile.src
new file mode 100644
index 0000000000..b26666252e
--- /dev/null
+++ b/erts/test/nt_SUITE_data/Makefile.src
@@ -0,0 +1,33 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1998-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%
+#
+
+CC = @CC@
+LD = @LD@
+CFLAGS = @CFLAGS@ -I@erl_include@ @DEFS@
+CROSSLDFLAGS = @CROSSLDFLAGS@
+
+PROGS = nt_info@exe@
+
+all: $(PROGS)
+
+nt_info@exe@: nt_info@obj@
+ $(LD) $(CROSSLDFLAGS) -o nt_info nt_info@obj@ @LIBS@
+
+nt_info@obj@: nt_info.c
+ $(CC) -c -o nt_info@obj@ $(CFLAGS) nt_info.c
diff --git a/erts/test/nt_SUITE_data/nt_info.c b/erts/test/nt_SUITE_data/nt_info.c
new file mode 100644
index 0000000000..33cf046bb6
--- /dev/null
+++ b/erts/test/nt_SUITE_data/nt_info.c
@@ -0,0 +1,176 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 1998-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%
+ */
+/*
+ * This is a simple command that gives some interesting
+ * system information on NT.
+ * It is run as a port program by the nt test suite to find out priorities
+ * of programs etc.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(VXWORKS)
+int nt_info(int argc, char **argv){
+ printf("Hello �lvsj�!\n");
+ return 0;
+}
+#elif !defined(__WIN32__)
+int main(int argc, char **argv){
+ printf("Hello �lvsj�!\n");
+ return 0;
+}
+#else /* Windows NT, here we go... */
+
+#include <windows.h>
+
+
+int erlang_format = 0;
+
+#if 0
+int last_error = 0;
+
+void print_last_error(void){
+ char *mes;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ (last_error) ? last_error : GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &mes,
+ 0,
+ NULL );
+ fprintf(stderr,"Error: %s",mes);
+ LocalFree(mes);
+}
+#endif
+
+typedef BOOL (WINAPI *tEnumProcesses)(DWORD *, DWORD, DWORD *);
+typedef BOOL (WINAPI *tEnumProcessModules)(HANDLE, HMODULE *, DWORD, DWORD *);
+typedef DWORD (WINAPI *tGetModuleBaseName)(HANDLE, HMODULE, char *, DWORD);
+
+static tGetModuleBaseName pGetModuleBaseName = NULL;
+static tEnumProcessModules pEnumProcessModules = NULL;
+static tEnumProcesses pEnumProcesses = NULL;
+
+static BOOL init_fpointers(void){
+ HINSTANCE instance = LoadLibrary("PSAPI.DLL");
+ if(instance == NULL){
+ fprintf(stderr,"Failed to load PSAPI.DLL.\n");
+ return FALSE;
+ }
+ if((pEnumProcesses =
+ (tEnumProcesses) GetProcAddress(instance,"EnumProcesses")) ==
+ NULL){
+ fprintf(stderr,"Failed to find EnumProcesses in DLL.\n");
+ return FALSE;
+ }
+ if((pEnumProcessModules =
+ (tEnumProcessModules) GetProcAddress(instance,"EnumProcessModules")) ==
+ NULL){
+ fprintf(stderr,"Failed to find EnumProcessModules in DLL.\n");
+ return FALSE;
+ }
+ if((pGetModuleBaseName =
+ (tGetModuleBaseName) GetProcAddress(instance,"GetModuleBaseNameA")) ==
+ NULL){
+ fprintf(stderr,"Failed to find GetModuleBaseName in DLL.\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+void one_line(DWORD pid){
+ char pname[MAX_PATH] = "???";
+ HMODULE hmod = NULL;
+ DWORD dummy;
+ DWORD priority = -1;
+ struct {
+ DWORD sym;
+ char *txt;
+ } tab[] = {
+ {HIGH_PRIORITY_CLASS,"high"},
+ {IDLE_PRIORITY_CLASS, "idle"},
+ {NORMAL_PRIORITY_CLASS,"normal"},
+ {REALTIME_PRIORITY_CLASS, "realtime"}
+ };
+ int tabsiz = sizeof(tab)/sizeof(*tab);
+ char *class = "???";
+ int i;
+
+ HANDLE hproc = OpenProcess(PROCESS_QUERY_INFORMATION |
+ PROCESS_VM_READ,
+ FALSE, pid );
+ if(!hproc)
+ goto print;
+ if(!(*pEnumProcessModules)(hproc,&hmod,sizeof(hmod),&dummy))
+ goto print;
+ if(!(*pGetModuleBaseName)(hproc,hmod,pname,sizeof(pname)))
+ goto print;
+ if(!(priority = GetPriorityClass(hproc)))
+ goto print;
+ for(i=0;i<tabsiz;++i)
+ if(tab[i].sym == priority)
+ class = tab[i].txt;
+print:
+ if(erlang_format)
+ printf("{\"%s\", %lu, \"%s\"}%s", pname, pid, class,
+ (erlang_format > 1) ? "" : "\n");
+ else
+ printf("%-32s %8lu %-9s\n", pname, pid, class);
+ if(hproc)
+ CloseHandle(hproc);
+ if(hmod)
+ CloseHandle(hmod);
+}
+
+int do_simple_ps(void){
+ DWORD procs[1024];
+ DWORD num_procs;
+ DWORD needed;
+ int i;
+
+ if(!(*pEnumProcesses)(procs,sizeof(procs),&needed)){
+ fprintf(stderr,"Failed to EnumProcesses\n");
+ return 1;
+ }
+ num_procs = needed / sizeof(DWORD);
+ if(erlang_format > 1)
+ printf("[");
+ for(i=0;i<num_procs;++i){
+ one_line(procs[i]);
+ if(erlang_format > 1 && i < num_procs -1)
+ printf(", ");
+ }
+ if(erlang_format > 1)
+ printf("]. \n");
+ return 0;
+}
+
+int main(int argc, char **argv){
+ if(argc>1 && !strcmp(argv[1],"-e"))
+ erlang_format = 1;
+ else if(argc>1 && !strcmp(argv[1],"-E"))
+ erlang_format = 2;
+ if(!init_fpointers())
+ return 1;
+ return do_simple_ps();
+}
+#endif
diff --git a/erts/test/otp_SUITE.erl b/erts/test/otp_SUITE.erl
new file mode 100644
index 0000000000..c6769743dd
--- /dev/null
+++ b/erts/test/otp_SUITE.erl
@@ -0,0 +1,297 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2000-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(otp_SUITE).
+
+-export([all/1,init_per_suite/1,end_per_suite/1]).
+-export([undefined_functions/1,deprecated_not_in_obsolete/1,
+ obsolete_but_not_deprecated/1,call_to_deprecated/1,
+ call_to_size_1/1,strong_components/1]).
+
+-include("test_server.hrl").
+-import(lists, [filter/2,foldl/3,foreach/2]).
+
+all(suite) ->
+ [undefined_functions,deprecated_not_in_obsolete,
+ obsolete_but_not_deprecated,call_to_deprecated,
+ call_to_size_1,strong_components].
+
+init_per_suite(Config) ->
+ Dog = test_server:timetrap(?t:minutes(10)),
+ Root = code:root_dir(),
+ Server = daily_xref,
+ ?line xref:start(Server),
+ ?line xref:set_default(Server, [{verbose,false},
+ {warnings,false},
+ {builtins,true}]),
+ ?line {ok,_Relname} = xref:add_release(Server, Root, {name,otp}),
+
+ %% If we are running the tests in the source tree, the ERTS application
+ %% is not in the code path. We must add it explicitly.
+ case code:lib_dir(erts) of
+ {error,bad_name} ->
+ Erts = filename:join([code:root_dir(),"erts","preloaded","ebin"]),
+ ?line {ok,_} = xref:add_directory(Server, Erts, []);
+ _ ->
+ ok
+ end,
+
+ ?line ?t:timetrap_cancel(Dog),
+ [{xref_server,Server}|Config].
+
+end_per_suite(Config) ->
+ Server = ?config(xref_server, Config),
+ catch xref:stop(Server),
+ Config.
+
+undefined_functions(Config) when is_list(Config) ->
+ Server = ?config(xref_server, Config),
+
+ %% Exclude calls from generated modules in the SSL application.
+ ExcludeFrom = "SSL-PKIX|PKIX.*|ssl_pkix_oid",
+ ?line UndefS = xref_base:analysis(undefined_function_calls),
+ ?line Q = io_lib:format("Undef = ~s,"
+ "ExcludedFrom = ~p:_/_,"
+ "Undef - Undef | ExcludedFrom",
+ [UndefS,ExcludeFrom]),
+ ?line {ok,Undef0} = xref:q(Server, lists:flatten(Q)),
+ ?line Undef1 = hipe_filter(Undef0),
+ ?line Undef2 = ssl_crypto_filter(Undef1),
+ ?line Undef3 = edoc_filter(Undef2),
+ ?line Undef = eunit_filter(Undef3),
+ ?line Undef = megaco_filter(Undef),
+
+ case Undef of
+ [] -> ok;
+ _ ->
+ foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls undefined ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, Undef),
+ ?line ?t:fail({length(Undef),undefined_functions_in_otp})
+
+ end,
+
+ ok.
+
+hipe_filter(Undef) ->
+ case erlang:system_info(hipe_architecture) of
+ undefined ->
+ filter(fun ({_,{hipe_bifs,_,_}}) -> false;
+ ({_,{hipe,_,_}}) -> false;
+ ({_,{hipe_consttab,_,_}}) -> false;
+ ({_,{hipe_converters,_,_}}) -> false;
+ ({{code,_,_},{Mod,_,_}}) ->
+ not is_hipe_module(Mod);
+ ({{code_server,_,_},{Mod,_,_}}) ->
+ not is_hipe_module(Mod);
+ ({{compile,_,_},{Mod,_,_}}) ->
+ not is_hipe_module(Mod);
+ ({{hipe,_,_},{Mod,_,_}}) ->
+ %% See comment for the next clause.
+ not is_hipe_module(Mod);
+ ({{cerl_to_icode,translate_flags1,2},
+ {hipe_rtl_arch,endianess,0}}) ->
+ false;
+ ({{Caller,_,_},{Callee,_,_}}) ->
+ %% Part of the hipe application is here
+ %% for the sake of Dialyzer. There are many
+ %% undefined calls within the hipe application.
+ not is_hipe_module(Caller) orelse
+ not is_hipe_module(Callee);
+ (_) -> true
+ end, Undef);
+ _Arch ->
+ filter(fun ({{Mod,_,_},{hipe_bifs,write_u64,2}}) ->
+ %% Unavailable except in 64 bit AMD. Ignore it.
+ not is_hipe_module(Mod);
+ (_) -> true
+ end, Undef)
+ end.
+
+is_hipe_module(Mod) ->
+ case atom_to_list(Mod) of
+ "hipe_"++_ -> true;
+ _ -> false
+ end.
+
+ssl_crypto_filter(Undef) ->
+ case {code:lib_dir(crypto),code:lib_dir(ssl)} of
+ {{error,bad_name},{error,bad_name}} ->
+ filter(fun({_,{ssl,_,_}}) -> false;
+ ({_,{crypto,_,_}}) -> false;
+ (_) -> true
+ end, Undef);
+ {_,_} -> Undef
+ end.
+
+edoc_filter(Undef) ->
+ %% Filter away function call that is catched.
+ filter(fun({{edoc_lib,uri_get_http,1},{http,request_sync,2}}) -> false;
+ (_) -> true
+ end, Undef).
+
+eunit_filter(Undef) ->
+ filter(fun({{eunit_test,wrapper_test_exported_,0},
+ {eunit_test,nonexisting_function,0}}) -> false;
+ (_) -> true
+ end, Undef).
+
+megaco_filter(Undef) ->
+ %% Intentional calls to undefined functions.
+ filter(fun({{megaco_compact_text_encoder,encode_action_reply,3},
+ {megaco_compact_text_encoder_v3,encode_action_reply,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_action_request,3},
+ {megaco_compact_text_encoder_v3,encode_action_request,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_action_requests,3},
+ {megaco_compact_text_encoder_v3,encode_action_requests,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_command_request,3},
+ {megaco_compact_text_encoder_v3,encode_command_request,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_message,3},
+ {megaco_compact_text_encoder_v3,encode_message,2}}) -> false;
+ ({{megaco_compact_text_encoder,encode_transaction,3},
+ {megaco_compact_text_encoder_v3,encode_transaction,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_action_reply,3},
+ {megaco_pretty_text_encoder_v3,encode_action_reply,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_action_request,3},
+ {megaco_pretty_text_encoder_v3,encode_action_request,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_action_requests,3},
+ {megaco_pretty_text_encoder_v3,encode_action_requests,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_command_request,3},
+ {megaco_pretty_text_encoder_v3,encode_command_request,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_message,3},
+ {megaco_pretty_text_encoder_v3,encode_message,2}}) -> false;
+ ({{megaco_pretty_text_encoder,encode_transaction,3},
+ {megaco_pretty_text_encoder_v3,encode_transaction,2}}) -> false;
+ (_) -> true
+ end, Undef).
+
+deprecated_not_in_obsolete(Config) when is_list(Config) ->
+ ?line Server = ?config(xref_server, Config),
+ ?line {ok,DeprecatedFunctions} = xref:q(Server, "DF"),
+
+ ?line L = foldl(fun({M,F,A}=MFA, Acc) ->
+ case otp_internal:obsolete(M, F, A) of
+ no -> [MFA|Acc];
+ _ -> Acc
+ end
+ end, [], DeprecatedFunctions),
+ case L of
+ [] -> ok;
+ _ ->
+ io:put_chars("The following functions have -deprecated() attributes,\n"
+ "but are not listed in otp_internal:obsolete/3.\n"),
+ ?line print_mfas(L),
+ ?line ?t:fail({length(L),deprecated_but_not_obsolete})
+ end.
+
+obsolete_but_not_deprecated(Config) when is_list(Config) ->
+ ?line Server = ?config(xref_server, Config),
+ ?line {ok,NotDeprecated} = xref:q(Server, "X - DF"),
+
+ ?line L = foldl(fun({M,F,A}=MFA, Acc) ->
+ case otp_internal:obsolete(M, F, A) of
+ no -> Acc;
+ _ -> [MFA|Acc]
+ end
+ end, [], NotDeprecated),
+
+ case L of
+ [] -> ok;
+ _ ->
+ io:put_chars("The following functions are listed "
+ "in otp_internal:obsolete/3,\n"
+ "but don't have -deprecated() attributes.\n"),
+ ?line print_mfas(L),
+ ?line ?t:fail({length(L),obsolete_but_not_deprecated})
+ end.
+
+
+call_to_deprecated(Config) when is_list(Config) ->
+ Server = ?config(xref_server, Config),
+ ?line {ok,DeprecatedCalls} = xref:q(Server, "strict(E || DF)"),
+ foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls deprecated ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, DeprecatedCalls),
+ {comment,integer_to_list(length(DeprecatedCalls))++" calls to deprecated functions"}.
+
+call_to_size_1(Config) when is_list(Config) ->
+ Server = ?config(xref_server, Config),
+
+ %% Applications that do not call erlang:size/1:
+ Apps = [compiler,debugger,kernel,observer,parsetools,
+ runtime_tools,stdlib,tools,webtool],
+
+ Fs = [{erlang,size,1}],
+
+ Q1 = io_lib:format("E || ~p : Fun", [Fs]),
+ ?line {ok,AllCallsToSize1} = xref:q(Server, lists:flatten(Q1)),
+
+ Q2 = io_lib:format("E | ~p : App || ~p : Fun", [Apps,Fs]),
+ ?line {ok,CallsToSize1} = xref:q(Server, lists:flatten(Q2)),
+
+ case CallsToSize1 of
+ [] ->
+ ok;
+ _ ->
+ io:format("These calls cause an error:~n"),
+ foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls soon to be deprecated ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, CallsToSize1)
+ end,
+
+ %% Enumerate calls to erlang:size/1 from other applications than
+ %% the ones known not to call erlang:size/1:
+ case AllCallsToSize1--CallsToSize1 of
+ [] ->
+ ok;
+ Calls ->
+ io:format("~n~nThese calls do not cause an error (yet):~n"),
+ foreach(fun ({MFA1,MFA2}) ->
+ io:format("~s calls soon to be deprecated ~s",
+ [format_mfa(MFA1),format_mfa(MFA2)])
+ end, Calls)
+ end,
+ case CallsToSize1 of
+ [] ->
+ ok;
+ _ ->
+ ?line ?t:fail({length(CallsToSize1),calls_to_size_1})
+ end.
+
+strong_components(Config) when is_list(Config) ->
+ Server = ?config(xref_server, Config),
+ ?line {ok,Cs} = xref:q(Server, "components AE"),
+ io:format("\n\nStrong components:\n\n~p\n", [Cs]),
+ ok.
+
+%%%
+%%% Common help functions.
+%%%
+
+
+print_mfas([MFA|T]) ->
+ io:format("~s\n", [format_mfa(MFA)]),
+ print_mfas(T);
+print_mfas([]) -> ok.
+
+format_mfa({M,F,A}) ->
+ lists:flatten(io_lib:format("~s:~s/~p", [M,F,A])).
diff --git a/erts/test/run_erl_SUITE.erl b/erts/test/run_erl_SUITE.erl
new file mode 100644
index 0000000000..afff4120d4
--- /dev/null
+++ b/erts/test/run_erl_SUITE.erl
@@ -0,0 +1,270 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2005-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(run_erl_SUITE).
+
+-export([all/1,init_per_testcase/2,fin_per_testcase/2,
+ basic/1,heavy/1,heavier/1,defunct/1]).
+-export([ping_me_back/1]).
+
+-include("test_server.hrl").
+
+init_per_testcase(_Case, Config) ->
+ Dog = ?t:timetrap(?t:minutes(2)),
+ [{watchdog, Dog}|Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(suite) ->
+ [basic,heavy,heavier,defunct].
+
+basic(Config) when is_list(Config) ->
+ case os:type() of
+ {unix,_} -> basic_1(Config);
+ _ -> {skip,"Not Unix"}
+ end.
+
+basic_1(Config) ->
+ ?line {Node,Pipe} = do_run_erl(Config, "basic"),
+
+ ?line ToErl = open_port({spawn,"to_erl "++Pipe}, []),
+ ?line erlang:port_command(ToErl, "halt().\r\n"),
+
+ receive
+ {nodedown,Node} ->
+ ?line io:format("Down: ~p\n", [Node])
+ after 10000 ->
+ ?line ?t:fail()
+ end,
+
+ ok.
+
+heavy(Config) when is_list(Config) ->
+ case os:type() of
+ {unix,_} -> heavy_1(Config);
+ _ -> {skip,"Not Unix"}
+ end.
+
+heavy_1(Config) ->
+ ?line {Node,Pipe} = do_run_erl(Config, "heavy"),
+
+ ?line ToErl = open_port({spawn,"to_erl "++Pipe}, []),
+ IoFormat = "io:format(\"~s\n\", [lists:duplicate(10000, 10)]).\r\n",
+ ?line erlang:port_command(ToErl, IoFormat),
+ ?line erlang:port_command(ToErl, IoFormat),
+ ?line erlang:port_command(ToErl, IoFormat),
+ ?line erlang:port_command(ToErl, "init:stop().\r\n"),
+
+ receive
+ {nodedown,Node} ->
+ ?line io:format("Down: ~p\n", [Node])
+ after 10000 ->
+ ?line ?t:fail()
+ end,
+
+ ?line case count_new_lines(ToErl, 0) of
+ Nls when Nls > 30000 ->
+ ok;
+ Nls ->
+ ?line io:format("new_lines: ~p\n", [Nls]),
+ ?line ?t:fail()
+ end.
+
+
+ping_me_back([Node]) when is_atom(Node) ->
+ net_adm:ping(Node);
+ping_me_back([Node]) ->
+ net_adm:ping(list_to_atom(Node)).
+
+count_new_lines(P, N) ->
+ receive
+ {P,{data,S}} ->
+ count_new_lines(P, count_new_lines_1(S, N))
+ after 0 ->
+ N
+ end.
+
+count_new_lines_1([$\n|T], N) ->
+ count_new_lines_1(T, N+1);
+count_new_lines_1([_|T], N) ->
+ count_new_lines_1(T, N);
+count_new_lines_1([], N) -> N.
+
+heavier(Config) when is_list(Config) ->
+ case os:type() of
+ {unix,_} -> heavier_1(Config);
+ _ -> {skip,"Not Unix"}
+ end.
+
+heavier_1(Config) ->
+ ?line {Node,Pipe} = do_run_erl(Config, "heavier"),
+
+ ?line ToErl = open_port({spawn,"to_erl "++Pipe}, []),
+ io:format("ToErl = ~p\n", [ToErl]),
+ X = 1,
+ Y = 555,
+ Z = 42,
+ ?line random:seed(X, Y, Z),
+ SeedCmd = lists:flatten(io_lib:format("random:seed(~p, ~p, ~p). \r\n",
+ [X,Y,Z])),
+ ?line io:format("~p\n", [SeedCmd]),
+ ?line erlang:port_command(ToErl, SeedCmd),
+
+ Iter = 1000,
+ MaxLen = 2048,
+
+ Random = "f(F), "++
+ "F = fun(F,0) -> ok; "++
+ "(F,N) -> " ++
+ "io:format(\"\\\"~s\\\"~n\","++
+ "[[35|[random:uniform(25)+65 || " ++
+ "_ <- lists:seq(1, "++
+ "random:uniform("++
+ integer_to_list(MaxLen)++
+ "))]]]), "++
+ "F(F,N-1) "++
+ "end,"++
+ "F(F,"++integer_to_list(Iter)++")."++" \r\n",
+
+
+ ?line io:format("~p\n", [Random]),
+ ?line erlang:port_command(ToErl, Random),
+
+ %% Finish.
+
+ ?line erlang:port_command(ToErl, "init:stop().\r\n"),
+ ?line receive_all(Iter, ToErl, MaxLen),
+ receive
+ {nodedown,Node} ->
+ ?line io:format("Down: ~p\n", [Node])
+ after 10000 ->
+ ?line c:flush(),
+ ?line ?t:fail()
+ end,
+
+ ok.
+
+receive_all(Iter, ToErl, MaxLen) ->
+ receive_all_1(Iter, [], ToErl, MaxLen).
+
+receive_all_1(0, _, _, _) -> ok;
+receive_all_1(Iter, Line, ToErl, MaxLen) ->
+ NumChars = random:uniform(MaxLen),
+ Pattern = [random:uniform(25)+65 || _ <- lists:seq(1, NumChars)],
+ receive_all_2(Iter, {NumChars,Pattern}, Line, ToErl, MaxLen).
+
+
+receive_all_2(Iter, {NumChars,Pattern}, Line0, ToErl, MaxLen) ->
+ case receive_match(Line0, {NumChars,Pattern}) of
+ {match,Line} ->
+ %%io:format("Match: ~p\n", [Line]),
+ receive_all_1(Iter-1, Line, ToErl, MaxLen);
+ {nomatch,Line} ->
+ %%io:format("NoMatch: ~p\n", [Line]),
+ receive
+ {ToErl,{data,S}} ->
+ %%io:format("Recv: ~p\n", [S]),
+ receive_all_2(Iter, {NumChars,Pattern}, Line++S, ToErl, MaxLen)
+ after 10000 ->
+ io:format("Timeout waiting for\n~p\ngot\n~p\n",
+ [Pattern, Line]),
+ ?line ?t:fail()
+ end
+ end.
+
+
+receive_match("\"#"++T, {NumChars,Pattern}) when length(T) >= NumChars ->
+ Match = lists:sublist(T, NumChars),
+ io:format("match candidate: ~p\n", [Match]),
+ Match = Pattern,
+ {match,lists:nthtail(NumChars, T)};
+receive_match("\"#"++T, _) ->
+ {nomatch,"\"#"++T};
+receive_match("\""=Line, _) ->
+ {nomatch,Line};
+receive_match([_|T], Tpl) ->
+ receive_match(T, Tpl);
+receive_match(Line, _) ->
+ {nomatch,Line}.
+
+
+defunct(Config) when is_list(Config) ->
+ case os:type() of
+ {unix,_} -> defunct_1(Config);
+ _ -> {skip,"Not Unix"}
+ end.
+
+defunct_1(Config) ->
+ case os:find_executable(perl) of
+ false ->
+ {skip,"No perl found"};
+ Perl ->
+ defunct_2(Config, Perl)
+ end.
+
+defunct_2(Config, Perl) ->
+ ?line Data = ?config(data_dir, Config),
+ ?line RunErlTest = filename:join(Data, "run_erl_test.pl"),
+ ?line Defuncter = filename:join(Data, "defuncter.pl"),
+ ?line Priv = ?config(priv_dir, Config),
+ ?line LogDir = filename:join(Priv, "defunct"),
+ ?line ok = file:make_dir(LogDir),
+ ?line Pipe = LogDir ++ "/",
+ ?line RunErl = os:find_executable(run_erl),
+ ?line Cmd = Perl ++ " " ++ RunErlTest ++ " " ++ RunErl ++ " " ++
+ Defuncter ++ " " ++ Pipe ++ " " ++ LogDir,
+ ?line io:format("~p", [Cmd]),
+ ?line Res = os:cmd(Cmd),
+ ?line io:format("~p\n", [Res]),
+ "OK"++_ = Res,
+ ok.
+
+%%% Utilities.
+
+do_run_erl(Config, Case) ->
+ ?line Priv = ?config(priv_dir, Config),
+ ?line LogDir = filename:join(Priv, Case),
+ ?line ok = file:make_dir(LogDir),
+ ?line Pipe = LogDir ++ "/",
+ ?line NodeName = "run_erl_node_" ++ Case,
+ ?line Cmd = "run_erl "++Pipe++" "++LogDir++" \"erl -sname " ++ NodeName ++
+ " -pa " ++ filename:dirname(code:which(?MODULE)) ++
+ " -s " ++ ?MODULE_STRING ++ " ping_me_back " ++
+ atom_to_list(node()) ++ "\"",
+ ?line io:format("~p\n", [Cmd]),
+
+ ?line net_kernel:monitor_nodes(true),
+ ?line open_port({spawn,Cmd}, []),
+ ?line [_,Host] = string:tokens(atom_to_list(node()), "@"),
+ ?line Node = list_to_atom(NodeName++"@"++Host),
+
+ receive
+ {nodeup,Node} ->
+ ?line io:format("Up: ~p\n", [Node]);
+ Other ->
+ ?line io:format("Unexpected: ~p\n", [Other]),
+ ?line ?t:fail()
+ after 10000 ->
+ ?line ?t:fail()
+ end,
+
+ {Node,Pipe}.
diff --git a/erts/test/run_erl_SUITE_data/defuncter.pl b/erts/test/run_erl_SUITE_data/defuncter.pl
new file mode 100644
index 0000000000..261f1b8061
--- /dev/null
+++ b/erts/test/run_erl_SUITE_data/defuncter.pl
@@ -0,0 +1,31 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2006-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%
+#
+
+$SIG{HUP} = 'IGNORE';
+if (fork() == 0) {
+ print "child\n";
+ my $i = 0;
+ for (;;) {
+ sleep(5);
+ print $i++, "\n";
+ }
+} else {
+ print "hejsan\n";
+ exit(1);
+}
diff --git a/erts/test/run_erl_SUITE_data/run_erl_test.pl b/erts/test/run_erl_SUITE_data/run_erl_test.pl
new file mode 100644
index 0000000000..2155225e7f
--- /dev/null
+++ b/erts/test/run_erl_SUITE_data/run_erl_test.pl
@@ -0,0 +1,41 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 2006-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%
+#
+
+my $run_erl = shift;
+my $defuncter = shift;
+my $pipe = shift;
+my $log_dir = shift;
+my $cmd = "run_erl $pipe $log_dir \"$^X $defuncter\"";
+my $pid;
+
+if (($pid = fork()) == 0) {
+ #print join(" ", $run_erl, $pipe, $log_dir, "$^X $defuncter");
+ exec($run_erl, $pipe, $log_dir, "$^X $defuncter");
+ die "ERROR: exec failed: $!\n";
+} elsif ($pid > 0) {
+ sleep(1);
+ my $res = waitpid($pid, 0);
+ if ($res == $pid) {
+ print "OK\n";
+ exit(0);
+ }
+ die "ERROR: waitpid($pid, 0) returned $res\n";
+} else {
+ die "ERROR: fork() failed: $!\n";
+}
diff --git a/erts/test/system.dynspec b/erts/test/system.dynspec
new file mode 100644
index 0000000000..799fd7611d
--- /dev/null
+++ b/erts/test/system.dynspec
@@ -0,0 +1,18 @@
+%% -*- erlang -*-
+%% You can test this file using this command.
+%% file:script("system.dynspec", [{'TestCCompiler',{msc | gnuc, undefined}}]).
+
+case {TestCCompiler, erlang:system_info(c_compiler_used)} of
+ {{CC, _}, {CC, _}} ->
+ [];
+ {{CC1, _}, {CC2, _}} when CC1 == msc; CC2 == msc ->
+ Comment =
+ "OTP's static C libraries (compiled with "
+ ++ atom_to_list(CC2) ++ ") aren't compatible "
+ "with the C compiler (" ++ atom_to_list(CC1)
+ ++ ") used for testing.",
+ StaticLibSuites = [ethread_SUITE, erl_print_SUITE],
+ lists:map(fun (Suite) -> {skip,{Suite, Comment}} end, StaticLibSuites);
+ {{CC1, _}, {CC2, _}} ->
+ []
+end.
diff --git a/erts/test/system.spec b/erts/test/system.spec
new file mode 100644
index 0000000000..9bfe2dbcf8
--- /dev/null
+++ b/erts/test/system.spec
@@ -0,0 +1 @@
+{topcase, {dir, "../system_test"}}.
diff --git a/erts/test/system.spec.vxworks b/erts/test/system.spec.vxworks
new file mode 100644
index 0000000000..378adf56ac
--- /dev/null
+++ b/erts/test/system.spec.vxworks
@@ -0,0 +1,2 @@
+{topcase, {dir, "../system_test"}}.
+{skip,{erlc_SUITE, "Not on VxWorks, erlc is a HOST tool."}}
diff --git a/erts/test/utils/gccifier.c b/erts/test/utils/gccifier.c
new file mode 100644
index 0000000000..64de764260
--- /dev/null
+++ b/erts/test/utils/gccifier.c
@@ -0,0 +1,316 @@
+/*
+ * %CopyrightBegin%
+ *
+ * Copyright Ericsson AB 2004-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%
+ *
+ */
+
+/*
+ * A compiler wrapper that translate (some) gcc command line arguments
+ * to the Visual C++ compiler and (of course) the gcc compiler. It also
+ * makes some changes in the command line arguments when debug compiling.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+
+#if !defined(__WIN32__)
+#define USE_EXEC
+#include <unistd.h>
+#endif
+
+
+#ifdef __WIN32__
+#define EOL "\r\n"
+#else
+#define EOL "\n"
+#endif
+
+#define ARGS_INCR 20
+
+static char *prog;
+
+typedef struct {
+ char **vec;
+ int no;
+ int ix;
+ int chars;
+} args_t;
+
+static void
+enomem(void)
+{
+ fprintf(stderr, "%s: Out of memory%s", prog, EOL);
+ exit(1);
+}
+
+static void
+save_arg(args_t *args, char *arg1, ...)
+{
+ char *carg;
+ va_list argp;
+
+ va_start(argp, arg1);
+ carg = arg1;
+ while (carg) {
+ if (args->no <= args->ix) {
+ args->vec = (char **) (args->no
+ ? realloc((void *) args->vec,
+ (sizeof(char *)
+ *(args->no + ARGS_INCR + 1)))
+ : malloc((sizeof(char *)
+ *(args->no + ARGS_INCR + 1))));
+ if (!args->vec)
+ enomem();
+ args->no += ARGS_INCR;
+ }
+ args->vec[args->ix++] = carg;
+ args->chars += strlen(carg);
+ carg = va_arg(argp, char *);
+ }
+ args->vec[args->ix++] = " ";
+ args->chars++;
+ va_end(argp);
+}
+
+static int
+is_prefix(char *prfx, char **str)
+{
+ int i;
+ for (i = 0; prfx[i] && (*str)[i]; i++) {
+ if (prfx[i] != (*str)[i])
+ return 0;
+ }
+ if (!prfx[i]) {
+ *str = &(*str)[i];
+ return 1;
+ }
+ return 0;
+}
+
+static void
+cpy(char **dst, char *src)
+{
+ int i;
+ for (i = 0; src[i]; i++)
+ (*dst)[i] = src[i];
+ *dst = &(*dst)[i];
+}
+
+typedef enum {
+ STDLIB_NONE,
+ STDLIB_MD,
+ STDLIB_ML,
+ STDLIB_MT
+} stdlib_t;
+
+int
+main(int argc, char *argv[])
+{
+ int res;
+ int i;
+ size_t cmd_len;
+ char *cmd;
+ char *cmd_end;
+ char *cc = NULL;
+ args_t args = {0};
+ int is_debug = 0;
+ int is_purify = 0;
+ int is_quantify = 0;
+ int is_purecov = 0;
+#ifdef __WIN32__
+ int is_shared = 0;
+ stdlib_t stdlib = STDLIB_NONE;
+ char *shared_flag = "";
+ char *stdlib_flag = "";
+ int have_link_args = 0;
+ args_t link_args = {0};
+
+#define CHECK_FIRST_LINK_ARG \
+ if (!have_link_args) { \
+ save_arg(&link_args, "-link", NULL); \
+ have_link_args = 1; \
+ }
+#else /* #ifdef __WIN32__ */
+#define CHECK_FIRST_LINK_ARG
+#endif /* #ifdef __WIN32__ */
+
+ prog = argv[0];
+
+
+ for (i = 1; i < argc; i++) {
+ char *arg = argv[i];
+ if (is_prefix("-CC", &arg)) {
+ cc = arg;
+ }
+ else if (is_prefix("-O", &arg)) {
+ if (!is_debug)
+ save_arg(&args, argv[i], NULL);
+ }
+ else if (strcmp("-DDEBUG", arg) == 0) {
+ save_arg(&args, arg, NULL);
+#ifdef __WIN32__
+ set_debug:
+#endif
+ if (!is_debug) {
+ int j;
+ is_debug = 1;
+#ifdef __WIN32__
+ save_arg(&args, "-Z7", NULL);
+ CHECK_FIRST_LINK_ARG;
+ save_arg(&link_args, "-debug", NULL);
+ save_arg(&link_args, "-pdb:none", NULL);
+#endif
+ for (j = 0; j < args.ix; j++) {
+ char *tmp_arg = args.vec[j];
+ if (is_prefix("-O", &tmp_arg))
+ args.vec[j] = "";
+ }
+ }
+ }
+ else if (strcmp("-DPURIFY", arg) == 0) {
+ save_arg(&args, arg, NULL);
+ is_purify = 1;
+ }
+ else if (strcmp("-DQUANTIFY", arg) == 0) {
+ save_arg(&args, arg, NULL);
+ is_quantify = 1;
+ }
+ else if (strcmp("-DPURECOV", arg) == 0) {
+ save_arg(&args, arg, NULL);
+ is_purecov = 1;
+ }
+#ifdef __WIN32__
+ else if (strcmp("-g", arg) == 0) {
+ goto set_debug;
+ }
+ else if (strcmp("-MD", arg) == 0)
+ stdlib = STDLIB_MD;
+ else if (strcmp("-MDd", arg) == 0) {
+ stdlib = STDLIB_MD;
+ goto set_debug;
+ }
+ else if (strcmp("-ML", arg) == 0)
+ stdlib = STDLIB_ML;
+ else if (strcmp("-MLd", arg) == 0) {
+ stdlib = STDLIB_ML;
+ goto set_debug;
+ }
+ else if (strcmp("-MT", arg) == 0)
+ stdlib = STDLIB_MT;
+ else if (strcmp("-MTd", arg) == 0) {
+ stdlib = STDLIB_MT;
+ goto set_debug;
+ }
+ else if (strcmp("-shared", arg) == 0 || strcmp("-LD", arg) == 0)
+ is_shared = 1;
+ else if (strcmp("-LDd", arg) == 0) {
+ is_shared = 1;
+ goto set_debug;
+ }
+ else if (strcmp("-Wall", arg) == 0) {
+ save_arg(&args, "-W3", NULL);
+ }
+ else if (is_prefix("-L", &arg)) {
+ CHECK_FIRST_LINK_ARG;
+ save_arg(&link_args, "-libpath:", arg, NULL);
+ }
+#endif /* #ifdef __WIN32__ */
+ else if (is_prefix("-l", &arg)) {
+ CHECK_FIRST_LINK_ARG;
+ if (is_debug && strcmp("ethread", arg) == 0)
+ arg = "ethread.debug";
+ else if (is_purify && strcmp("ethread", arg) == 0)
+ arg = "ethread.purify";
+ else if (is_quantify && strcmp("ethread", arg) == 0)
+ arg = "ethread.quantify";
+ else if (is_purecov && strcmp("ethread", arg) == 0)
+ arg = "ethread.purecov";
+#ifdef __WIN32__
+ else if (strcmp("socket", arg) == 0)
+ arg = "ws2_32";
+ save_arg(&link_args, arg, ".lib", NULL);
+#else
+ save_arg(&args, "-l", arg, NULL);
+#endif
+ }
+ else
+ save_arg(&args, argv[i], NULL);
+ }
+
+ if (!cc || !cc[0]) {
+ fprintf(stderr, "%s: Missing compulsory -CC flag%s", prog, EOL);
+ exit(1);
+ }
+
+ cmd_len = strlen(cc) + 1 + args.chars + 1;
+
+#ifdef __WIN32__
+ if (is_shared)
+ shared_flag = is_debug ? "-LDd " : "-LD ";
+ switch (stdlib) {
+ case STDLIB_MD: stdlib_flag = is_debug ? "-MDd " : "-MD "; break;
+ case STDLIB_ML: stdlib_flag = is_debug ? "-MLd " : "-ML "; break;
+ case STDLIB_MT: stdlib_flag = is_debug ? "-MTd " : "-MT "; break;
+ case STDLIB_NONE: break;
+ }
+
+ cmd_len += strlen(shared_flag) + strlen(stdlib_flag) + link_args.chars;
+#endif
+
+ cmd = (char *) malloc(sizeof(char) * cmd_len);
+
+ if (!cmd)
+ enomem();
+ cmd_end = cmd;
+ cpy(&cmd_end, cc);
+ cpy(&cmd_end, " ");
+#ifdef __WIN32__
+ cpy(&cmd_end, stdlib_flag);
+ cpy(&cmd_end, shared_flag);
+#endif
+ for (i = 0; i < args.ix; i++)
+ cpy(&cmd_end, args.vec[i]);
+#ifdef __WIN32__
+ for (i = 0; i < link_args.ix; i++)
+ cpy(&cmd_end, link_args.vec[i]);
+#endif
+ *cmd_end = '\0';
+
+ printf("==> %s%s", cmd, EOL);
+ fflush(stdout);
+
+#ifdef USE_EXEC
+ (void) execl("/bin/sh", "sh", "-c", cmd, (char *) NULL);
+ perror(NULL);
+ res = 1;
+#else
+ res = system(cmd);
+#endif
+
+ free((void *) args.vec);
+#ifdef __WIN32__
+ free((void *) link_args.vec);
+#endif
+ free((void *) cmd);
+
+ if (res < 0)
+ res = 1;
+ return res;
+}
diff --git a/erts/test/z_SUITE.erl b/erts/test/z_SUITE.erl
new file mode 100644
index 0000000000..0e37af1ca2
--- /dev/null
+++ b/erts/test/z_SUITE.erl
@@ -0,0 +1,315 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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(z_SUITE).
+
+%%
+%% This suite expects to be run as the last suite of all suites.
+%%
+
+%-define(line_trace, 1).
+
+-include_lib("kernel/include/file.hrl").
+
+-record(core_search_conf, {search_dir,
+ extra_search_dir,
+ cerl,
+ file,
+ run_by_ts}).
+
+-define(DEFAULT_TIMEOUT, ?t:minutes(5)).
+
+-export([all/1, init_per_testcase/2, fin_per_testcase/2]).
+
+-export([search_for_core_files/1, core_files/1]).
+
+-include("test_server.hrl").
+
+
+init_per_testcase(Case, Config) ->
+ Dog = ?t:timetrap(?DEFAULT_TIMEOUT),
+ [{testcase, Case}, {watchdog, Dog} |Config].
+
+fin_per_testcase(_Case, Config) ->
+ Dog = ?config(watchdog, Config),
+ ?t:timetrap_cancel(Dog),
+ ok.
+
+all(doc) -> [];
+all(suite) ->
+ [core_files].
+
+
+core_files(doc) ->
+ [];
+core_files(suite) ->
+ [];
+core_files(Config) when is_list(Config) ->
+ case os:type() of
+ {win32, _} ->
+ {skipped, "No idea searching for core-files on windows"};
+ {unix, darwin} ->
+ core_file_search(
+ core_search_conf(true,
+ os:getenv("OTP_DAILY_BUILD_TOP_DIR"),
+ "/cores"));
+ _ ->
+ core_file_search(
+ core_search_conf(true,
+ os:getenv("OTP_DAILY_BUILD_TOP_DIR")))
+ end.
+
+search_for_core_files(Dir) ->
+ case os:type() of
+ {win32, _} ->
+ io:format("No idea searching for core-files on windows");
+ {unix, darwin} ->
+ core_file_search(core_search_conf(false, Dir, "/cores"));
+ _ ->
+ core_file_search(core_search_conf(false, Dir))
+ end.
+
+find_cerl(false) ->
+ case os:getenv("ERL_TOP") of
+ false -> false;
+ ETop ->
+ Cerl = filename:join([ETop, "bin", "cerl"]),
+ case filelib:is_regular(Cerl) of
+ true -> Cerl;
+ _ -> false
+ end
+ end;
+find_cerl(DBTop) ->
+ case catch filelib:wildcard(filename:join([DBTop,
+ "otp_src_R*",
+ "bin",
+ "cerl"])) of
+ [Cerl | _ ] ->
+ case filelib:is_regular(Cerl) of
+ true -> Cerl;
+ _ -> false
+ end;
+ _ ->
+ false
+ end.
+
+is_dir(false) ->
+ false;
+is_dir(Dir) ->
+ filelib:is_dir(Dir).
+
+core_search_conf(RunByTS, DBTop) ->
+ core_search_conf(RunByTS, DBTop, false).
+
+core_search_conf(RunByTS, DBTop, XDir) ->
+ SearchDir = case is_dir(DBTop) of
+ false ->
+ case code:which(test_server) of
+ non_existing ->
+ {ok, CWD} = file:get_cwd(),
+ CWD;
+ TS ->
+ filename:dirname(filename:dirname(TS))
+ end;
+ true ->
+ DBTop
+ end,
+ XSearchDir = case is_dir(XDir) of
+ false ->
+ false;
+ true ->
+ case SearchDir == XDir of
+ true -> false;
+ _ -> XDir
+ end
+ end,
+ #core_search_conf{search_dir = SearchDir,
+ extra_search_dir = XSearchDir,
+ cerl = find_cerl(DBTop),
+ file = os:find_executable("file"),
+ run_by_ts = RunByTS}.
+
+file_inspect(#core_search_conf{file = File}, Core) ->
+ FRes0 = os:cmd(File ++ " " ++ Core),
+ FRes = case regexp:match(FRes0, Core) of
+ {match, S, E} ->
+ L = length(FRes0),
+ case S of
+ 1 ->
+ lists:sublist(FRes0, E+1, L+1);
+ _ ->
+ lists:sublist(FRes0, 1, S-1)
+ ++
+ " "
+ ++
+ lists:sublist(FRes0, E+1, L+1)
+ end;
+ _ -> FRes0
+ end,
+ case regexp:match(FRes, "[Tt][Ee][Xx][Tt]") of
+ nomatch ->
+ case regexp:match(FRes, "[Aa][Ss][Cc][Ii][Ii]") of
+ nomatch ->
+ probably_a_core;
+ _ ->
+ not_a_core
+ end;
+ _ ->
+ not_a_core
+ end.
+
+mk_readable(F) ->
+ catch file:write_file_info(F, #file_info{mode = 8#00444}).
+
+ignore_core(C) ->
+ filelib:is_regular(filename:join([filename:dirname(C),
+ "ignore_core_files"])).
+
+core_cand(#core_search_conf{file = false}, C, Cs) ->
+ %% Guess that it is a core file; make it readable by anyone and save it
+ mk_readable(C),
+ [C|Cs];
+core_cand(Conf, C, Cs) ->
+ case file_inspect(Conf, C) of
+ not_a_core -> Cs;
+ _ ->
+ %% Probably a core file; make it readable by anyone and save it
+ mk_readable(C),
+ case ignore_core(C) of
+ true -> [{ignore, C}|Cs];
+ _ -> [C|Cs]
+ end
+ end.
+
+time_fstr() ->
+ "(~w-~.2.0w-~.2.0w ~w.~.2.0w:~.2.0w)".
+mod_time_list(F) ->
+ case catch filelib:last_modified(F) of
+ {{Y,Mo,D},{H,Mi,S}} ->
+ [Y,Mo,D,H,Mi,S];
+ _ ->
+ [0,0,0,0,0,0]
+ end.
+
+str_strip(S) ->
+ string:strip(string:strip(string:strip(S), both, $\n), both, $\r).
+
+format_core(Conf, {ignore, Core}) ->
+ format_core(Conf, Core, "[ignored] ");
+format_core(Conf, Core) ->
+ format_core(Conf, Core, "").
+
+format_core(#core_search_conf{file = false}, Core, Ignore) ->
+ io:format(" ~s~s " ++ time_fstr() ++ "~s~n",
+ [Ignore, Core] ++ mod_time_list(Core));
+format_core(#core_search_conf{file = File}, Core, Ignore) ->
+ FRes = str_strip(os:cmd(File ++ " " ++ Core)),
+ case catch regexp:match(FRes, Core) of
+ {match, _, _} ->
+ io:format(" ~s~s " ++ time_fstr() ++ "~n",
+ [Ignore, FRes] ++ mod_time_list(Core));
+ _ ->
+ io:format(" ~s~s: ~s " ++ time_fstr() ++ "~n",
+ [Ignore, Core, FRes] ++ mod_time_list(Core))
+ end.
+
+core_file_search(#core_search_conf{search_dir = Base,
+ extra_search_dir = XBase,
+ cerl = Cerl,
+ run_by_ts = RunByTS} = Conf) ->
+ case Cerl of
+ false -> ok;
+ _ -> catch io:format("A cerl script that probably can be used for "
+ "inspection of emulator cores:~n ~s~n",
+ [Cerl])
+ end,
+ io:format("Searching for core-files in: ~s~s~n",
+ [case XBase of
+ false -> "";
+ _ -> XBase ++ " and "
+ end,
+ Base]),
+ Filter = fun (Core, Cores) ->
+ case filelib:is_regular(Core) of
+ true ->
+ case filename:basename(Core) of
+ "core" ->
+ core_cand(Conf, Core, Cores);
+ "core." ++ _ ->
+ core_cand(Conf, Core, Cores);
+ BName ->
+ case lists:suffix(".core", BName) of
+ true -> core_cand(Conf, Core, Cores);
+ _ -> Cores
+ end
+ end;
+ _ ->
+ Cores
+ end
+ end,
+ case case XBase of
+ false -> [];
+ _ -> filelib:fold_files(XBase, "core", true, Filter, [])
+ end ++ filelib:fold_files(Base, "core", true, Filter, []) of
+ [] ->
+ io:format("No core-files found.~n", []),
+ ok;
+ Cores ->
+ io:format("Found core files:~n",[]),
+ lists:foreach(fun (C) -> format_core(Conf, C) end, Cores),
+ {ICores, FCores} = lists:foldl(fun ({ignore, IC}, {ICs, FCs}) ->
+ {[" "++IC|ICs], FCs};
+ (FC, {ICs, FCs}) ->
+ {ICs, [" "++FC|FCs]}
+ end,
+ {[],[]},
+ Cores),
+ ICoresComment =
+ "Core-files marked with [ignored] were found in directories~n"
+ "containing an ignore_core_files file, i.e., the testcase~n"
+ "writer has decided that core-files dumped there should be~n"
+ "ignored. This testcase won't fail on ignored core-files~n"
+ "found.~n",
+ Res = lists:flatten([case FCores of
+ [] ->
+ [];
+ _ ->
+ ["Core-files found:",
+ lists:reverse(FCores)]
+ end,
+ case {FCores, ICores} of
+ {[], []} -> [];
+ {_, []} -> [];
+ {[], _} -> [];
+ _ -> " "
+ end,
+ case ICores of
+ [] -> [];
+ _ ->
+ io:format(ICoresComment, []),
+ ["Ignored core-files found:",
+ lists:reverse(ICores)]
+ end]),
+ case {RunByTS, ICores, FCores} of
+ {true, [], []} -> ok;
+ {true, _, []} -> {comment, Res};
+ {true, _, _} -> ?t:fail(Res);
+ _ -> Res
+ end
+ end.